[platform, project] statistical interface implementation

This commit is contained in:
hcxm 2021-01-29 10:51:39 +08:00
parent 498a012e82
commit 9c92113a43
5 changed files with 587 additions and 18 deletions

160
models/action_ext.go Normal file
View File

@ -0,0 +1,160 @@
package models
import "strings"
// GetFeedsOptions options for retrieving feeds
type GetContributorsOptionsExt struct {
RepoId int64
UserId int64
}
type ContributorsDto struct {
Contributions int64 `json:"contributions"`
ID int64 `json:"id"`
Login string `json:"login"`
//Type string `json:"type"`
}
func GetContributors(opt GetContributorsOptionsExt) (interface{}, error) {
sql:=
`select a.act_user_id as id ,
u.name as login,
count(act_user_id) as contributions
from action a
left join user u on a.act_user_id=u.id
where repo_id=? and user_id=?
group by repo_id,act_user_id `
result:=make([]ContributorsDto,0,0)
err:=x.SQL(sql,opt.RepoId,opt.UserId).Find(&result)
return result,err
}
type GetGetActivityOptions struct {
FromDateUnix int64 `json:"-"`
ToDateUnix int64 `json:"-"`
FromDate string `json:"from_date"`
ToDate string `json:"to_date"`
Top int64 `json:"-"`
}
type PlatformDTO struct {
Id int64 `json:"-"`
Name string `json:"-"`
TotalCount int64 `json:"total_count"`
ActiveCount int64 `json:"active_count"`
}
//平台所需数据;
func GetActivity(opt *GetGetActivityOptions) (interface{}, error) {
//sql:=
// `select a.id,a.name,ifNull(b.active_count,0) as active_count,t.total_count
// from ( select 11 as id ,'PullRequest' name union
// select 5 as id, 'Commit' name
// ) a
// left join (
// select op_type, count(op_type) as active_count
// from action a
// where (a.op_type=11 or a.op_type=5)
// and (created_unix>=? and created_unix<=?)
// group by a.op_type
// ) b on a.id=b.op_type
// left join (
// select op_type, count(op_type) as total_count
// from action a
// where (a.op_type=11 or a.op_type=5)
// group by a.op_type
// ) t on a.id=t.op_type
//`
sql:=`select a.id,a.name,ifNull(b.active_count,0) as active_count,b.total_count
from ( select 11 as id ,'PullRequest' name
union
select 5 as id, 'Commit' name
) a
left join (
select op_type,count(op_type) as total_count,
sum(case when a.created_unix>=? and a.created_unix<=?
then 1 else 0 end
) as active_count
from action a
where (a.op_type=11 or a.op_type=5)
group by a.op_type
) b on a.id=b.op_type`
datalist:=make([]PlatformDTO,0,0)
err:=x.SQL(sql,opt.FromDateUnix,opt.ToDateUnix).Find(&datalist)
if err !=nil {
return nil ,err
}
convertMap:=make(map[string]interface{})
for i:=0;i<=len(datalist)-1;i++{
convertMap[strings.ToLower(datalist[i].Name)]=datalist[i]
}
//convertMap["param"]=opt
return convertMap,err
}
type ProjectDTO struct {
Id int64 `json:"-"`
Name string `json:"name"`
TotalCount int64 `json:"total_count"`
ActiveCount int64 `json:"active_count"`
}
//项目所需数据-按项目统计 top 5
func GetActivityProject(opt *GetGetActivityOptions) (interface{}, error) {
sql:=
`select repo_id as id,r.name,
count(op_type) as total_count,
sum(case when a.created_unix>=? and a.created_unix<=?
then 1 else 0 end
) as active_count
from action a
left join repository r on a.repo_id=r.id
where (a.op_type=5)
group by a.repo_id
order by total_count desc
limit ?
`
datalist:=make([]ProjectDTO,0,0)
err:=x.SQL(sql,opt.FromDateUnix,opt.ToDateUnix,opt.Top).Find(&datalist)
return datalist,err
}
//项目所需数据-按开发者统计 top 5
func GetActivityDevelop(opt *GetGetActivityOptions) (interface{}, error) {
sql:=
`select u.name as develop_name,
r.name as project_name,
count(op_type) as total_count,
sum(case when (a.created_unix>=? and a.created_unix<=?) then 1 else 0 end ) as active_count
from action a
left join repository r on a.repo_id=r.id
left join user u on a.act_user_id=u.id
where (a.op_type=5)
group by a.act_user_id,a.repo_id
order by total_count desc
limit ? `
datalist:=make([]DevelopDTO,0,0)
err:=x.SQL(sql,opt.FromDateUnix,opt.ToDateUnix,opt.Top).Find(&datalist)
return datalist,err
}
type DevelopDTO struct {
DevelopName string `json:"develop_name"`
ProjectName string `json:"project_name"`
TotalCount int64 `json:"total_count"`
ActiveCount int64 `json:"active_count"`
}

