metripy 0.3.2__py3-none-any.whl → 0.3.4__py3-none-any.whl
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.
Potentially problematic release.
This version of metripy might be problematic. Click here for more details.
- metripy/Application/Info.py +29 -4
- metripy/Report/Html/Reporter.py +34 -7
- metripy/templates/html_report/css/styles.css +1386 -0
- metripy/templates/html_report/dependencies.html +441 -0
- metripy/templates/html_report/files.html +1080 -0
- metripy/templates/html_report/git_analysis.html +325 -0
- metripy/templates/html_report/images/logo.svg +31 -0
- metripy/templates/html_report/index.html +385 -0
- metripy/templates/html_report/js/charts.js +313 -0
- metripy/templates/html_report/js/dashboard.js +546 -0
- metripy/templates/html_report/js/git_analysis.js +383 -0
- metripy/templates/html_report/top_offenders.html +267 -0
- metripy/templates/html_report/trends.html +468 -0
- {metripy-0.3.2.dist-info → metripy-0.3.4.dist-info}/METADATA +1 -1
- {metripy-0.3.2.dist-info → metripy-0.3.4.dist-info}/RECORD +19 -8
- {metripy-0.3.2.dist-info → metripy-0.3.4.dist-info}/WHEEL +0 -0
- {metripy-0.3.2.dist-info → metripy-0.3.4.dist-info}/entry_points.txt +0 -0
- {metripy-0.3.2.dist-info → metripy-0.3.4.dist-info}/licenses/LICENSE +0 -0
- {metripy-0.3.2.dist-info → metripy-0.3.4.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,383 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git Analysis JavaScript
|
|
3
|
+
* Handles charts and interactivity for the Git Analysis page
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
class GitAnalysis {
|
|
7
|
+
constructor() {
|
|
8
|
+
this.data = {};
|
|
9
|
+
this.init();
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
init() {
|
|
13
|
+
this.loadData();
|
|
14
|
+
this.setupCharts();
|
|
15
|
+
this.setupInteractivity();
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
loadData() {
|
|
19
|
+
try {
|
|
20
|
+
// Load git statistics from embedded data
|
|
21
|
+
if (window.GIT_STATS_DATA) {
|
|
22
|
+
this.data.gitStats = this.formatGitCommitsData(window.GIT_STATS_DATA);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Load git churn data from embedded data
|
|
26
|
+
if (window.GIT_CHURN_DATA) {
|
|
27
|
+
this.data.gitChurn = window.GIT_CHURN_DATA;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Load comprehensive git analysis data
|
|
31
|
+
if (window.GIT_ANALYSIS_DATA) {
|
|
32
|
+
this.data.analysis = window.GIT_ANALYSIS_DATA;
|
|
33
|
+
this.populateAnalysisData();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
console.log('Git analysis data loaded successfully');
|
|
37
|
+
} catch (error) {
|
|
38
|
+
console.error('Error loading git analysis data:', error);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
formatGitCommitsData(gitData) {
|
|
43
|
+
// Convert git statistics data to chart format
|
|
44
|
+
if (gitData && typeof gitData === 'object' && !Array.isArray(gitData)) {
|
|
45
|
+
return Object.entries(gitData).map(([date, count]) => ({
|
|
46
|
+
month: this.formatMonthName(date),
|
|
47
|
+
commits: count,
|
|
48
|
+
date: new Date(date + '-01').toISOString()
|
|
49
|
+
})).sort((a, b) => new Date(a.date) - new Date(b.date));
|
|
50
|
+
}
|
|
51
|
+
return [];
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
formatMonthName(monthString) {
|
|
55
|
+
try {
|
|
56
|
+
let date;
|
|
57
|
+
if (monthString.includes('-')) {
|
|
58
|
+
date = new Date(monthString + (monthString.split('-').length === 2 ? '-01' : ''));
|
|
59
|
+
} else {
|
|
60
|
+
date = new Date(monthString);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return date.toLocaleDateString('en-US', {
|
|
64
|
+
month: 'short',
|
|
65
|
+
year: 'numeric'
|
|
66
|
+
});
|
|
67
|
+
} catch (error) {
|
|
68
|
+
return monthString; // Return original if parsing fails
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
setupCharts() {
|
|
73
|
+
this.setupCommitChart();
|
|
74
|
+
this.setupChurnChart();
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
setupCommitChart() {
|
|
78
|
+
const canvas = document.getElementById('gitCommitsChart');
|
|
79
|
+
if (!canvas || !this.data.gitStats || this.data.gitStats.length === 0) {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const ctx = canvas.getContext('2d');
|
|
84
|
+
|
|
85
|
+
new Chart(ctx, {
|
|
86
|
+
type: 'line',
|
|
87
|
+
data: {
|
|
88
|
+
labels: this.data.gitStats.map(item => item.month),
|
|
89
|
+
datasets: [{
|
|
90
|
+
label: 'Commits',
|
|
91
|
+
data: this.data.gitStats.map(item => item.commits),
|
|
92
|
+
borderColor: '#3b82f6',
|
|
93
|
+
backgroundColor: 'rgba(59, 130, 246, 0.1)',
|
|
94
|
+
borderWidth: 2,
|
|
95
|
+
fill: true,
|
|
96
|
+
tension: 0.4,
|
|
97
|
+
pointBackgroundColor: '#3b82f6',
|
|
98
|
+
pointBorderColor: '#ffffff',
|
|
99
|
+
pointBorderWidth: 2,
|
|
100
|
+
pointRadius: 4,
|
|
101
|
+
pointHoverRadius: 6
|
|
102
|
+
}]
|
|
103
|
+
},
|
|
104
|
+
options: {
|
|
105
|
+
responsive: true,
|
|
106
|
+
maintainAspectRatio: false,
|
|
107
|
+
scales: {
|
|
108
|
+
y: {
|
|
109
|
+
beginAtZero: true,
|
|
110
|
+
grid: {
|
|
111
|
+
color: 'rgba(0, 0, 0, 0.05)'
|
|
112
|
+
},
|
|
113
|
+
ticks: {
|
|
114
|
+
color: '#64748b'
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
x: {
|
|
118
|
+
grid: {
|
|
119
|
+
color: 'rgba(0, 0, 0, 0.05)'
|
|
120
|
+
},
|
|
121
|
+
ticks: {
|
|
122
|
+
color: '#64748b'
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
},
|
|
126
|
+
plugins: {
|
|
127
|
+
legend: {
|
|
128
|
+
display: false
|
|
129
|
+
},
|
|
130
|
+
tooltip: {
|
|
131
|
+
backgroundColor: 'rgba(0, 0, 0, 0.8)',
|
|
132
|
+
titleColor: '#ffffff',
|
|
133
|
+
bodyColor: '#ffffff',
|
|
134
|
+
borderColor: '#3b82f6',
|
|
135
|
+
borderWidth: 1,
|
|
136
|
+
cornerRadius: 8,
|
|
137
|
+
displayColors: false,
|
|
138
|
+
callbacks: {
|
|
139
|
+
title: (context) => `${context[0].label}`,
|
|
140
|
+
label: (context) => `${context.parsed.y} commits`
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
interaction: {
|
|
145
|
+
intersect: false,
|
|
146
|
+
mode: 'index'
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
setupChurnChart() {
|
|
153
|
+
const canvas = document.getElementById('gitChurnChart');
|
|
154
|
+
if (!canvas || !this.data.gitChurn) {
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const ctx = canvas.getContext('2d');
|
|
159
|
+
|
|
160
|
+
// Sample churn data if not provided
|
|
161
|
+
const churnData = this.data.gitChurn || this.generateSampleChurnData();
|
|
162
|
+
|
|
163
|
+
const labels = Object.keys(churnData);
|
|
164
|
+
const added = labels.map(label => churnData[label].added);
|
|
165
|
+
const removed = labels.map(label => -churnData[label].removed);
|
|
166
|
+
new Chart(ctx, {
|
|
167
|
+
type: 'bar',
|
|
168
|
+
data: {
|
|
169
|
+
labels: labels,
|
|
170
|
+
datasets: [
|
|
171
|
+
{
|
|
172
|
+
label: 'Lines Removed',
|
|
173
|
+
data: removed, // Goes downward
|
|
174
|
+
backgroundColor: 'rgba(255, 99, 132, 0.6)'
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
label: 'Lines Added',
|
|
178
|
+
data: added, // Goes upward
|
|
179
|
+
backgroundColor: 'rgba(75, 192, 192, 0.6)'
|
|
180
|
+
}
|
|
181
|
+
]
|
|
182
|
+
},
|
|
183
|
+
options: {
|
|
184
|
+
responsive: true,
|
|
185
|
+
plugins: {
|
|
186
|
+
tooltip: {
|
|
187
|
+
callbacks: {
|
|
188
|
+
label: function(context) {
|
|
189
|
+
return `${context.dataset.label}: ${Math.abs(context.raw)}`;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
},
|
|
194
|
+
scales: {
|
|
195
|
+
y: {
|
|
196
|
+
stacked: true,
|
|
197
|
+
ticks: {
|
|
198
|
+
callback: function(value) {
|
|
199
|
+
return Math.abs(value);
|
|
200
|
+
}
|
|
201
|
+
},
|
|
202
|
+
},
|
|
203
|
+
x: {
|
|
204
|
+
stacked: true
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
generateSampleChurnData() {
|
|
213
|
+
// Generate sample data if churn data is not provided
|
|
214
|
+
const months = [];
|
|
215
|
+
const added = [];
|
|
216
|
+
const removed = [];
|
|
217
|
+
|
|
218
|
+
// Get last 6 months
|
|
219
|
+
for (let i = 5; i >= 0; i--) {
|
|
220
|
+
const date = new Date();
|
|
221
|
+
date.setMonth(date.getMonth() - i);
|
|
222
|
+
months.push(date.toLocaleDateString('en-US', { month: 'short', year: 'numeric' }));
|
|
223
|
+
|
|
224
|
+
// Generate random but realistic data
|
|
225
|
+
added.push(Math.floor(Math.random() * 2000) + 500);
|
|
226
|
+
removed.push(Math.floor(Math.random() * 1500) + 200);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
return {
|
|
230
|
+
labels: months,
|
|
231
|
+
added: added,
|
|
232
|
+
removed: removed
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
populateAnalysisData() {
|
|
237
|
+
if (!this.data.analysis) return;
|
|
238
|
+
|
|
239
|
+
try {
|
|
240
|
+
this.populateActiveDays();
|
|
241
|
+
this.populateCommitQuality();
|
|
242
|
+
this.populateRecommendations();
|
|
243
|
+
|
|
244
|
+
// Setup table interactivity after populating tables
|
|
245
|
+
this.setupTableInteractivity();
|
|
246
|
+
} catch (error) {
|
|
247
|
+
console.error('Error populating analysis data:', error);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
populateActiveDays() {
|
|
252
|
+
const container = document.getElementById('active-days-content');
|
|
253
|
+
if (!container || !this.data.analysis.active_days) return;
|
|
254
|
+
|
|
255
|
+
container.innerHTML = '';
|
|
256
|
+
|
|
257
|
+
this.data.analysis.active_days.forEach(day => {
|
|
258
|
+
const p = document.createElement('p');
|
|
259
|
+
const note = day.is_deploy_day ? ` (${day.note})` : '';
|
|
260
|
+
p.innerHTML = `<strong>${day.day_name}:</strong> ${day.percentage}% of commits${note}`;
|
|
261
|
+
container.appendChild(p);
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
populateCommitQuality() {
|
|
266
|
+
const container = document.getElementById('commit-quality-content');
|
|
267
|
+
if (!container || !this.data.analysis) return;
|
|
268
|
+
|
|
269
|
+
container.innerHTML = `
|
|
270
|
+
<p><strong>Small commits:</strong> ${this.data.analysis.small_commits_percentage}% (<50 lines)</p>
|
|
271
|
+
<p><strong>Message quality:</strong> ${this.data.analysis.good_message_percentage}% have good descriptions</p>
|
|
272
|
+
<p><strong>Fix commits:</strong> ${this.data.analysis.fix_commits_percentage}% (indicates stability)</p>
|
|
273
|
+
`;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
populateRecommendations() {
|
|
277
|
+
const container = document.getElementById('recommendations-content');
|
|
278
|
+
if (!container || !this.data.analysis.recommendations) return;
|
|
279
|
+
|
|
280
|
+
container.innerHTML = '';
|
|
281
|
+
|
|
282
|
+
this.data.analysis.recommendations.forEach(rec => {
|
|
283
|
+
const p = document.createElement('p');
|
|
284
|
+
p.textContent = `• ${rec.recommendation}`;
|
|
285
|
+
container.appendChild(p);
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
setupInteractivity() {
|
|
290
|
+
// Setup navigation highlight
|
|
291
|
+
this.setupNavigationHighlight();
|
|
292
|
+
// Table interactivity is set up after populating tables in populateAnalysisData()
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
setupTableInteractivity() {
|
|
296
|
+
const tables = document.querySelectorAll('.hotspot-table tbody tr, .contributor-table tbody tr');
|
|
297
|
+
tables.forEach(row => {
|
|
298
|
+
row.style.cursor = 'pointer';
|
|
299
|
+
row.addEventListener('click', function() {
|
|
300
|
+
// Highlight clicked row
|
|
301
|
+
this.style.backgroundColor = 'var(--bg-tertiary)';
|
|
302
|
+
setTimeout(() => {
|
|
303
|
+
this.style.backgroundColor = '';
|
|
304
|
+
}, 300);
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
row.addEventListener('mouseenter', function() {
|
|
308
|
+
this.style.backgroundColor = 'rgba(59, 130, 246, 0.05)';
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
row.addEventListener('mouseleave', function() {
|
|
312
|
+
this.style.backgroundColor = '';
|
|
313
|
+
});
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
setupNavigationHighlight() {
|
|
318
|
+
// Ensure git analysis nav item is highlighted
|
|
319
|
+
const navItems = document.querySelectorAll('.nav-item');
|
|
320
|
+
navItems.forEach(item => {
|
|
321
|
+
const link = item.querySelector('.nav-link');
|
|
322
|
+
if (link && link.getAttribute('href') === 'git_analysis.html') {
|
|
323
|
+
item.classList.add('active');
|
|
324
|
+
} else {
|
|
325
|
+
item.classList.remove('active');
|
|
326
|
+
}
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
// Utility function to show notifications
|
|
331
|
+
showNotification(message, type = 'info') {
|
|
332
|
+
const notification = document.createElement('div');
|
|
333
|
+
notification.className = `notification notification-${type}`;
|
|
334
|
+
notification.style.cssText = `
|
|
335
|
+
position: fixed;
|
|
336
|
+
top: 20px;
|
|
337
|
+
right: 20px;
|
|
338
|
+
padding: 1rem 1.5rem;
|
|
339
|
+
border-radius: 0.5rem;
|
|
340
|
+
color: white;
|
|
341
|
+
font-weight: 500;
|
|
342
|
+
z-index: 1000;
|
|
343
|
+
transform: translateX(100%);
|
|
344
|
+
transition: transform 0.3s ease;
|
|
345
|
+
`;
|
|
346
|
+
|
|
347
|
+
// Set background color based on type
|
|
348
|
+
const colors = {
|
|
349
|
+
success: '#10b981',
|
|
350
|
+
error: '#ef4444',
|
|
351
|
+
warning: '#f59e0b',
|
|
352
|
+
info: '#3b82f6'
|
|
353
|
+
};
|
|
354
|
+
notification.style.backgroundColor = colors[type] || colors.info;
|
|
355
|
+
notification.textContent = message;
|
|
356
|
+
|
|
357
|
+
// Add to DOM
|
|
358
|
+
document.body.appendChild(notification);
|
|
359
|
+
|
|
360
|
+
// Animate in
|
|
361
|
+
setTimeout(() => {
|
|
362
|
+
notification.style.transform = 'translateX(0)';
|
|
363
|
+
}, 100);
|
|
364
|
+
|
|
365
|
+
// Remove after delay
|
|
366
|
+
setTimeout(() => {
|
|
367
|
+
notification.style.transform = 'translateX(100%)';
|
|
368
|
+
setTimeout(() => {
|
|
369
|
+
if (document.body.contains(notification)) {
|
|
370
|
+
document.body.removeChild(notification);
|
|
371
|
+
}
|
|
372
|
+
}, 300);
|
|
373
|
+
}, 3000);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
// Initialize git analysis when DOM is loaded
|
|
378
|
+
document.addEventListener('DOMContentLoaded', () => {
|
|
379
|
+
window.gitAnalysis = new GitAnalysis();
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
// Export for global access
|
|
383
|
+
window.GitAnalysis = GitAnalysis;
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>Git Analysis - Code Metrics Dashboard</title>
|
|
7
|
+
<link rel="stylesheet" href="css/styles.css">
|
|
8
|
+
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
|
|
9
|
+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
|
10
|
+
<style>.cc-offenders {
|
|
11
|
+
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
|
12
|
+
background-color: #f9f9f9;
|
|
13
|
+
padding: 1.5rem;
|
|
14
|
+
border-radius: 8px;
|
|
15
|
+
max-width: 600px;
|
|
16
|
+
margin: 2rem auto;
|
|
17
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.cc-offenders h2 {
|
|
21
|
+
text-align: center;
|
|
22
|
+
color: #333;
|
|
23
|
+
margin-bottom: 1rem;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.offender-list {
|
|
27
|
+
list-style: none;
|
|
28
|
+
padding: 0;
|
|
29
|
+
margin: 0;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.offender {
|
|
33
|
+
background-color: #fff;
|
|
34
|
+
border: 1px solid #ddd;
|
|
35
|
+
padding: 1rem;
|
|
36
|
+
margin-bottom: 1rem;
|
|
37
|
+
border-radius: 4px;
|
|
38
|
+
border-left-width: 6px;
|
|
39
|
+
border-left-style: solid;
|
|
40
|
+
transition: box-shadow 0.2s ease;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.offender:hover {
|
|
44
|
+
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.08);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
.offender-name {
|
|
49
|
+
font-weight: bold;
|
|
50
|
+
font-size: 1.1rem;
|
|
51
|
+
margin-bottom: 0.5rem;
|
|
52
|
+
color: #222;
|
|
53
|
+
word-break: break-word; /* Ensures long names wrap */
|
|
54
|
+
white-space: normal; /* Allows wrapping */
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
.offender-details {
|
|
59
|
+
font-size: 0.95rem;
|
|
60
|
+
color: #555;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.label {
|
|
64
|
+
font-weight: 600;
|
|
65
|
+
margin-right: 0.5rem;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/* Status-based border colors */
|
|
69
|
+
.status-good {
|
|
70
|
+
border-left-color: #10b981; /* Green */
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.status-ok {
|
|
74
|
+
border-left-color: #f59e0b; /* Yellow/Amber */
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.status-warning {
|
|
78
|
+
border-left-color: #f97316; /* Orange */
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.status-critical {
|
|
82
|
+
border-left-color: #ef4444; /* Red */
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
</style>
|
|
86
|
+
</head>
|
|
87
|
+
<body>
|
|
88
|
+
<div class="dashboard">
|
|
89
|
+
<!-- Sidebar -->
|
|
90
|
+
<aside class="sidebar">
|
|
91
|
+
<div class="sidebar-header">
|
|
92
|
+
<div class="logo">
|
|
93
|
+
<img src="images/logo.svg" alt="Metripy Logo" class="logo-icon">
|
|
94
|
+
<h2>Metripy</h2>
|
|
95
|
+
</div>
|
|
96
|
+
</div>
|
|
97
|
+
|
|
98
|
+
<nav class="sidebar-nav">
|
|
99
|
+
<ul>
|
|
100
|
+
<li class="nav-item">
|
|
101
|
+
<a href="index.html" class="nav-link">
|
|
102
|
+
<i class="fas fa-tachometer-alt"></i>
|
|
103
|
+
<span>Overview</span>
|
|
104
|
+
</a>
|
|
105
|
+
</li>
|
|
106
|
+
<li class="nav-item">
|
|
107
|
+
<a href="files.html" class="nav-link">
|
|
108
|
+
<i class="fas fa-file-code"></i>
|
|
109
|
+
<span>Files</span>
|
|
110
|
+
</a>
|
|
111
|
+
</li>
|
|
112
|
+
<li class="nav-item active">
|
|
113
|
+
<a href="top_offenders.html" class="nav-link">
|
|
114
|
+
<i class="fa-solid fa-stethoscope"></i>
|
|
115
|
+
<span>Top Offenders</span>
|
|
116
|
+
</a>
|
|
117
|
+
</li>
|
|
118
|
+
<li class="nav-item">
|
|
119
|
+
<a href="git_analysis.html" class="nav-link">
|
|
120
|
+
<i class="fab fa-git-alt"></i>
|
|
121
|
+
<span>Git Analysis</span>
|
|
122
|
+
</a>
|
|
123
|
+
</li>
|
|
124
|
+
<li class="nav-item">
|
|
125
|
+
<a href="dependencies.html" class="nav-link">
|
|
126
|
+
<i class="fas fa-cubes"></i>
|
|
127
|
+
<span>Dependencies</span>
|
|
128
|
+
</a>
|
|
129
|
+
</li>
|
|
130
|
+
<li class="nav-item">
|
|
131
|
+
<a href="trends.html" class="nav-link">
|
|
132
|
+
<i class="fas fa-chart-line"></i>
|
|
133
|
+
<span>Trends</span>
|
|
134
|
+
</a>
|
|
135
|
+
</li>
|
|
136
|
+
</ul>
|
|
137
|
+
</nav>
|
|
138
|
+
|
|
139
|
+
<div class="sidebar-footer">
|
|
140
|
+
<div class="project-info">
|
|
141
|
+
<h4>Project: {{project_name}}</h4>
|
|
142
|
+
<p>Last updated: {{last_updated}}</p>
|
|
143
|
+
</div>
|
|
144
|
+
</div>
|
|
145
|
+
</aside>
|
|
146
|
+
|
|
147
|
+
<!-- Main Content -->
|
|
148
|
+
<main class="main-content">
|
|
149
|
+
<header class="page-header">
|
|
150
|
+
<div class="header-content">
|
|
151
|
+
<h1>Top Offenders</h1>
|
|
152
|
+
<p class="subtitle">View top offenders of different criteria on file and function level</p>
|
|
153
|
+
</div>
|
|
154
|
+
</header>
|
|
155
|
+
|
|
156
|
+
<section class="two-column-section">
|
|
157
|
+
<div class="info-card">
|
|
158
|
+
<h4>File Lines of code</h4>
|
|
159
|
+
|
|
160
|
+
<ul class="offender-list">
|
|
161
|
+
{{#EACH file_loc_offenders AS offender}}
|
|
162
|
+
<li class="offender status-{{offender.status}}">
|
|
163
|
+
<div class="offender-name">{{offender.full_name}}</div>
|
|
164
|
+
<div class="offender-details">
|
|
165
|
+
<span class="label">Lines of code:</span> {{offender.loc}}
|
|
166
|
+
</div>
|
|
167
|
+
</li>
|
|
168
|
+
{{/EACH}}
|
|
169
|
+
</ul>
|
|
170
|
+
|
|
171
|
+
</div>
|
|
172
|
+
<div class="info-card">
|
|
173
|
+
<h4>Function size</h4>
|
|
174
|
+
|
|
175
|
+
<ul class="offender-list">
|
|
176
|
+
{{#EACH function_size_offenders AS offender}}
|
|
177
|
+
<li class="offender status-{{offender.status}}">
|
|
178
|
+
<div class="offender-name">{{offender.full_name}}</div>
|
|
179
|
+
<div class="offender-details">
|
|
180
|
+
<span class="label">Size:</span> {{offender.loc}} Lines
|
|
181
|
+
</div>
|
|
182
|
+
</li>
|
|
183
|
+
{{/EACH}}
|
|
184
|
+
</ul>
|
|
185
|
+
|
|
186
|
+
</div>
|
|
187
|
+
</section>
|
|
188
|
+
|
|
189
|
+
<div class="section-divider"></div>
|
|
190
|
+
|
|
191
|
+
<section class="two-column-section">
|
|
192
|
+
<div class="info-card">
|
|
193
|
+
<h4>File Cyclomatic complexity</h4>
|
|
194
|
+
|
|
195
|
+
<ul class="offender-list">
|
|
196
|
+
{{#EACH file_cc_offenders AS offender}}
|
|
197
|
+
<li class="offender status-{{offender.status}}">
|
|
198
|
+
<div class="offender-name">{{offender.full_name}}</div>
|
|
199
|
+
<div class="offender-details">
|
|
200
|
+
<span class="label">Complexity:</span> {{offender.totalCc}}
|
|
201
|
+
</div>
|
|
202
|
+
</li>
|
|
203
|
+
{{/EACH}}
|
|
204
|
+
</ul>
|
|
205
|
+
|
|
206
|
+
</div>
|
|
207
|
+
<div class="info-card">
|
|
208
|
+
<h4>Function Cyclomatic complexity</h4>
|
|
209
|
+
|
|
210
|
+
<ul class="offender-list">
|
|
211
|
+
{{#EACH function_cc_offenders AS offender}}
|
|
212
|
+
<li class="offender status-{{offender.status}}">
|
|
213
|
+
<div class="offender-name">{{offender.full_name}}</div>
|
|
214
|
+
<div class="offender-details">
|
|
215
|
+
<span class="label">Complexity:</span> {{offender.complexity}}
|
|
216
|
+
</div>
|
|
217
|
+
</li>
|
|
218
|
+
{{/EACH}}
|
|
219
|
+
</ul>
|
|
220
|
+
|
|
221
|
+
</div>
|
|
222
|
+
</section>
|
|
223
|
+
|
|
224
|
+
<div class="section-divider"></div>
|
|
225
|
+
|
|
226
|
+
<section class="two-column-section">
|
|
227
|
+
<div class="info-card">
|
|
228
|
+
<h4>File Maintainability Index</h4>
|
|
229
|
+
|
|
230
|
+
<ul class="offender-list">
|
|
231
|
+
{{#EACH file_mi_offenders AS offender}}
|
|
232
|
+
<li class="offender status-{{offender.status}}">
|
|
233
|
+
<div class="offender-name">{{offender.full_name}}</div>
|
|
234
|
+
<div class="offender-details">
|
|
235
|
+
<span class="label">Maintainability Index:</span> {{offender.maintainabilityIndex}}
|
|
236
|
+
</div>
|
|
237
|
+
</li>
|
|
238
|
+
{{/EACH}}
|
|
239
|
+
</ul>
|
|
240
|
+
|
|
241
|
+
</div>
|
|
242
|
+
<div class="info-card">
|
|
243
|
+
<h4>Function Maintainability Index</h4>
|
|
244
|
+
|
|
245
|
+
<ul class="offender-list">
|
|
246
|
+
{{#EACH function_mi_offenders AS offender}}
|
|
247
|
+
<li class="offender status-{{offender.status}}">
|
|
248
|
+
<div class="offender-name">{{offender.full_name}}</div>
|
|
249
|
+
<div class="offender-details">
|
|
250
|
+
<span class="label">Maintainability Index:</span> {{offender.maintainability_index}}
|
|
251
|
+
</div>
|
|
252
|
+
</li>
|
|
253
|
+
{{/EACH}}
|
|
254
|
+
</ul>
|
|
255
|
+
|
|
256
|
+
</div>
|
|
257
|
+
</section>
|
|
258
|
+
</main>
|
|
259
|
+
</div>
|
|
260
|
+
|
|
261
|
+
<!-- Scripts -->
|
|
262
|
+
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
|
263
|
+
<script>
|
|
264
|
+
// Embed data directly from template engine
|
|
265
|
+
</script>
|
|
266
|
+
</body>
|
|
267
|
+
</html>
|