Skip to content

Commit b69f213

Browse files
authored
merge: merge pull request #15 from n0rfas/dev
2 parents 699338d + 77d1237 commit b69f213

4 files changed

Lines changed: 54448 additions & 6 deletions

File tree

git_analytics/static/index.html

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,27 @@ <h2>Authors</h2>
153153
</div>
154154
</div>
155155
</div>
156+
<div class="row mt-4">
157+
<div class="col-md-12">
158+
<div class="card h-100 w-100">
159+
<div class="card-header">
160+
<span>More by authors</span>
161+
<i class="bi bi-info-circle"
162+
data-bs-toggle="tooltip"
163+
data-bs-placement="right"
164+
title="More information on each author separately.">
165+
</i>
166+
</div>
167+
<div class="card-body">
168+
<div class="row">
169+
<div class="col-md-12">
170+
<div class="accordion" id="accordionAuthors"></div>
171+
</div>
172+
</div>
173+
</div>
174+
</div>
175+
</div>
176+
</div>
156177
<div class="row mt-4">
157178
<div class="col-md-12">
158179
<div class="card h-100 w-100">
@@ -288,7 +309,7 @@ <h2>Commits</h2>
288309
<!-- footer -->
289310
<footer class="bg-dark text-white py-3 mt-auto">
290311
<div class="container">
291-
<span>&copy; 2025 ver 0.1.12</span>
312+
<span>&copy; 2025 ver 0.1.13</span>
292313
</div>
293314
</footer>
294315
<script src="js/bootstrap.bundle.min.js"></script>

git_analytics/static/js/git-analytics.js