View File

@ -76,6 +76,7 @@ import (
"code.gitea.io/gitea/routers/api/v1/notify"
"code.gitea.io/gitea/routers/api/v1/org"
"code.gitea.io/gitea/routers/api/v1/repo"
report "code.gitea.io/gitea/routers/api/v1/reporter"
"code.gitea.io/gitea/routers/api/v1/settings"
_ "code.gitea.io/gitea/routers/api/v1/swagger" // for swagger generation
"code.gitea.io/gitea/routers/api/v1/user"
@ -584,6 +585,14 @@ func RegisterRoutes(m *macaron.Macaron) {
})
}, reqToken())
//数据统计
m.Group("/activity", func() {
m.Get("", report.GetActivity)
m.Get("/project", report.GetActivityProject)
m.Get("/develop", report.GetActivityDevelop)
})
m.Group("/user", func() {
m.Get("", user.GetAuthenticatedUser)
m.Combo("/emails").Get(user.ListEmails).
@ -673,14 +682,18 @@ func RegisterRoutes(m *macaron.Macaron) {
},reqToken())
m.Group("/count", func() {
m.Get("", viewfile.CommitCount)
m.Get("", viewfile.CommitCount) //****
})
m.Group("/releases", func() {
m.Get("/latest", viewfile.LatestRelease) //待确认 to do;
m.Get("/latest", viewfile.LatestRelease) //响应数据待确认 to do;
})
//
m.Group("/find", func() {
m.Get("", viewfile.FindFiles) //文件搜索 to do;
m.Get("", viewfile.FindFiles) //文件搜索 ****
})
m.Group("/contributors", func() {
m.Get("", report.GetContributors) //获取仓库的所有构建者信息 ****
})
m.Combo("").Get(reqAnyRepoReader(), repo.Get).

View File

@ -0,0 +1,243 @@
package report
import (
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/context"
"fmt"
"net/http"
"time"
)
func GetActivity(ctx *context.APIContext) {
// swagger:operation GET /activity activity activity
// ---
// summary: Statistics of commit and pull request data,Platform required data **
// produces:
// - application/json
// parameters:
// - name: from
// in: query
// description: Query begin date
// type: string
// required: false
// - name: to
// in: query
// description: Query end date
// type: string
// required: false
// responses:
// "200":
// "$ref": "#/responses/"
// "404":
// "$ref": "#/responses/notFound"
opt:=GetParamOption(ctx)
if opt==nil {
return
}
list, err := models.GetActivity(opt)
if err != nil {
ctx.ServerError("GetActivity", err)
return
}
ctx.JSON(http.StatusOK,list)
}
type PrjectDTO struct {
Project interface{} `json:"project"`
//Param struct{
// FromDate string `json:"from_date"`
// ToDate string `json:"to_date"`
//} `json:"param"`
}
func GetActivityDevelop(ctx *context.APIContext) {
// swagger:operation GET /activity/develop activity develop
// ---
// summary: Statistics of submitted data by developers **
// produces:
// - application/json
// parameters:
// - name: from
// in: query
// description: Query begin date
// type: string
// required: false
// - name: to
// in: query
// description: Query end date
// type: string
// required: false
// - name: top
// in: query
// description: Display the previous n records
// type: integer
// required: false
// responses:
// "200":
// "$ref": "#/responses"
// "404":
// "$ref": "#/responses/notFound"
opt:=GetParamOption(ctx)
if opt==nil {
return
}
list, err := models.GetActivityDevelop(opt)
if err != nil {
ctx.ServerError("GetActivityDevelop", err)
return
}
data:=DevelopDTO{Develop:list}
//data.Param.FromDate=opt.FromDate
//data.Param.ToDate=opt.ToDate
ctx.JSON(http.StatusOK,data)
}
type DevelopDTO struct {
Develop interface{} `json:"develop"`
//Param struct {
// FromDate string `json:"from_date"`
// ToDate string `json:"to_date"`
//} `json:"param"`
}
func GetActivityProject(ctx *context.APIContext) {
// swagger:operation GET /activity/project activity project
// ---
// summary: Statistics of submitted data by project **
// produces:
// - application/json
// parameters:
// - name: from
// in: query
// description: Query begin date
// type: string
// required: false
// - name: to
// in: query
// description: Query end date
// type: string
// required: false
// - name: top
// in: query
// description: Display the previous n records
// type: integer
// required: false
// responses:
// "200":
// "$ref": "#/responses"
// "404":
// "$ref": "#/responses/notFound"
opt:=GetParamOption(ctx)
if opt==nil {
return
}
list, err := models.GetActivityProject(opt)
if err != nil {
ctx.ServerError("GetActivityProject", err)
return
}
data:=PrjectDTO{Project:list}
//data.Param.FromDate=opt.FromDate
//data.Param.ToDate=opt.ToDate
ctx.JSON(http.StatusOK,data)
}
func GetContributors(ctx *context.APIContext) {
// swagger:operation GET /repos/{owner}/{repo}/contributors repository contributors
// ---
// summary: Get all builder information in the repository **
// produces:
// - application/json
// parameters:
// - name: owner
// in: path
// description: owner of the repo
// type: string
// required: true
// - name: repo
// in: path
// description: name of the repo
// type: string
// required: true
// responses:
// "200":
// "$ref": "#/responses/"
// "404":
// "$ref": "#/responses/notFound"
opt:= models.GetContributorsOptionsExt{
UserId:ctx.Repo.Owner.ID,
RepoId:ctx.Repo.Repository.ID,
}
list, err := models.GetContributors(opt)
if err != nil {
ctx.ServerError("GetFeedsExt", err)
return
}
ctx.JSON(http.StatusOK,list)
}
func GetParamOption(ctx *context.APIContext) (opt *models.GetGetActivityOptions) {
Layout:="2006-01-02 15:04:05"
//##top
top:=ctx.QueryInt64("top")
if top<=0 {
top=5
}else if top>=20 {
top=20
}
//##from
from:=ctx.QueryTrim("from")
if from=="" {
ctx.Error(http.StatusBadRequest,"param.from", fmt.Errorf("请指定from参数"))
return
//from=time.Now().Format("2006-01-02")
}
if len(from)<=10 {
from = from + " 00:00:00"
}
t,err:= time.ParseInLocation(Layout,from,time.Local)
if err!=nil {
ctx.Error(http.StatusBadRequest,"param.from", err)
return
}
FromDate:=t.Unix()
//fmt.Println("********from:",from," ", FromDate," convert:",time.Unix( FromDate,0).Format("2006-01-02 15:04:05"))
//##to
to:=ctx.QueryTrim("to")
if to =="" {
ctx.Error(http.StatusBadRequest,"param.to", fmt.Errorf("请指定to参数"))
return
//to =time.Now().Format("2006-01-02")
}
if len(to )<=10 {
to = to + " 23:59:59"
}
t,err= time.ParseInLocation(Layout,to ,time.Local)
if err!=nil {
ctx.Error(http.StatusBadRequest,"param.to ", err)
return
}
ToDate:=t.Unix()
//fmt.Println("********to:",to ," ", ToDate," convert:",time.Unix( ToDate,0).Format(Layout))
opt= &models.GetGetActivityOptions{
FromDateUnix:FromDate,
ToDateUnix:ToDate,
FromDate:from,
ToDate:to,
Top:top,
}
return opt
}

View File

@ -4,26 +4,26 @@ import (
"bytes"
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/charset"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/lfs"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/markup"
"code.gitea.io/gitea/modules/repofiles"
repo_module "code.gitea.io/gitea/modules/repository"
"code.gitea.io/gitea/modules/setting"
"encoding/base64"
"fmt"
"gitea.com/macaron/macaron"
gotemplate "html/template"
"io/ioutil"
"net/http"
"net/url"
"path"
"path/filepath"
"strconv"
"strings"
"code.gitea.io/gitea/modules/charset"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/lfs"
"code.gitea.io/gitea/modules/markup"
"code.gitea.io/gitea/modules/setting"
"gitea.com/macaron/macaron"
)
func Map2DTO(ctx *context.APIContext) (dto *ReadmeDTO) {
@ -262,7 +262,7 @@ func CommitCount(ctx *context.APIContext) {
}
}
log.Info("********CommitCount:ref:%s", ref)
//log.Info("********CommitCount:ref:%s", ref)
var err error
if ctx.Repo.GitRepo == nil {
fmt.Println("*****ctx.Repo.GitRepo is nil ")
@ -281,13 +281,13 @@ func CommitCount(ctx *context.APIContext) {
}()
}
// Get the commit object for the ref
commit, err := ctx.Repo.GitRepo.GetCommit(ref)
if err != nil || commit==nil{
ctx.Error(http.StatusInternalServerError,"ctx.Repo.GitRepo.GetCommit", err)
return
}
//log.Info("********GetCommit:%v",commit)
ctx.Repo.Commit=commit
CommitCount,err:=ctx.Repo.Commit.CommitsCount()
@ -304,7 +304,7 @@ func CommitCount(ctx *context.APIContext) {
IncludeTags: true,
}
fmt.Println("*****************ctx.Repo.Repository.ID:",ctx.Repo.Repository.ID)
//fmt.Println("*****************ctx.Repo.Repository.ID:",ctx.Repo.Repository.ID)
ReleaseCount, err := models.GetReleaseCountByRepoID(ctx.Repo.Repository.ID, opts)
if err != nil {
ctx.ServerError("GetReleaseCountByRepoID", err)
@ -340,7 +340,6 @@ type CountDTO struct {
ReleaseCount int64 `json:"release_count"`
TagCount int64 `json:"tag_count"`
BranchCount int64 `json:"branch_count"`
}
// LatestRelease redirects to the latest release
@ -384,6 +383,7 @@ func LatestRelease(ctx *context.APIContext) {
}()
}
release, err := models.GetLatestReleaseByRepoIDExt(ctx.Repo.Repository.ID)
//fmt.Println("****************ctx.Repo.Repository.ID:",ctx.Repo.Repository.ID," ",release," ",err)
if err != nil {
@ -996,7 +996,6 @@ func getReadmeFileFromPathExt(ctx *context.APIContext, treePath, ref string) (*n
}
func FindFiles(ctx *context.APIContext) {
// swagger:operation GET /repos/{owner}/{repo}/find repository find
// ---
@ -1096,7 +1095,11 @@ func FindFileFromPathExt(ctx *context.APIContext, treePath, ref, key string) (fi
if entry.IsDir() {
continue
}
if strings.Contains(strings.ToLower(entry.Name()),strings.ToLower(key)) || key=="" {
fileName:=filepath.Base(entry.Name())
if strings.Contains(strings.ToLower(fileName),strings.ToLower(key)) || key=="" {
name := entry.Name()
//isSymlink := entry.IsLink()
//target := entry
@ -1128,7 +1131,7 @@ func FindFileFromPathExt(ctx *context.APIContext, treePath, ref, key string) (fi
Item := &SearchFileItem{
Name:name,
Name:fileName,
Path:treePath,
SHA:entry.ID.String(),
Type:entry.Type(),

View File

@ -23,6 +23,120 @@
},
"basePath": "/api/v1",
"paths": {
"/activity": {
"get": {
"produces": [
"application/json"
],
"tags": [
"activity"
],
"summary": "Statistics of commit and pull request data,Platform required data **",
"operationId": "activity",
"parameters": [
{
"type": "string",
"description": "Query begin date",
"name": "from",
"in": "query"
},
{
"type": "string",
"description": "Query end date",
"name": "to",
"in": "query"
}
],
"responses": {
"200": {
"$ref": "#/responses/"
},
"404": {
"$ref": "#/responses/notFound"
}
}
}
},
"/activity/develop": {
"get": {
"produces": [
"application/json"
],
"tags": [
"activity"
],
"summary": "Statistics of submitted data by developers **",
"operationId": "develop",
"parameters": [
{
"type": "string",
"description": "Query begin date",
"name": "from",
"in": "query"
},
{
"type": "string",
"description": "Query end date",
"name": "to",
"in": "query"
},
{
"type": "integer",
"description": "Display the previous n records",
"name": "top",
"in": "query"
}
],
"responses": {
"200": {
"$ref": "#/responses"
},
"404": {
"$ref": "#/responses/notFound"
}
}
}
},
"/activity/project": {
"get": {
"produces": [
"application/json"
],
"tags": [
"activity"
],
"summary": "Statistics of submitted data by project **",
"operationId": "project",
"parameters": [
{
"type": "string",
"description": "Query begin date",
"name": "from",
"in": "query"
},
{
"type": "string",
"description": "Query end date",
"name": "to",
"in": "query"
},
{
"type": "integer",
"description": "Display the previous n records",
"name": "top",
"in": "query"
}
],
"responses": {
"200": {
"$ref": "#/responses"
},
"404": {
"$ref": "#/responses/notFound"
}
}
}
},
"/admin/orgs": {
"get": {
"produces": [
@ -2961,6 +3075,42 @@
}
}
},
"/repos/{owner}/{repo}/contributors": {
"get": {
"produces": [
"application/json"
],
"tags": [
"repository"
],
"summary": "Get all builder information in the repository **",
"operationId": "contributors",
"parameters": [
{
"type": "string",
"description": "owner of the repo",
"name": "owner",
"in": "path",
"required": true
},
{
"type": "string",
"description": "name of the repo",
"name": "repo",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"$ref": "#/responses/"
},
"404": {
"$ref": "#/responses/notFound"
}
}
}
},
"/repos/{owner}/{repo}/count": {
"get": {
"produces": [