Skip to content

Commit 558e822

Browse files
author
Automation
committed
Fix status-board.php data display and projects.php issue counts
- Fixed status-board.php to correctly parse API response data structure - Updated getGHDash.php to use gh_issue_project_status table for accurate project filtering - Modified getProjects.php to show correct issue counts (19 for SYNECA ROADMAP, 13 for UNASSIGNED) - Cleaned up all test files - Improved project board status integration across the application
1 parent 40a4c65 commit 558e822

11 files changed

Lines changed: 185 additions & 47 deletions

api/getGHIssues.php

Lines changed: 47 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,17 @@ function insertIssueIntoDatabase($pdo, $issue, $projectData = null) {
5050
$gh_id = $issue['number'] ?? 0;
5151
$gh_node_id = $issue['node_id'] ?? '';
5252
$gh_id_url = $issue['html_url'] ?? '';
53-
$repo = $issue['repository']['name'] ?? '';
54-
$repo_url = $issue['repository']['html_url'] ?? '';
53+
54+
// Extract repository name from repository_url (for search API response)
55+
$repo = '';
56+
$repo_url = '';
57+
if (isset($issue['repository_url'])) {
58+
$repo_url = $issue['repository_url'];
59+
$repo = basename($repo_url);
60+
} elseif (isset($issue['repository']['name'])) {
61+
$repo = $issue['repository']['name'];
62+
$repo_url = $issue['repository']['html_url'] ?? '';
63+
}
5564
$issue_text = $issue['title'] ?? '';
5665
$client = '';
5766
$assigned_date = isset($issue['created_at']) ? date('Y-m-d', strtotime($issue['created_at'])) : date('Y-m-d');
@@ -71,19 +80,39 @@ function insertIssueIntoDatabase($pdo, $issue, $projectData = null) {
7180
$gh_project_title = '';
7281
}
7382

74-
// Insert issue into database
83+
// Set project URL
84+
$gh_project_url = $projectData && is_array($projectData) ? ($projectData['url'] ?? '') : '';
85+
86+
// Insert issue into database with ON DUPLICATE KEY UPDATE
7587
$stmt = $pdo->prepare(
7688
"INSERT INTO gh_issues (gh_id, gh_node_id, gh_id_url, repo, repo_url, gh_project_url, issue_text, client, assigned_date, target_date,
7789
gh_json, assignee, gh_project, gh_project_title, last_updated_at, closed_at, gh_state) VALUES
78-
(:gh_id, :gh_node_id, :gh_id_url, :repo, :repo_url, :gh_project_url, :issue_text, :client, :assigned_date, :target_date, :gh_json, :assignee, :gh_project, :gh_project_title, :updated_at, :closed_at, :gh_state)"
90+
(:gh_id, :gh_node_id, :gh_id_url, :repo, :repo_url, :gh_project_url, :issue_text, :client, :assigned_date, :target_date, :gh_json, :assignee, :gh_project, :gh_project_title, :updated_at, :closed_at, :gh_state)
91+
ON DUPLICATE KEY UPDATE
92+
gh_id = VALUES(gh_id),
93+
gh_id_url = VALUES(gh_id_url),
94+
repo = VALUES(repo),
95+
repo_url = VALUES(repo_url),
96+
gh_project_url = VALUES(gh_project_url),
97+
issue_text = VALUES(issue_text),
98+
client = VALUES(client),
99+
assigned_date = VALUES(assigned_date),
100+
target_date = VALUES(target_date),
101+
gh_json = VALUES(gh_json),
102+
assignee = VALUES(assignee),
103+
gh_project = VALUES(gh_project),
104+
gh_project_title = VALUES(gh_project_title),
105+
last_updated_at = VALUES(last_updated_at),
106+
closed_at = VALUES(closed_at),
107+
gh_state = VALUES(gh_state)"
79108
);
80109

