ikinci temizlik tamamlandı
This commit is contained in:
@@ -0,0 +1,302 @@
|
||||
@php
|
||||
/**
|
||||
* @api-readonly
|
||||
* Returns developer project statistics from GitHub
|
||||
*/
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Carbon\Carbon;
|
||||
|
||||
// Configuration
|
||||
$token = env('GITHUB_TOKEN');
|
||||
$org = 'Truncgil-Techology';
|
||||
$projectNumber = 2;
|
||||
|
||||
if (!$token) {
|
||||
echo json_encode(['status' => 'error', 'message' => 'GITHUB_TOKEN not set']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// GraphQL Query to fetch Project V2 items and fields
|
||||
$query = <<<GRAPHQL
|
||||
query {
|
||||
organization(login: "$org") {
|
||||
projectV2(number: $projectNumber) {
|
||||
title
|
||||
items(first: 100) {
|
||||
nodes {
|
||||
fieldValues(first: 20) {
|
||||
nodes {
|
||||
... on ProjectV2ItemFieldSingleSelectValue {
|
||||
name
|
||||
field {
|
||||
... on ProjectV2FieldCommon {
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
... on ProjectV2ItemFieldUserValue {
|
||||
users(first: 5) {
|
||||
nodes {
|
||||
login
|
||||
avatarUrl
|
||||
name
|
||||
}
|
||||
}
|
||||
field {
|
||||
... on ProjectV2FieldCommon {
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
content {
|
||||
... on Issue {
|
||||
title
|
||||
url
|
||||
state
|
||||
number
|
||||
createdAt
|
||||
updatedAt
|
||||
closedAt
|
||||
}
|
||||
... on DraftIssue {
|
||||
title
|
||||
createdAt
|
||||
updatedAt
|
||||
}
|
||||
... on PullRequest {
|
||||
title
|
||||
url
|
||||
state
|
||||
number
|
||||
createdAt
|
||||
updatedAt
|
||||
closedAt
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
GRAPHQL;
|
||||
|
||||
try {
|
||||
$response = Http::withToken($token)->post('https://api.github.com/graphql', [
|
||||
'query' => $query
|
||||
]);
|
||||
|
||||
if ($response->failed()) {
|
||||
throw new Exception("GitHub API Error: " . $response->body());
|
||||
}
|
||||
|
||||
$data = $response->json();
|
||||
|
||||
if (isset($data['errors'])) {
|
||||
throw new Exception("GraphQL Error: " . json_encode($data['errors']));
|
||||
}
|
||||
|
||||
$project = $data['data']['organization']['projectV2'] ?? null;
|
||||
|
||||
if (!$project) {
|
||||
throw new Exception("Project not found or access denied.");
|
||||
}
|
||||
|
||||
$items = $project['items']['nodes'];
|
||||
|
||||
// Data structures for advanced analysis
|
||||
$developerStats = [];
|
||||
$timelineStats = [
|
||||
'weekly' => [],
|
||||
'monthly' => []
|
||||
];
|
||||
$detailedItems = []; // Array for DataGrid
|
||||
|
||||
$statusMapping = [
|
||||
'Done' => 'completed',
|
||||
'Ready' => 'active',
|
||||
'In progress' => 'active',
|
||||
'In review' => 'active',
|
||||
'Backlog' => 'pending',
|
||||
'No Status' => 'pending'
|
||||
];
|
||||
|
||||
foreach ($items as $item) {
|
||||
$status = 'No Status';
|
||||
$size = 'No Size';
|
||||
$assignees = [];
|
||||
|
||||
// Parse Field Values
|
||||
foreach ($item['fieldValues']['nodes'] as $fieldValue) {
|
||||
if (!isset($fieldValue['field']['name'])) continue;
|
||||
|
||||
$fieldName = $fieldValue['field']['name'];
|
||||
|
||||
if ($fieldName === 'Status') {
|
||||
$status = $fieldValue['name'];
|
||||
} elseif ($fieldName === 'Size') {
|
||||
$size = $fieldValue['name'];
|
||||
} elseif ($fieldName === 'Assignees') {
|
||||
foreach ($fieldValue['users']['nodes'] as $user) {
|
||||
$assignees[] = $user['login'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($assignees)) {
|
||||
$assignees[] = 'Unassigned';
|
||||
}
|
||||
|
||||
// Content details
|
||||
$content = $item['content'] ?? [];
|
||||
$title = $content['title'] ?? 'Untitled';
|
||||
$url = $content['url'] ?? '#';
|
||||
$state = $content['state'] ?? 'OPEN';
|
||||
|
||||
$createdAt = $content['createdAt'] ?? null;
|
||||
$updatedAt = $content['updatedAt'] ?? null;
|
||||
$closedAt = $content['closedAt'] ?? null;
|
||||
|
||||
// Determine completion date
|
||||
$completionDate = ($state === 'CLOSED' || $state === 'MERGED' || $status === 'Done')
|
||||
? ($closedAt ?? $updatedAt)
|
||||
: null;
|
||||
|
||||
$isCompleted = ($completionDate !== null);
|
||||
|
||||
// Duration Calculation
|
||||
$duration = 'N/A';
|
||||
$durationSeconds = 0;
|
||||
|
||||
if ($createdAt) {
|
||||
try {
|
||||
$cStart = Carbon::parse($createdAt);
|
||||
$endDateStr = $isCompleted ? $completionDate : $updatedAt;
|
||||
if (!$endDateStr) $endDateStr = $createdAt;
|
||||
|
||||
$cEnd = Carbon::parse($endDateStr);
|
||||
|
||||
$diff = $cStart->diff($cEnd);
|
||||
$parts = [];
|
||||
if ($diff->y > 0) $parts[] = $diff->y . 'y';
|
||||
if ($diff->m > 0) $parts[] = $diff->m . 'mo';
|
||||
if ($diff->d > 0) $parts[] = $diff->d . 'd';
|
||||
if ($diff->h > 0) $parts[] = $diff->h . 'h';
|
||||
if (empty($parts) && $diff->i > 0) $parts[] = $diff->i . 'm';
|
||||
if (empty($parts)) $parts[] = '0m';
|
||||
|
||||
$duration = implode(' ', array_slice($parts, 0, 2));
|
||||
$durationSeconds = $cStart->diffInSeconds($cEnd);
|
||||
|
||||
} catch (Exception $e) {
|
||||
$duration = 'Error';
|
||||
}
|
||||
}
|
||||
|
||||
// Add to detailed items list (For DataGrid)
|
||||
$detailedItems[] = [
|
||||
'title' => $title,
|
||||
'status' => $status,
|
||||
'size' => $size,
|
||||
'assignees' => implode(', ', $assignees),
|
||||
'url' => $url,
|
||||
'duration' => $duration,
|
||||
'duration_seconds' => $durationSeconds,
|
||||
'created_at' => $createdAt ? Carbon::parse($createdAt)->format('Y-m-d H:i') : '-',
|
||||
'end_date' => $completionDate ? Carbon::parse($completionDate)->format('Y-m-d H:i') : '-'
|
||||
];
|
||||
|
||||
// Analyze for each assignee (For Charts/Cards)
|
||||
foreach ($assignees as $assignee) {
|
||||
if (!isset($developerStats[$assignee])) {
|
||||
$developerStats[$assignee] = [
|
||||
'total_tasks' => 0,
|
||||
'completed_tasks' => 0,
|
||||
'active_tasks' => 0,
|
||||
'pending_tasks' => 0,
|
||||
'sizes' => [],
|
||||
'completion_history' => []
|
||||
];
|
||||
}
|
||||
|
||||
$developerStats[$assignee]['total_tasks']++;
|
||||
|
||||
$generalStatus = $statusMapping[$status] ?? 'active';
|
||||
|
||||
if ($isCompleted) {
|
||||
$developerStats[$assignee]['completed_tasks']++;
|
||||
|
||||
if ($completionDate) {
|
||||
$cDate = Carbon::parse($completionDate);
|
||||
$monthKey = $cDate->format('Y-m');
|
||||
|
||||
if (!isset($developerStats[$assignee]['completion_history']['monthly'][$monthKey])) {
|
||||
$developerStats[$assignee]['completion_history']['monthly'][$monthKey] = 0;
|
||||
}
|
||||
$developerStats[$assignee]['completion_history']['monthly'][$monthKey]++;
|
||||
}
|
||||
} else {
|
||||
if ($generalStatus === 'active') {
|
||||
$developerStats[$assignee]['active_tasks']++;
|
||||
} else {
|
||||
$developerStats[$assignee]['pending_tasks']++;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isset($developerStats[$assignee]['sizes'][$size])) {
|
||||
$developerStats[$assignee]['sizes'][$size] = 0;
|
||||
}
|
||||
$developerStats[$assignee]['sizes'][$size]++;
|
||||
}
|
||||
}
|
||||
|
||||
// Format Developer Stats for Frontend
|
||||
$performanceData = [];
|
||||
foreach ($developerStats as $assignee => $stats) {
|
||||
$performanceData[] = [
|
||||
'assignee' => $assignee,
|
||||
'total' => $stats['total_tasks'],
|
||||
'completed' => $stats['completed_tasks'],
|
||||
'active' => $stats['active_tasks'],
|
||||
'pending' => $stats['pending_tasks'],
|
||||
'completion_rate' => $stats['total_tasks'] > 0 ? round(($stats['completed_tasks'] / $stats['total_tasks']) * 100, 1) : 0,
|
||||
'sizes' => $stats['sizes'],
|
||||
'history' => $stats['completion_history']
|
||||
];
|
||||
}
|
||||
|
||||
// Format Timeline Data
|
||||
$timelineChartData = [];
|
||||
$allMonths = [];
|
||||
foreach ($developerStats as $assignee => $stats) {
|
||||
if (isset($stats['completion_history']['monthly'])) {
|
||||
$allMonths = array_merge($allMonths, array_keys($stats['completion_history']['monthly']));
|
||||
}
|
||||
}
|
||||
$allMonths = array_unique($allMonths);
|
||||
sort($allMonths);
|
||||
|
||||
foreach ($allMonths as $month) {
|
||||
$row = ['month' => $month];
|
||||
foreach ($developerStats as $assignee => $stats) {
|
||||
$row[$assignee] = $stats['completion_history']['monthly'][$month] ?? 0;
|
||||
}
|
||||
$timelineChartData[] = $row;
|
||||
}
|
||||
|
||||
echo json_encode([
|
||||
'status' => 'success',
|
||||
'project_title' => $project['title'],
|
||||
'developer_performance' => $performanceData,
|
||||
'timeline_chart' => $timelineChartData,
|
||||
'raw_items' => $detailedItems, // Restored this field for DataGrid
|
||||
'meta' => [
|
||||
'total_tasks' => count($items)
|
||||
]
|
||||
], JSON_UNESCAPED_UNICODE);
|
||||
|
||||
} catch (Exception $e) {
|
||||
echo json_encode(['status' => 'error', 'message' => $e->getMessage()], JSON_UNESCAPED_UNICODE);
|
||||
}
|
||||
@endphp
|
||||
Reference in New Issue
Block a user