|
|
|
@@ -20,8 +20,10 @@ import ( |
|
|
|
|
|
|
|
const DEFAULT_PAGE_SIZE = 10 |
|
|
|
const DATE_FORMAT = "2006-01-02" |
|
|
|
const MONTH_FORMAT = "2006-01" |
|
|
|
const EXCEL_DATE_FORMAT = "20060102" |
|
|
|
const CREATE_TIME_FORMAT = "2006/01/02 15:04:05" |
|
|
|
const UPDATE_TIME_FORMAT = "2006-01-02 15:04:05" |
|
|
|
|
|
|
|
type ProjectsPeriodData struct { |
|
|
|
RecordBeginTime string `json:"recordBeginTime"` |
|
|
|
@@ -60,6 +62,40 @@ type ProjectLatestData struct { |
|
|
|
Top10 []UserInfo `json:"top10"` |
|
|
|
} |
|
|
|
|
|
|
|
type ProjectSummaryBaseData struct { |
|
|
|
NumReposAdd int64 `json:"numReposAdd"` |
|
|
|
NumRepoPublicAdd int64 `json:"numRepoPublicAdd"` |
|
|
|
NumRepoPrivateAdd int64 `json:"numRepoPrivateAdd"` |
|
|
|
NumRepoForkAdd int64 `json:"numRepoForkAdd"` |
|
|
|
NumRepoMirrorAdd int64 `json:"numRepoMirrorAdd"` |
|
|
|
NumRepoSelfAdd int64 `json:"numRepoSelfAdd"` |
|
|
|
NumRepos int64 `json:"numRepos"` |
|
|
|
CreatTime string `json:"creatTime"` |
|
|
|
} |
|
|
|
|
|
|
|
type ProjectSummaryData struct { |
|
|
|
ProjectSummaryBaseData |
|
|
|
NumRepoPublic int64 `json:"numRepoPublic"` |
|
|
|
NumRepoPrivate int64 `json:"numRepoPrivate"` |
|
|
|
NumRepoFork int64 `json:"numRepoFork"` |
|
|
|
NumRepoMirror int64 `json:"numRepoMirror"` |
|
|
|
NumRepoSelf int64 `json:"numRepoSelf"` |
|
|
|
|
|
|
|
NumRepoOrgAdd int64 `json:"numRepoOrgAdd"` |
|
|
|
NumRepoNotOrgAdd int64 `json:"numRepoNotOrgAdd"` |
|
|
|
|
|
|
|
NumRepoOrg int64 `json:"numRepoOrg"` |
|
|
|
NumRepoNotOrg int64 `json:"numRepoNotOrg"` |
|
|
|
} |
|
|
|
|
|
|
|
type ProjectSummaryPeriodData struct { |
|
|
|
RecordBeginTime string `json:"recordBeginTime"` |
|
|
|
PageSize int `json:"pageSize"` |
|
|
|
TotalPage int `json:"totalPage"` |
|
|
|
TotalCount int64 `json:"totalCount"` |
|
|
|
PageRecords []*ProjectSummaryBaseData `json:"pageRecords"` |
|
|
|
} |
|
|
|
|
|
|
|
func RestoreForkNumber(ctx *context.Context) { |
|
|
|
repos, err := models.GetAllRepositories() |
|
|
|
if err != nil { |
|
|
|
@@ -73,6 +109,144 @@ func RestoreForkNumber(ctx *context.Context) { |
|
|
|
ctx.JSON(http.StatusOK, struct{}{}) |
|
|
|
} |
|
|
|
|
|
|
|
func GetLatestProjectsSummaryData(ctx *context.Context) { |
|
|
|
stat, err := models.GetLatest2SummaryStatistic() |
|
|
|
data := ProjectSummaryData{} |
|
|
|
if err == nil && len(stat) > 0 { |
|
|
|
data.NumRepos = stat[0].NumRepos |
|
|
|
data.NumRepoOrg = stat[0].NumRepoOrg |
|
|
|
data.NumRepoNotOrg = stat[0].NumRepos - stat[0].NumRepoOrg |
|
|
|
data.NumRepoFork = stat[0].NumRepoFork |
|
|
|
data.NumRepoMirror = stat[0].NumRepoMirror |
|
|
|
data.NumRepoSelf = stat[0].NumRepoSelf |
|
|
|
data.NumRepoPrivate = stat[0].NumRepoPrivate |
|
|
|
data.NumRepoPublic = stat[0].NumRepoPublic |
|
|
|
data.CreatTime = stat[0].CreatedUnix.Format(UPDATE_TIME_FORMAT) |
|
|
|
if len(stat) == 2 { |
|
|
|
data.NumReposAdd = stat[0].NumRepos - stat[1].NumRepos |
|
|
|
data.NumRepoOrgAdd = stat[0].NumRepoOrg - stat[1].NumRepoOrg |
|
|
|
data.NumRepoNotOrgAdd = (stat[0].NumRepos - stat[0].NumRepoOrg) - (stat[1].NumRepos - stat[1].NumRepoOrg) |
|
|
|
data.NumRepoForkAdd = stat[0].NumRepoFork - stat[1].NumRepoFork |
|
|
|
data.NumRepoMirrorAdd = stat[0].NumRepoMirror - stat[1].NumRepoMirror |
|
|
|
data.NumRepoSelfAdd = stat[0].NumRepoSelf - stat[1].NumRepoSelf |
|
|
|
data.NumRepoPrivateAdd = stat[0].NumRepoPrivate - stat[1].NumRepoPrivate |
|
|
|
data.NumRepoPublicAdd = stat[0].NumRepoPublic - stat[1].NumRepoPublic |
|
|
|
} |
|
|
|
} |
|
|
|
ctx.JSON(200, data) |
|
|
|
} |
|
|
|
|
|
|
|
func GetProjectsSummaryData(ctx *context.Context) { |
|
|
|
|
|
|
|
var datas = make([]*ProjectSummaryBaseData, 0) |
|
|
|
|
|
|
|
recordBeginTime, err := getRecordBeginTime() |
|
|
|
if err != nil { |
|
|
|
log.Error("Can not get record begin time", err) |
|
|
|
ctx.Error(http.StatusBadRequest, ctx.Tr("repo.record_begintime_get_err")) |
|
|
|
return |
|
|
|
} |
|
|
|
beginTime, endTime, err := getTimePeroid(ctx, recordBeginTime) |
|
|
|
|
|
|
|
beginTime = beginTime.AddDate(0, 0, -1) |
|
|
|
|
|
|
|
queryType := ctx.QueryTrim("type") |
|
|
|
|
|
|
|
page := ctx.QueryInt("page") |
|
|
|
if page <= 0 { |
|
|
|
page = 1 |
|
|
|
} |
|
|
|
pageSize := ctx.QueryInt("pagesize") |
|
|
|
if pageSize <= 0 { |
|
|
|
pageSize = DEFAULT_PAGE_SIZE |
|
|
|
} |
|
|
|
var count int64 |
|
|
|
|
|
|
|
if queryType == "all" || queryType == "current_year" { |
|
|
|
dates := getEndOfMonthDates(beginTime, endTime) |
|
|
|
count, _ = models.GetSummaryStatisticByDateCount(dates) |
|
|
|
stats, err := models.GetSummaryStatisticByDates(dates, page, pageSize) |
|
|
|
if err != nil { |
|
|
|
log.Warn("can not get summary data", err) |
|
|
|
} else { |
|
|
|
|
|
|
|
for i, v := range stats { |
|
|
|
if i == 0 { |
|
|
|
continue |
|
|
|
} |
|
|
|
data := ProjectSummaryBaseData{} |
|
|
|
setStatisticsData(&data, v, stats[i-1]) |
|
|
|
createTime, _ := time.Parse(DATE_FORMAT, v.Date) |
|
|
|
data.CreatTime = createTime.Format(MONTH_FORMAT) |
|
|
|
datas = append(datas, &data) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} else { |
|
|
|
count, _ = models.GetSummaryStatisticByTimeCount(beginTime, endTime) |
|
|
|
stats, err := models.GetSummaryStatisticByTime(beginTime, endTime, page, pageSize) |
|
|
|
if err != nil { |
|
|
|
log.Warn("can not get summary data", err) |
|
|
|
} else { |
|
|
|
|
|
|
|
for i, v := range stats { |
|
|
|
if i == 0 { |
|
|
|
continue |
|
|
|
} |
|
|
|
data := ProjectSummaryBaseData{} |
|
|
|
setStatisticsData(&data, v, stats[i-1]) |
|
|
|
data.CreatTime = v.Date |
|
|
|
datas = append(datas, &data) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
projectSummaryPeriodData := ProjectSummaryPeriodData{ |
|
|
|
TotalCount: count - 1, |
|
|
|
TotalPage: getTotalPage(count-1, pageSize), |
|
|
|
RecordBeginTime: recordBeginTime.Format(DATE_FORMAT), |
|
|
|
PageSize: pageSize, |
|
|
|
PageRecords: datas, |
|
|
|
} |
|
|
|
|
|
|
|
ctx.JSON(200, projectSummaryPeriodData) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
func setStatisticsData(data *ProjectSummaryBaseData, v *models.SummaryStatistic, stats *models.SummaryStatistic) { |
|
|
|
data.NumReposAdd = v.NumRepos - stats.NumRepos |
|
|
|
data.NumRepoPublicAdd = v.NumRepoPublic - stats.NumRepoPublic |
|
|
|
data.NumRepoPrivateAdd = v.NumRepoPrivate - stats.NumRepoPrivate |
|
|
|
data.NumRepoMirrorAdd = v.NumRepoMirror - stats.NumRepoMirror |
|
|
|
data.NumRepoForkAdd = v.NumRepoFork - stats.NumRepoFork |
|
|
|
data.NumRepoSelfAdd = v.NumRepoSelf - stats.NumRepoSelf |
|
|
|
|
|
|
|
data.NumRepos = v.NumRepos |
|
|
|
} |
|
|
|
|
|
|
|
func getEndOfMonthDates(beginTime time.Time, endTime time.Time) []string { |
|
|
|
var dates = []string{} |
|
|
|
date := endOfMonth(beginTime.AddDate(0, -1, 0)) |
|
|
|
dates = append(dates, date.Format(DATE_FORMAT)) |
|
|
|
|
|
|
|
tempDate := endOfMonth(beginTime) |
|
|
|
|
|
|
|
for { |
|
|
|
if tempDate.Before(endTime) { |
|
|
|
dates = append(dates, tempDate.Format(DATE_FORMAT)) |
|
|
|
tempDate = endOfMonth(tempDate.AddDate(0, 0, 1)) |
|
|
|
} else { |
|
|
|
break |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return dates |
|
|
|
} |
|
|
|
|
|
|
|
func endOfMonth(date time.Time) time.Time { |
|
|
|
return date.AddDate(0, 1, -date.Day()) |
|
|
|
} |
|
|
|
|
|
|
|
func GetAllProjectsPeriodStatistics(ctx *context.Context) { |
|
|
|
|
|
|
|
recordBeginTime, err := getRecordBeginTime() |
|
|
|
@@ -210,6 +384,118 @@ func ServeAllProjectsPeriodStatisticsFile(ctx *context.Context) { |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
func GetProjectsSummaryDataFile(ctx *context.Context) { |
|
|
|
|
|
|
|
recordBeginTime, err := getRecordBeginTime() |
|
|
|
if err != nil { |
|
|
|
log.Error("Can not get record begin time", err) |
|
|
|
ctx.Error(http.StatusBadRequest, ctx.Tr("repo.record_begintime_get_err")) |
|
|
|
return |
|
|
|
} |
|
|
|
beginTime, endTime, err := getTimePeroid(ctx, recordBeginTime) |
|
|
|
beginTime = beginTime.AddDate(0, 0, -1) |
|
|
|
if err != nil { |
|
|
|
log.Error("Parameter is wrong", err) |
|
|
|
ctx.Error(http.StatusBadRequest, ctx.Tr("repo.parameter_is_wrong")) |
|
|
|
return |
|
|
|
} |
|
|
|
|
|
|
|
page := ctx.QueryInt("page") |
|
|
|
if page <= 0 { |
|
|
|
page = 1 |
|
|
|
} |
|
|
|
pageSize := 100 |
|
|
|
|
|
|
|
if err != nil { |
|
|
|
log.Error("Can not query the last updated time.", err) |
|
|
|
ctx.Error(http.StatusBadRequest, ctx.Tr("repo.last_update_time_error")) |
|
|
|
return |
|
|
|
} |
|
|
|
|
|
|
|
var projectAnalysis = ctx.Tr("repo.repo_stat_develop") |
|
|
|
fileName := getSummaryFileName(ctx, beginTime, endTime, projectAnalysis) |
|
|
|
|
|
|
|
f := excelize.NewFile() |
|
|
|
|
|
|
|
index := f.NewSheet(projectAnalysis) |
|
|
|
f.DeleteSheet("Sheet1") |
|
|
|
|
|
|
|
for k, v := range allProjectsPeriodSummaryHeader(ctx) { |
|
|
|
f.SetCellValue(projectAnalysis, k, v) |
|
|
|
} |
|
|
|
|
|
|
|
var total int64 |
|
|
|
queryType := ctx.QueryTrim("type") |
|
|
|
row := 2 |
|
|
|
|
|
|
|
if queryType == "all" || queryType == "current_year" { |
|
|
|
dates := getEndOfMonthDates(beginTime, endTime) |
|
|
|
total, _ = models.GetSummaryStatisticByDateCount(dates) |
|
|
|
totalPage := getTotalPage(total, pageSize) |
|
|
|
|
|
|
|
for i := 0; i < totalPage; i++ { |
|
|
|
|
|
|
|
stats, err := models.GetSummaryStatisticByDates(dates, i+1, pageSize) |
|
|
|
if err != nil { |
|
|
|
log.Warn("can not get summary data", err) |
|
|
|
} else { |
|
|
|
for j, v := range stats { |
|
|
|
if j == 0 { |
|
|
|
continue |
|
|
|
} |
|
|
|
data := ProjectSummaryBaseData{} |
|
|
|
setStatisticsData(&data, v, stats[j-1]) |
|
|
|
createTime, _ := time.Parse(DATE_FORMAT, v.Date) |
|
|
|
data.CreatTime = createTime.Format(MONTH_FORMAT) |
|
|
|
|
|
|
|
for k, v := range allProjectsPeriodSummaryValues(row, &data, ctx) { |
|
|
|
f.SetCellValue(projectAnalysis, k, v) |
|
|
|
} |
|
|
|
row++ |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else { |
|
|
|
total, _ = models.GetSummaryStatisticByTimeCount(beginTime, endTime) |
|
|
|
totalPage := getTotalPage(total, pageSize) |
|
|
|
|
|
|
|
for i := 0; i < totalPage; i++ { |
|
|
|
|
|
|
|
stats, err := models.GetSummaryStatisticByTime(beginTime, endTime, i+1, pageSize) |
|
|
|
if err != nil { |
|
|
|
log.Warn("can not get summary data", err) |
|
|
|
} else { |
|
|
|
for j, v := range stats { |
|
|
|
if j == 0 { |
|
|
|
continue |
|
|
|
} |
|
|
|
data := ProjectSummaryBaseData{} |
|
|
|
setStatisticsData(&data, v, stats[j-1]) |
|
|
|
data.CreatTime = v.Date |
|
|
|
|
|
|
|
for k, v := range allProjectsPeriodSummaryValues(row, &data, ctx) { |
|
|
|
f.SetCellValue(projectAnalysis, k, v) |
|
|
|
} |
|
|
|
row++ |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
f.SetActiveSheet(index) |
|
|
|
|
|
|
|
ctx.Resp.Header().Set("Content-Disposition", "attachment; filename="+url.QueryEscape(fileName)) |
|
|
|
ctx.Resp.Header().Set("Content-Type", "application/octet-stream") |
|
|
|
|
|
|
|
f.WriteTo(ctx.Resp) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
func ServeAllProjectsOpenIStatisticsFile(ctx *context.Context) { |
|
|
|
|
|
|
|
page := ctx.QueryInt("page") |
|
|
|
@@ -290,6 +576,20 @@ func getFileName(ctx *context.Context, beginTime time.Time, endTime time.Time, p |
|
|
|
return frontName |
|
|
|
} |
|
|
|
|
|
|
|
func getSummaryFileName(ctx *context.Context, beginTime time.Time, endTime time.Time, projectAnalysis string) string { |
|
|
|
baseName := projectAnalysis + "_" |
|
|
|
|
|
|
|
if ctx.QueryTrim("type") == "all" { |
|
|
|
baseName = baseName + ctx.Tr("repo.all") |
|
|
|
} else if ctx.QueryTrim("type") == "current_year" { |
|
|
|
baseName = baseName + ctx.Tr("repo.current_year") |
|
|
|
} else { |
|
|
|
baseName = baseName + beginTime.Format(EXCEL_DATE_FORMAT) + "_" + endTime.AddDate(0, 0, -1).Format(EXCEL_DATE_FORMAT) |
|
|
|
} |
|
|
|
frontName := baseName + ".xlsx" |
|
|
|
return frontName |
|
|
|
} |
|
|
|
|
|
|
|
func allProjectsPeroidHeader(ctx *context.Context) map[string]string { |
|
|
|
|
|
|
|
return map[string]string{"A1": ctx.Tr("admin.repos.id"), "B1": ctx.Tr("admin.repos.projectName"), "C1": ctx.Tr("repo.owner"), "D1": ctx.Tr("admin.repos.isPrivate"), "E1": ctx.Tr("admin.repos.openi"), "F1": ctx.Tr("admin.repos.visit"), "G1": ctx.Tr("admin.repos.download"), "H1": ctx.Tr("admin.repos.pr"), "I1": ctx.Tr("admin.repos.commit"), |
|
|
|
@@ -297,6 +597,19 @@ func allProjectsPeroidHeader(ctx *context.Context) map[string]string { |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
func allProjectsPeriodSummaryHeader(ctx *context.Context) map[string]string { |
|
|
|
|
|
|
|
return map[string]string{"A1": ctx.Tr("repo.date"), "B1": ctx.Tr("repo.repo_add"), "C1": ctx.Tr("repo.repo_total"), "D1": ctx.Tr("repo.repo_public_add"), "E1": ctx.Tr("repo.repo_private_add"), "F1": ctx.Tr("repo.repo_self_add"), "G1": ctx.Tr("repo.repo_fork_add"), "H1": ctx.Tr("repo.repo_mirror_add")} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
func allProjectsPeriodSummaryValues(row int, rs *ProjectSummaryBaseData, ctx *context.Context) map[string]string { |
|
|
|
|
|
|
|
return map[string]string{getCellName("A", row): rs.CreatTime, getCellName("B", row): strconv.FormatInt(rs.NumReposAdd, 10), getCellName("C", row): strconv.FormatInt(rs.NumRepos, 10), getCellName("D", row): strconv.FormatInt(rs.NumRepoPublicAdd, 10), getCellName("E", row): strconv.FormatInt(rs.NumRepoPrivateAdd, 10), |
|
|
|
getCellName("F", row): strconv.FormatInt(rs.NumRepoSelfAdd, 10), getCellName("G", row): strconv.FormatInt(rs.NumRepoForkAdd, 10), getCellName("H", row): strconv.FormatInt(rs.NumRepoMirrorAdd, 10), |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
func allProjectsPeroidValues(row int, rs *models.RepoStatistic, ctx *context.Context) map[string]string { |
|
|
|
return map[string]string{getCellName("A", row): strconv.FormatInt(rs.RepoID, 10), getCellName("B", row): rs.DisplayName(), getCellName("C", row): rs.OwnerName, getCellName("D", row): getBoolDisplay(rs.IsPrivate, ctx), getCellName("E", row): strconv.FormatFloat(rs.RadarTotal, 'f', 2, 64), |
|
|
|
getCellName("F", row): strconv.FormatInt(rs.NumVisits, 10), getCellName("G", row): strconv.FormatInt(rs.NumDownloads, 10), getCellName("H", row): strconv.FormatInt(rs.NumPulls, 10), getCellName("I", row): strconv.FormatInt(rs.NumCommits, 10), |
|
|
|
|