81110
$stmt->bindParam(':gh_id', $gh_id);
82111
$stmt->bindParam(':gh_node_id', $gh_node_id);
83112
$stmt->bindParam(':gh_id_url', $gh_id_url);
84113
$stmt->bindParam(':repo', $repo);
85114
$stmt->bindParam(':repo_url', $repo_url);
86-
$stmt->bindParam(':gh_project_url', '');
115+
$stmt->bindParam(':gh_project_url', $gh_project_url);
87116
$stmt->bindParam(':issue_text', $issue_text);
88117
$stmt->bindParam(':client', $client);
89118
$stmt->bindParam(':assigned_date', $assigned_date);
@@ -98,7 +127,7 @@ function insertIssueIntoDatabase($pdo, $issue, $projectData = null) {
98127

99128
try {
100129
$stmt->execute();
101-
write_log("Inserted issue #{$gh_id}: {$issue_text} - Project: {$gh_project_title}");
130+
write_log("Inserted/Updated issue #{$gh_id}: {$issue_text} - Project: {$gh_project_title}");
102131
} catch (PDOException $e) {
103132
write_log("Database Error inserting issue #{$gh_id}: " . $e->getMessage());
104133
return;
@@ -111,7 +140,7 @@ function insertIssueIntoDatabase($pdo, $issue, $projectData = null) {
111140
if (is_array($label) && isset($label['name']) && isset($label['color'])) {
112141
$tag = $label['name'];
113142
$color = $label['color'];
114-
$stmt = $pdo->prepare("INSERT INTO gh_issue_tags (gh_node_id, tag, color) VALUES (:gh_node_id, :tag, :color)");
143+
$stmt = $pdo->prepare("INSERT INTO gh_issue_tags (gh_node_id, tag, color) VALUES (:gh_node_id, :tag, :color) ON DUPLICATE KEY UPDATE color = VALUES(color)");
115144
$stmt->bindParam(':gh_node_id', $gh_node_id);
116145
$stmt->bindParam(':tag', $tag);
117146
$stmt->bindParam(':color', $color);
@@ -134,7 +163,8 @@ function fetchAllIssuesWithProjects($githubOrg, $githubToken, $appName) {
134163
write_log("Starting to fetch issues from GitHub API...");
135164

136165
while (true) {
137-
$apiUrl = "https://api.github.com/orgs/{$githubOrg}/issues?filter=all&state=open&per_page={$perPage}&page={$page}";
166+
// Use the correct GitHub API endpoint for organization issues
167+
$apiUrl = "https://api.github.com/search/issues?q=org:{$githubOrg}+is:issue+is:open&per_page={$perPage}&page={$page}";
138168

139169
$curl = curl_init();
140170
curl_setopt($curl, CURLOPT_URL, $apiUrl);
@@ -150,26 +180,31 @@ function fetchAllIssuesWithProjects($githubOrg, $githubToken, $appName) {
150180
curl_close($curl);
151181

152182
if ($httpCode !== 200) {
153-
write_log("GitHub API error: HTTP {$httpCode} for page {$page}");
183+
write_log("GitHub API error: HTTP {$httpCode} for page {$page}. Response: " . substr($response, 0, 200));
154184
break;
155185
}
156186

157-
$issues = json_decode($response, true);
187+
$data = json_decode($response, true);
158188

159-
if (empty($issues)) {
189+
if (!isset($data['items']) || empty($data['items'])) {
160190
write_log("No more issues found on page {$page}");
161191
break;
162192
}
163193

194+
$issues = $data['items'];
164195
write_log("Fetched " . count($issues) . " issues from page {$page}");
165196

166197
foreach ($issues as $issue) {
167198
if (isset($issue['pull_request'])) {
168199
continue; // Skip pull requests
169200
}
170201

202+
// Extract repository name from the issue URL
203+
$repoUrl = $issue['repository_url'];
204+
$repoName = basename($repoUrl);
205+
171206
// For each issue, fetch its project assignments
172-
$projectData = fetchIssueProjects($githubOrg, $githubToken, $appName, $issue['repository']['name'], $issue['number']);
207+
$projectData = fetchIssueProjects($githubOrg, $githubToken, $appName, $repoName, $issue['number']);
173208
$issue['project_data'] = $projectData;
174209
$allIssues[] = $issue;
175210
}

api/utilities_project.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,21 @@
55
//require '../vendor/autoload.php'; // Include Guzzle library
66
require_once(__DIR__ . '/../config/app.php');
77

8+
// Define write_log function if not already defined
9+
if (!function_exists('write_log')) {
10+
function write_log($message) {
11+
$timestamp = date('Y-m-d H:i:s');
12+
$logMessage = "[{$timestamp}] {$message}" . PHP_EOL;
13+
14+
// Try to write to log file, but don't fail if we can't
15+
try {
16+
@file_put_contents(__DIR__ . '/../config/app.log', $logMessage, FILE_APPEND);
17+
} catch (Exception $e) {
18+
// Silently fail if we can't write to log file
19+
}
20+
}
21+
}
22+
823

924

1025
function insertAuditData($pdo, $action, $startTime, $endTime) {

config/app.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,12 @@ function logError($message, $type = 'ERROR', $context = []) {
2626
$logMessage .= " | Context: " . json_encode($context);
2727
}
2828

29-
file_put_contents(__DIR__ . '/app.log', $logMessage . PHP_EOL, FILE_APPEND);
29+
// Try to write to log file, but don't fail if we can't
30+
try {
31+
@file_put_contents(__DIR__ . '/app.log', $logMessage . PHP_EOL, FILE_APPEND);
32+
} catch (Exception $e) {
33+
// Silently fail if we can't write to log file
34+
}
3035
}
3136

3237
// Custom success logging function

config/database.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
<?php
2+
// Include app.php for logging functions
3+
require_once __DIR__ . '/app.php';
4+
25
/*
36
session_start();
47
if(!checkUserSession($_SESSION["user"]))

docker-compose.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ services:
1616
DB_NAME: project_management
1717
DB_USER: github_smart_user
1818
DB_PASSWORD: github_smart_password
19-
GITHUB_TOKEN: ${GITHUB_TOKEN:-}
19+
GITHUB_TOKEN: ${GITHUB_TOKEN:-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}
20+
GITHUB_ORG: ${GITHUB_ORG:-Syneca}
2021
ports:
2122
- "8081:8080"
2223
volumes:

docker/entrypoint.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ DB_ORANGEHRM=${DB_ORANGEHRM:-orange}
2222
2323
# GitHub API
2424
GITHUB_TOKEN=${GITHUB_TOKEN:-}
25+
GITHUB_ORG=${GITHUB_ORG:-Syneca}
2526
2627
# Debugger flag used by legacy code
2728
DEBUGGER=${DEBUGGER:-no}

public/api/getGHDash.php

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -133,21 +133,33 @@ function handleLatestIssues($pdo) {
133133

134134
function handleIssuesByProject($pdo) {
135135
$project = validateInput($_GET['projectId'] ?? '', 'string');
136-
$query = "SELECT * FROM gh_issues WHERE 1=1";
137136

138137
if ($project) {
139138
if ($project === "UNASSIGNED") {
140-
$query .= " AND (gh_project IS NULL OR gh_project = '')";
139+
// Get issues that are NOT in any project board
140+
$query = "
141+
SELECT i.*
142+
FROM gh_issues i
143+
WHERE i.gh_node_id NOT IN (SELECT DISTINCT gh_node_id FROM gh_issue_project_status)
144+
ORDER BY i.assigned_date DESC
145+
";
146+
$stmt = $pdo->prepare($query);
141147
} else {
142-
$query .= " AND gh_project = :project";
148+
// Get issues that are assigned to the specific project board
149+
$query = "
150+
SELECT i.*
151+
FROM gh_issues i
152+
INNER JOIN gh_issue_project_status p ON i.gh_node_id = p.gh_node_id
153+
WHERE p.project_id = :project
154+
ORDER BY i.assigned_date DESC
155+
";
156+
$stmt = $pdo->prepare($query);
157+
$stmt->bindValue(':project', $project, PDO::PARAM_STR);
143158
}
144-
}
145-
146-
$query .= " ORDER BY assigned_date DESC";
147-
$stmt = $pdo->prepare($query);
148-
149-
if ($project && $project !== "UNASSIGNED") {
150-
$stmt->bindValue(':project', $project, PDO::PARAM_STR);
159+
} else {
160+
// If no project specified, return all issues
161+
$query = "SELECT * FROM gh_issues ORDER BY assigned_date DESC";
162+
$stmt = $pdo->prepare($query);
151163
}
152164

153165
$stmt->execute();

public/api/getGHIssues.php

Lines changed: 47 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,17 @@ function insertIssueIntoDatabase($pdo, $issue, $projectData = null) {
5252
$gh_id = $issue['number'] ?? 0;
5353
$gh_node_id = $issue['node_id'] ?? '';
5454
$gh_id_url = $issue['html_url'] ?? '';
55-
$repo = $issue['repository']['name'] ?? '';
56-
$repo_url = $issue['repository']['html_url'] ?? '';
55+
56+
// Extract repository name from repository_url (for search API response)
57+
$repo = '';
58+
$repo_url = '';
59+
if (isset($issue['repository_url'])) {
60+
$repo_url = $issue['repository_url'];
61+
$repo = basename($repo_url);
62+
} elseif (isset($issue['repository']['name'])) {
63+
$repo = $issue['repository']['name'];
64+
$repo_url = $issue['repository']['html_url'] ?? '';
65+
}
5766
$issue_text = $issue['title'] ?? '';
5867
$client = '';
5968
$assigned_date = isset($issue['created_at']) ? date('Y-m-d', strtotime($issue['created_at'])) : date('Y-m-d');
@@ -73,19 +82,39 @@ function insertIssueIntoDatabase($pdo, $issue, $projectData = null) {
7382
$gh_project_title = '';
7483
}
7584

76-
// Insert issue into database
85+
// Set project URL
86+
$gh_project_url = $projectData && is_array($projectData) ? ($projectData['url'] ?? '') : '';
87+
88+
// Insert issue into database with ON DUPLICATE KEY UPDATE
7789
$stmt = $pdo->prepare(
7890
"INSERT INTO gh_issues (gh_id, gh_node_id, gh_id_url, repo, repo_url, gh_project_url, issue_text, client, assigned_date, target_date,
7991
gh_json, assignee, gh_project, gh_project_title, last_updated_at, closed_at, gh_state) VALUES
80-
(:gh_id, :gh_node_id, :gh_id_url, :repo, :repo_url, :gh_project_url, :issue_text, :client, :assigned_date, :target_date, :gh_json, :assignee, :gh_project, :gh_project_title, :updated_at, :closed_at, :gh_state)"
92+
(:gh_id, :gh_node_id, :gh_id_url, :repo, :repo_url, :gh_project_url, :issue_text, :client, :assigned_date, :target_date, :gh_json, :assignee, :gh_project, :gh_project_title, :updated_at, :closed_at, :gh_state)
93+
ON DUPLICATE KEY UPDATE
94+
gh_id = VALUES(gh_id),
95+
gh_id_url = VALUES(gh_id_url),
96+
repo = VALUES(repo),
97+
repo_url = VALUES(repo_url),
98+
gh_project_url = VALUES(gh_project_url),
99+
issue_text = VALUES(issue_text),
100+
client = VALUES(client),
101+
assigned_date = VALUES(assigned_date),
102+
target_date = VALUES(target_date),
103+
gh_json = VALUES(gh_json),
104+
assignee = VALUES(assignee),
105+
gh_project = VALUES(gh_project),
106+
gh_project_title = VALUES(gh_project_title),
107+
last_updated_at = VALUES(last_updated_at),
108+
closed_at = VALUES(closed_at),
109+
gh_state = VALUES(gh_state)"
81110
);
82111

83112
$stmt->bindParam(':gh_id', $gh_id);
84113
$stmt->bindParam(':gh_node_id', $gh_node_id);
85114
$stmt->bindParam(':gh_id_url', $gh_id_url);
86115
$stmt->bindParam(':repo', $repo);
87116
$stmt->bindParam(':repo_url', $repo_url);
88-
$stmt->bindParam(':gh_project_url', '');
117+
$stmt->bindParam(':gh_project_url', $gh_project_url);
89118
$stmt->bindParam(':issue_text', $issue_text);
90119
$stmt->bindParam(':client', $client);
91120
$stmt->bindParam(':assigned_date', $assigned_date);
@@ -100,7 +129,7 @@ function insertIssueIntoDatabase($pdo, $issue, $projectData = null) {
100129

101130
try {
102131
$stmt->execute();
103-
write_log("Inserted issue #{$gh_id}: {$issue_text} - Project: {$gh_project_title}");
132+
write_log("Inserted/Updated issue #{$gh_id}: {$issue_text} - Project: {$gh_project_title}");
104133
} catch (PDOException $e) {
105134
write_log("Database Error inserting issue #{$gh_id}: " . $e->getMessage());
106135
return;
@@ -113,7 +142,7 @@ function insertIssueIntoDatabase($pdo, $issue, $projectData = null) {
113142
if (is_array($label) && isset($label['name']) && isset($label['color'])) {
114143
$tag = $label['name'];
115144
$color = $label['color'];
116-
$stmt = $pdo->prepare("INSERT INTO gh_issue_tags (gh_node_id, tag, color) VALUES (:gh_node_id, :tag, :color)");
145+
$stmt = $pdo->prepare("INSERT INTO gh_issue_tags (gh_node_id, tag, color) VALUES (:gh_node_id, :tag, :color) ON DUPLICATE KEY UPDATE color = VALUES(color)");
117146
$stmt->bindParam(':gh_node_id', $gh_node_id);
118147
$stmt->bindParam(':tag', $tag);
119148
$stmt->bindParam(':color', $color);
@@ -136,7 +165,8 @@ function fetchAllIssuesWithProjects($githubOrg, $githubToken, $appName) {
136165
write_log("Starting to fetch issues from GitHub API...");
137166

138167
while (true) {
139-
$apiUrl = "https://api.github.com/orgs/{$githubOrg}/issues?filter=all&state=open&per_page={$perPage}&page={$page}";
168+
// Use the correct GitHub API endpoint for organization issues
169+
$apiUrl = "https://api.github.com/search/issues?q=org:{$githubOrg}+is:issue+is:open&per_page={$perPage}&page={$page}";
140170

141171
$curl = curl_init();
142172
curl_setopt($curl, CURLOPT_URL, $apiUrl);
@@ -152,26 +182,31 @@ function fetchAllIssuesWithProjects($githubOrg, $githubToken, $appName) {
152182
curl_close($curl);
153183

154184
if ($httpCode !== 200) {
155-
write_log("GitHub API error: HTTP {$httpCode} for page {$page}");
185+
write_log("GitHub API error: HTTP {$httpCode} for page {$page}. Response: " . substr($response, 0, 200));
156186
break;
157187
}
158188

159-
$issues = json_decode($response, true);
189+
$data = json_decode($response, true);
160190

161-
if (empty($issues)) {
191+
if (!isset($data['items']) || empty($data['items'])) {
162192
write_log("No more issues found on page {$page}");
163193
break;
164194
}
165195

196+
$issues = $data['items'];
166197
write_log("Fetched " . count($issues) . " issues from page {$page}");
167198

168199
foreach ($issues as $issue) {
169200
if (isset($issue['pull_request'])) {
170201
continue; // Skip pull requests
171202
}
172203

204+
// Extract repository name from the issue URL
205+
$repoUrl = $issue['repository_url'];
206+
$repoName = basename($repoUrl);
207+
173208
// For each issue, fetch its project assignments
174-
$projectData = fetchIssueProjects($githubOrg, $githubToken, $appName, $issue['repository']['name'], $issue['number']);
209+
$projectData = fetchIssueProjects($githubOrg, $githubToken, $appName, $repoName, $issue['number']);
175210
$issue['project_data'] = $projectData;
176211
$allIssues[] = $issue;
177212
}

0 commit comments

Comments
 (0)