-
-
Notifications
You must be signed in to change notification settings - Fork 5.8k
Implement code frequency graph #29191
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
21 commits
Select commit
Hold shift + click to select a range
df172cf
Revert "Move types out from "modules/structs" to not pollute api"
sahinakkaya cdfa057
Add initial code frequency page
sahinakkaya 214a18d
Implement code frequency feature
sahinakkaya c426ecd
Fix linting errors
sahinakkaya 511c63f
Handle data generation logic
sahinakkaya 4f6f2df
Fix reference error in test file
sahinakkaya 29c064c
Reapply "Move types out from "modules/structs" to not pollute api"
sahinakkaya 50ce59c
Revert "Fix reference error in test file"
sahinakkaya ccae9a9
Extract duplicate code to seperate file
sahinakkaya 2aaa273
Apply suggestions from code review
sahinakkaya 7ab988b
Remove useless code
sahinakkaya 47f1672
Rename colors variable
sahinakkaya d1c682e
Fix linting error
sahinakkaya 645ea60
Remove unnecessary imports
sahinakkaya 2bcb7b7
Remove unnecessary imports
sahinakkaya bebc2ec
Merge branch 'main' into code-frequency-graph
GiteaBot f2c87ca
Deduplicate translations
sahinakkaya c3474aa
Merge remote-tracking branch 'upstream/main' into code-frequency-graph
sahinakkaya abdf1b8
Deduplicate translations
sahinakkaya 69dacd1
Merge remote-tracking branch 'upstream/main' into code-frequency-graph
sahinakkaya 31c4226
Merge branch 'main' into code-frequency-graph
GiteaBot File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
// Copyright 2023 The Gitea Authors. All rights reserved. | ||
// SPDX-License-Identifier: MIT | ||
|
||
package repo | ||
|
||
import ( | ||
"errors" | ||
"net/http" | ||
|
||
"code.gitea.io/gitea/modules/base" | ||
"code.gitea.io/gitea/modules/context" | ||
contributors_service "code.gitea.io/gitea/services/repository" | ||
) | ||
|
||
const ( | ||
tplCodeFrequency base.TplName = "repo/activity" | ||
) | ||
|
||
// CodeFrequency renders the page to show repository code frequency | ||
func CodeFrequency(ctx *context.Context) { | ||
ctx.Data["Title"] = ctx.Tr("repo.activity.navbar.code_frequency") | ||
|
||
ctx.Data["PageIsActivity"] = true | ||
ctx.Data["PageIsCodeFrequency"] = true | ||
ctx.PageData["repoLink"] = ctx.Repo.RepoLink | ||
|
||
ctx.HTML(http.StatusOK, tplCodeFrequency) | ||
} | ||
|
||
// CodeFrequencyData returns JSON of code frequency data | ||
func CodeFrequencyData(ctx *context.Context) { | ||
if contributorStats, err := contributors_service.GetContributorStats(ctx, ctx.Cache, ctx.Repo.Repository, ctx.Repo.CommitID); err != nil { | ||
if errors.Is(err, contributors_service.ErrAwaitGeneration) { | ||
ctx.Status(http.StatusAccepted) | ||
return | ||
} | ||
ctx.ServerError("GetCodeFrequencyData", err) | ||
} else { | ||
ctx.JSON(http.StatusOK, contributorStats["total"].Weeks) | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
{{if .Permission.CanRead $.UnitTypeCode}} | ||
<div id="repo-code-frequency-chart" | ||
data-locale-loading-title="{{ctx.Locale.Tr "graphs.component_loading" (ctx.Locale.Tr "graphs.code_frequency.what")}}" | ||
data-locale-loading-title-failed="{{ctx.Locale.Tr "graphs.component_loading_failed" (ctx.Locale.Tr "graphs.code_frequency.what")}}" | ||
data-locale-loading-info="{{ctx.Locale.Tr "graphs.component_loading_info"}}" | ||
data-locale-component-failed-to-load="{{ctx.Locale.Tr "graphs.component_failed_to_load"}}" | ||
> | ||
</div> | ||
{{end}} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,172 @@ | ||
<script> | ||
import {SvgIcon} from '../svg.js'; | ||
import { | ||
Chart, | ||
Legend, | ||
LinearScale, | ||
TimeScale, | ||
PointElement, | ||
LineElement, | ||
Filler, | ||
} from 'chart.js'; | ||
import {GET} from '../modules/fetch.js'; | ||
import {Line as ChartLine} from 'vue-chartjs'; | ||
import { | ||
startDaysBetween, | ||
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'; | ||
|
||
const {pageData} = window.config; | ||
|
||
Chart.defaults.color = chartJsColors.text; | ||
Chart.defaults.borderColor = chartJsColors.border; | ||
|
||
Chart.register( | ||
TimeScale, | ||
LinearScale, | ||
Legend, | ||
PointElement, | ||
LineElement, | ||
Filler, | ||
); | ||
|
||
export default { | ||
components: {ChartLine, SvgIcon}, | ||
props: { | ||
locale: { | ||
type: Object, | ||
required: true | ||
}, | ||
}, | ||
data: () => ({ | ||
isLoading: false, | ||
errorText: '', | ||
repoLink: pageData.repoLink || [], | ||
data: [], | ||
}), | ||
mounted() { | ||
this.fetchGraphData(); | ||
}, | ||
methods: { | ||
async fetchGraphData() { | ||
this.isLoading = true; | ||
try { | ||
let response; | ||
do { | ||
response = await GET(`${this.repoLink}/activity/code-frequency/data`); | ||
if (response.status === 202) { | ||
await sleep(1000); // wait for 1 second before retrying | ||
} | ||
} while (response.status === 202); | ||
if (response.ok) { | ||
this.data = await response.json(); | ||
const weekValues = Object.values(this.data); | ||
const start = weekValues[0].week; | ||
const end = firstStartDateAfterDate(new Date()); | ||
const startDays = startDaysBetween(new Date(start), new Date(end)); | ||
this.data = fillEmptyStartDaysWithZeroes(startDays, this.data); | ||
this.errorText = ''; | ||
} else { | ||
this.errorText = response.statusText; | ||
} | ||
} catch (err) { | ||
this.errorText = err.message; | ||
} finally { | ||
this.isLoading = false; | ||
} | ||
}, | ||
|
||
toGraphData(data) { | ||
return { | ||
datasets: [ | ||
{ | ||
data: data.map((i) => ({x: i.week, y: i.additions})), | ||
pointRadius: 0, | ||
pointHitRadius: 0, | ||
fill: true, | ||
label: 'Additions', | ||
backgroundColor: chartJsColors['additions'], | ||
borderWidth: 0, | ||
tension: 0.3, | ||
}, | ||
{ | ||
data: data.map((i) => ({x: i.week, y: -i.deletions})), | ||
pointRadius: 0, | ||
pointHitRadius: 0, | ||
fill: true, | ||
label: 'Deletions', | ||
backgroundColor: chartJsColors['deletions'], | ||
borderWidth: 0, | ||
tension: 0.3, | ||
}, | ||
], | ||
}; | ||
}, | ||
|
||
getOptions() { | ||
return { | ||
responsive: true, | ||
maintainAspectRatio: false, | ||
animation: true, | ||
plugins: { | ||
legend: { | ||
display: true, | ||
}, | ||
}, | ||
scales: { | ||
x: { | ||
type: 'time', | ||
grid: { | ||
display: false, | ||
}, | ||
time: { | ||
minUnit: 'month', | ||
}, | ||
ticks: { | ||
maxRotation: 0, | ||
maxTicksLimit: 12 | ||
}, | ||
}, | ||
y: { | ||
ticks: { | ||
maxTicksLimit: 6 | ||
}, | ||
}, | ||
}, | ||
}; | ||
}, | ||
}, | ||
}; | ||
</script> | ||
<template> | ||
<div> | ||
<div class="ui header gt-df gt-ac gt-sb"> | ||
{{ isLoading ? locale.loadingTitle : errorText ? locale.loadingTitleFailed: `Code frequency over the history of ${repoLink.slice(1)}` }} | ||
</div> | ||
<div class="gt-df ui segment main-graph"> | ||
<div v-if="isLoading || errorText !== ''" class="gt-tc gt-m-auto"> | ||
<div v-if="isLoading"> | ||
<SvgIcon name="octicon-sync" class="gt-mr-3 job-status-rotate"/> | ||
{{ locale.loadingInfo }} | ||
</div> | ||
<div v-else class="text red"> | ||
<SvgIcon name="octicon-x-circle-fill"/> | ||
{{ errorText }} | ||
</div> | ||
</div> | ||
<ChartLine | ||
v-memo="data" v-if="data.length !== 0" | ||
:data="toGraphData(data)" :options="getOptions()" | ||
/> | ||
</div> | ||
</div> | ||
</template> | ||
<style scoped> | ||
.main-graph { | ||
height: 440px; | ||
} | ||
</style> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.