Implement code frequency graph (#29191)

### Overview
This is the implementation of Code Frequency page. This feature was
mentioned on these issues: #18262, #7392.

It adds another tab to Activity page called Code Frequency. Code
Frequency tab shows additions and deletions over time since the
repository existed.

Before:
<img width="1296" alt="image"
src="2603504f-aee7-4929-a8c4-fb3412a7a0f6">

After:
<img width="1296" alt="image"
src="58c03721-729f-4536-a663-9f337f240963">

---

#### Features
- See additions deletions over time since repository existed
- Click on "Additions" or "Deletions" legend to show only one type of
contribution
- Use the same cache from Contributors page so that the loading of data
will be fast once it is cached by visiting either one of the pages

---------

Co-authored-by: Giteabot <teabot@gitea.io>
(cherry picked from commit 875f5ea6d83c8371f309df99654ca3556623004c)
This commit is contained in:
Şahin Akkaya 2024-02-24 02:41:24 +03:00 committed by Earl Warren
parent fc384e494e
commit f097799953
No known key found for this signature in database
GPG key ID: 0579CB2928A78A00
13 changed files with 277 additions and 32 deletions

View file

@ -3,10 +3,7 @@ import {SvgIcon} from '../svg.js';
import {
Chart,
Title,
Tooltip,
Legend,
BarElement,
CategoryScale,
LinearScale,
TimeScale,
PointElement,
@ -21,27 +18,13 @@ import {
firstStartDateAfterDate,
fillEmptyStartDaysWithZeroes,
} from '../utils/time.js';
import {chartJsColors} from '../utils/color.js';
import {sleep} from '../utils.js';
import 'chartjs-adapter-dayjs-4/dist/chartjs-adapter-dayjs-4.esm';
import $ from 'jquery';
const {pageData} = window.config;
const colors = {
text: '--color-text',
border: '--color-secondary-alpha-60',
commits: '--color-primary-alpha-60',
additions: '--color-green',
deletions: '--color-red',
title: '--color-secondary-dark-4',
};
const styles = window.getComputedStyle(document.documentElement);
const getColor = (name) => styles.getPropertyValue(name).trim();
for (const [key, value] of Object.entries(colors)) {
colors[key] = getColor(value);
}
const customEventListener = {
id: 'customEventListener',
afterEvent: (chart, args, opts) => {
@ -54,17 +37,14 @@ const customEventListener = {
}
};
Chart.defaults.color = colors.text;
Chart.defaults.borderColor = colors.border;
Chart.defaults.color = chartJsColors.text;
Chart.defaults.borderColor = chartJsColors.border;
Chart.register(
TimeScale,
CategoryScale,
LinearScale,
BarElement,
Title,
Tooltip,
Legend,
PointElement,
LineElement,
Filler,
@ -122,7 +102,7 @@ export default {
do {
response = await GET(`${this.repoLink}/activity/contributors/data`);
if (response.status === 202) {
await new Promise((resolve) => setTimeout(resolve, 1000)); // wait for 1 second before retrying
await sleep(1000); // wait for 1 second before retrying
}
} while (response.status === 202);
if (response.ok) {
@ -222,7 +202,7 @@ export default {
pointRadius: 0,
pointHitRadius: 0,
fill: 'start',
backgroundColor: colors[this.type],
backgroundColor: chartJsColors[this.type],
borderWidth: 0,
tension: 0.3,
},
@ -254,7 +234,6 @@ export default {
title: {
display: type === 'main',
text: 'drag: zoom, shift+drag: pan, double click: reset zoom',
color: colors.title,
position: 'top',
align: 'center',
},
@ -262,9 +241,6 @@ export default {
chartType: type,
instance: this,
},
legend: {
display: false,
},
zoom: {
pan: {
enabled: true,