Lines changed: 107 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ async function loadAndRender(type, value, timeIntervalLabel) {
6969
renderInsDelLinesByAuthors(stats.authors_statistics.authors);
7070
renderCodeChurnByAuthor(stats.authors_statistics.authors);
7171
renderCommitsByAuthor(stats.authors_statistics.authors);
72+
renderAccordionAuthors(stats);
7273
renderAuthorsContributionsTable(stats.authors_statistics.authors);
7374

7475
buildHourByAuthorChart(stats.historical_statistics.hour_of_day);
@@ -166,15 +167,23 @@ function renderChart(id, config) {
166167
}
167168

168169
function renderCommitsByAuthor(authorsData) {
170+
const chartName = "chartCommitsByAuthor";
169171
const labels = Object.keys(authorsData);
170172
const dataValues = Object.values(authorsData).map(a => a.commits);
171173

172-
renderChart("chartCommitsByAuthor", {
174+
subRenderCommitsByAuthor(chartName, labels, dataValues);
175+
}
176+
177+
function subRenderCommitsByAuthor(chartName, labels, values) {
178+
179+
console.log("Rendering commits by author:", chartName, labels, values);
180+
181+
renderChart(chartName, {
173182
type: "pie",
174183
data: {
175184
labels: labels,
176185
datasets: [{
177-
data: dataValues,
186+
data: values,
178187
}]
179188
},
180189
options: {
@@ -324,6 +333,38 @@ function buildHourByAuthorChart(hourOfDayData) {
324333
});
325334
}
326335

336+
function buildHourByAuthorChartForAccordion(chartName, dataValue) {
337+
const HOUR_LABELS = Array.from({ length: 24 }, (_, i) => String(i));
338+
339+
renderChart(chartName, {
340+
type: "bar",
341+
data: {
342+
labels: HOUR_LABELS,
343+
datasets: [{
344+
data: dataValue,
345+
stack: "commits",
346+
borderWidth: 1,
347+
backgroundColor: "#74c0fc"
348+
}]
349+
},
350+
options: {
351+
responsive: true,
352+
plugins: {
353+
legend: { position: "bottom", display: false },
354+
tooltip: {
355+
callbacks: {
356+
label: (c) => `${c.dataset.label}: ${c.parsed.y}`
357+
}
358+
}
359+
},
360+
scales: {
361+
x: { stacked: true },
362+
y: { stacked: true, beginAtZero: true, ticks: { precision: 0 } }
363+
}
364+
}
365+
});
366+
}
367+
327368
function buildWeekByAuthorChart(dayOfWeekData) {
328369
const WEEK_LABELS = ["Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"];
329370

@@ -461,12 +502,16 @@ function buildDayOfMonthByAuthorChart(dayOfMonthData) {
461502
}
462503

463504
function renderExtensionsHorizontalBar(filesExtensionsTotal) {
505+
SubRenderExtensionsHorizontalBar("chartExtensions", filesExtensionsTotal)
506+
}
507+
508+
function SubRenderExtensionsHorizontalBar(chartName, data) {
464509
const COLOR_INSERTIONS = "#198754";
465510
const COLOR_DELETIONS = "#dc3545";
466511

467512
const cleanKey = (k) => String(k).trim().replace(/}+$/, "");
468513

469-
const items = Object.entries(filesExtensionsTotal).map(([ext, v]) => {
514+
const items = Object.entries(data).map(([ext, v]) => {
470515
const key = cleanKey(ext) || "no_extension";
471516
const ins = Number(v?.insertions || 0);
472517
const del = Number(v?.deletions || 0);
@@ -481,7 +526,7 @@ function renderExtensionsHorizontalBar(filesExtensionsTotal) {
481526
const insertions = filtered.map(it => it.insertions);
482527
const deletions = filtered.map(it => -Math.abs(it.deletions)); // отрицательные
483528

484-
renderChart("chartExtensions", {
529+
renderChart(chartName, {
485530
type: "bar",
486531
data: {
487532
labels,
@@ -627,6 +672,64 @@ function renderWeeklyCommitTypes(weeklyCommitTypesData) {
627672
});
628673
}
629674

675+
function renderAccordionAuthors(stats) {
676+
const authorsList = Object.keys(stats.authors_statistics.authors).sort();
677+
678+
const accordion = document.getElementById("accordionAuthors");
679+
accordion.innerHTML = "";
680+
681+
682+
authorsList.forEach((author, index) => {
683+
const collapseId = `collapse-${index}`;
684+
const chartExtensionsId = `chartExtensions-${index}`;
685+
686+
const chartCommitTypesId = `chartCommitTypes-${index}`;
687+
const chartCommitTypesLabels = Object.keys(stats.commit_type.author_commit_type_counter[author]);
688+
const chartCommitTypesValues = Object.values(stats.commit_type.author_commit_type_counter[author]);
689+
690+
const chartDayId = `chartDay-${index}`;
691+
692+
const chartDayValues = Object.keys(stats.historical_statistics.hour_of_day).map(h => stats.historical_statistics.hour_of_day[h][author] || 0);
693+
694+
695+
const item = document.createElement("div");
696+
item.className = "accordion-item";
697+
item.innerHTML = `
698+
<div class="accordion-item">
699+
<h2 class="accordion-header" id="heading-${index}">
700+
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#${collapseId}" aria-expanded="false" aria-controls="${collapseId}">
701+
${author}
702+
</button>
703+
</h2>
704+
<div id="${collapseId}" class="accordion-collapse collapse" aria-labelledby="heading-${index}" data-bs-parent="#accordionAuthors">
705+
<div class="accordion-body">
706+
<div class="row">
707+
<div class="col-md-12">
708+
<canvas id="${chartExtensionsId}"></canvas>
709+
</div>
710+
</div>
711+
<div class="row">
712+
<div class="col-md-4">
713+
<canvas id="${chartCommitTypesId}"></canvas>
714+
</div>
715+
<div class="col-md-8">
716+
<canvas id="${chartDayId}"></canvas>
717+
</div>
718+
</div>
719+
</div>
720+
</div>
721+
`;
722+
723+
accordion.appendChild(item);
724+
725+
setTimeout(() => {
726+
SubRenderExtensionsHorizontalBar(chartExtensionsId, stats.language_statistics.files_extensions_by_author[author]);
727+
subRenderCommitsByAuthor(chartCommitTypesId, chartCommitTypesLabels, chartCommitTypesValues);
728+
buildHourByAuthorChartForAccordion(chartDayId, chartDayValues);
729+
}, 0);
730+
});
731+
}
732+
630733
function renderAuthorsContributionsTable(authorsData) {
631734
const tbody = document.getElementById("authorsContributionsTable");
632735
tbody.innerHTML = "";

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "git-analytics"
3-
version = "0.1.12"
3+
version = "0.1.13"
44
description = "Advanced analytics for Git repositories — commits, authors, code churn, lines of code, trends, and visual dashboards."
55
authors = ["n0rfas <n0rfas@protonmail.com>"]
66
license = "MIT"

0 commit comments

Comments
 (0)