diff --git a/models/attachment.go b/models/attachment.go index 418d7c881..684a38b21 100755 --- a/models/attachment.go +++ b/models/attachment.go @@ -464,3 +464,12 @@ func CanDelAttachment(isSigned bool, user *User, attach *Attachment) bool { } return false } + +func GetAttachmentSizeByDatasetID(datasetID int64) (int64, error) { + total, err := x.Where("dataset_id = ?", datasetID).SumInt(&Attachment{}, "size") + if err != nil { + return 0, err + } + + return total, nil +} diff --git a/models/cloudbrain.go b/models/cloudbrain.go index c26f8a2b6..4b2bec8e6 100755 --- a/models/cloudbrain.go +++ b/models/cloudbrain.go @@ -687,7 +687,7 @@ func CanDelJob(isSigned bool, user *User, job *CloudbrainInfo) bool { return false } - if user.ID == job.UserID || user.IsAdmin || permission.AccessMode >= AccessModeAdmin { + if (user.ID == job.UserID && permission.AccessMode >= AccessModeWrite) || user.IsAdmin || permission.AccessMode >= AccessModeAdmin { return true } return false diff --git a/models/issue_comment.go b/models/issue_comment.go old mode 100644 new mode 100755 index f7017435d..60d38452c --- a/models/issue_comment.go +++ b/models/issue_comment.go @@ -1016,3 +1016,19 @@ func UpdateCommentsMigrationsByType(tp structs.GitServiceType, originalAuthorID }) return err } + +func GetCommentCountByRepoID(repoID int64) (int64, error) { + //sql := fmt.Sprintf("select count(1) from comment where issue_id in (select id from issue where repo_id = %d) and type = %d;", repoID, CommentTypeComment) + //res, err := x.Query(sql) + //if err != nil { + // return 0, err + //} + //return int64(binary.BigEndian.Uint64(res[0]["count"])), nil + + total, err := x.Where("issue_id in (select id from issue where repo_id = ?) and type = ?", repoID, CommentTypeComment).Count(&Comment{}) + if err != nil { + return 0, err + } + + return total, nil +} diff --git a/models/models.go b/models/models.go index 3927dfbf0..412148235 100755 --- a/models/models.go +++ b/models/models.go @@ -136,7 +136,7 @@ func init() { ) tablesStatistic = append(tablesStatistic, - new(FileChunk), + new(RepoStatistic), new(UserBusinessAnalysis), ) diff --git a/models/release.go b/models/release.go old mode 100644 new mode 100755 diff --git a/models/repo_list.go b/models/repo_list.go index 928e1f953..c4d8ee823 100755 --- a/models/repo_list.go +++ b/models/repo_list.go @@ -331,7 +331,7 @@ func SearchRepositoryCondition(opts *SearchRepoOptions) builder.Cond { } if opts.TopicName != "" { var subQueryCond = builder.NewCond() - subQueryCond = subQueryCond.Or(builder.Eq{"topic.name": opts.TopicName}) + subQueryCond = subQueryCond.Or(builder.Eq{"topic.name": strings.ToLower(opts.TopicName)}) subQuery := builder.Select("repo_topic.repo_id").From("repo_topic"). Join("INNER", "topic", "topic.id = repo_topic.topic_id"). Where(subQueryCond). diff --git a/models/repo_statistic.go b/models/repo_statistic.go new file mode 100755 index 000000000..b987f4f46 --- /dev/null +++ b/models/repo_statistic.go @@ -0,0 +1,60 @@ +package models + +import ( + "code.gitea.io/gitea/modules/timeutil" + "fmt" +) + +// RepoStatistic statistic info of all repository +type RepoStatistic struct { + ID int64 `xorm:"pk autoincr"` + RepoID int64 `xorm:"unique(s) NOT NULL"` + Date string `xorm:"unique(s) NOT NULL"` + NumWatches int64 `xorm:"NOT NULL DEFAULT 0"` + NumStars int64 `xorm:"NOT NULL DEFAULT 0"` + NumForks int64 `xorm:"NOT NULL DEFAULT 0"` + NumDownloads int64 `xorm:"NOT NULL DEFAULT 0"` + NumComments int64 `xorm:"NOT NULL DEFAULT 0"` + NumVisits int64 `xorm:"NOT NULL DEFAULT 0"` + NumClosedIssues int64 `xorm:"NOT NULL DEFAULT 0"` + NumVersions int64 `xorm:"NOT NULL DEFAULT 0"` + //develop months + NumDevMonths int64 `xorm:"NOT NULL DEFAULT 0"` + RepoSize int64 `xorm:"NOT NULL DEFAULT 0"` + DatasetSize int64 `xorm:"NOT NULL DEFAULT 0"` + NumModels int64 `xorm:"NOT NULL DEFAULT 0"` + NumWikiViews int64 `xorm:"NOT NULL DEFAULT 0"` + NumCommits int64 `xorm:"NOT NULL DEFAULT 0"` + NumIssues int64 `xorm:"NOT NULL DEFAULT 0"` + NumPulls int64 `xorm:"NOT NULL DEFAULT 0"` + IssueFixedRate float32 `xorm:"NOT NULL"` + NumContributor int64 `xorm:"NOT NULL DEFAULT 0"` + NumKeyContributor int64 `xorm:"NOT NULL DEFAULT 0"` + + CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` + UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` +} + +func DeleteRepoStatDaily(date string) error { + sess := xStatistic.NewSession() + defer sess.Close() + if err := sess.Begin(); err != nil { + return fmt.Errorf("Begin: %v", err) + } + + if _, err := sess.Where("date = ?", date).Delete(&RepoStatistic{}); err != nil { + return fmt.Errorf("Delete: %v", err) + } + + if err := sess.Commit(); err != nil { + sess.Close() + return fmt.Errorf("Commit: %v", err) + } + + sess.Close() + return nil +} + +func InsertRepoStat(repoStat *RepoStatistic) (int64, error) { + return xStatistic.Insert(repoStat) +} diff --git a/modules/cron/tasks_basic.go b/modules/cron/tasks_basic.go old mode 100644 new mode 100755 index f42710618..26cd16778 --- a/modules/cron/tasks_basic.go +++ b/modules/cron/tasks_basic.go @@ -163,6 +163,28 @@ func registerHandleBlockChainUnSuccessCommits() { }) } +func registerHandleRepoStatistic() { + RegisterTaskFatal("handle_repo_statistic", &BaseConfig{ + Enabled: true, + RunAtStart: false, + Schedule: "@daily", + }, func(ctx context.Context, _ *models.User, _ Config) error { + repo.RepoStatisticAuto() + return nil + }) +} + +func registerHandleUserStatistic() { + RegisterTaskFatal("handle_user_statistic", &BaseConfig{ + Enabled: true, + RunAtStart: false, + Schedule: "@daily", + }, func(ctx context.Context, _ *models.User, _ Config) error { + repo.TimingCountData() + return nil + }) +} + func initBasicTasks() { registerUpdateMirrorTask() registerRepoHealthCheck() @@ -177,4 +199,7 @@ func initBasicTasks() { registerHandleBlockChainUnSuccessRepos() registerHandleBlockChainMergedPulls() registerHandleBlockChainUnSuccessCommits() + + registerHandleRepoStatistic() + registerHandleUserStatistic() } diff --git a/routers/private/internal.go b/routers/private/internal.go index 9d5f7b31c..b254d48ba 100755 --- a/routers/private/internal.go +++ b/routers/private/internal.go @@ -42,7 +42,8 @@ func RegisterRoutes(m *macaron.Macaron) { m.Post("/manager/shutdown", Shutdown) m.Post("/manager/restart", Restart) m.Post("/manager/flush-queues", bind(private.FlushOptions{}), FlushQueues) - m.Post("/cmd/update_all_repo_commit_cnt", UpdateAllRepoCommitCnt) + m.Post("/tool/update_all_repo_commit_cnt", UpdateAllRepoCommitCnt) + m.Post("/tool/repo_stat", RepoStatisticManually) }, CheckInternalToken) } diff --git a/routers/private/cmd.go b/routers/private/tool.go similarity index 87% rename from routers/private/cmd.go rename to routers/private/tool.go index 3c44ae697..a7a7bee9d 100755 --- a/routers/private/cmd.go +++ b/routers/private/tool.go @@ -5,11 +5,13 @@ package private import ( - "gitea.com/macaron/macaron" "net/http" "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/routers/repo" + + "gitea.com/macaron/macaron" ) func UpdateAllRepoCommitCnt(ctx *macaron.Context) { @@ -35,3 +37,8 @@ func UpdateAllRepoCommitCnt(ctx *macaron.Context) { "error_msg": "", }) } + +func RepoStatisticManually(ctx *macaron.Context) { + date := ctx.Query("date") + repo.RepoStatisticDaily(date) +} diff --git a/routers/repo/repo_statistic.go b/routers/repo/repo_statistic.go new file mode 100755 index 000000000..ceb410958 --- /dev/null +++ b/routers/repo/repo_statistic.go @@ -0,0 +1,122 @@ +package repo + +import ( + "time" + + "code.gitea.io/gitea/models" + "code.gitea.io/gitea/modules/log" +) + +//auto daily or manually +func RepoStatisticAuto() { + log.Info("", time.Now()) + yesterday := time.Now().AddDate(0, 0, -1).Format("2006-01-02") + RepoStatisticDaily(yesterday) +} + +func RepoStatisticDaily(date string) { + log.Info("%s", date) + if err := models.DeleteRepoStatDaily(date); err != nil { + log.Error("DeleteRepoStatDaily failed: %v", err.Error()) + return + } + + repos, err := models.GetAllRepositories() + if err != nil { + log.Error("GetAllRepositories failed: %v", err.Error()) + return + } + + for _, repo := range repos { + log.Info("start statistic: %s", repo.Name) + repoGitStat, err := models.GetRepoKPIStats(repo) + if err != nil { + log.Error("GetRepoKPIStats failed: %s", repo.Name) + log.Error("failed statistic: %s", repo.Name) + continue + } + + var issueFixedRate float32 + if repo.NumIssues != 0 { + issueFixedRate = float32(repo.NumClosedIssues) / float32(repo.NumIssues) + } + + numVersions, err := models.GetReleaseCountByRepoID(repo.ID, models.FindReleasesOptions{}) + if err != nil { + log.Error("GetReleaseCountByRepoID failed: %s", repo.Name) + log.Error("failed statistic: %s", repo.Name) + continue + } + + datasetSize, err := getDatasetSize(repo) + if err != nil { + log.Error("getDatasetSize failed: %s", repo.Name) + log.Error("failed statistic: %s", repo.Name) + continue + } + + numComments, err := models.GetCommentCountByRepoID(repo.ID) + if err != nil { + log.Error("GetCommentCountByRepoID failed: %s", repo.Name) + log.Error("failed statistic: %s", repo.Name) + continue + } + + //beginTime, endTime := getStatTime(date) + //numVisits := repository.AppointProjectView(repo.OwnerName, repo.Name, beginTime, endTime) + numVisits := 0 + + repoStat := models.RepoStatistic{ + RepoID: repo.ID, + Date: date, + NumWatches: int64(repo.NumWatches), + NumStars: int64(repo.NumStars), + NumDownloads: repo.CloneCnt, + NumComments: numComments, + NumVisits: int64(numVisits), + NumClosedIssues: int64(repo.NumClosedIssues), + NumVersions: numVersions, + NumDevMonths: repoGitStat.DevelopAge, + RepoSize: repo.Size, + DatasetSize: datasetSize, + NumModels: 0, + NumWikiViews: repoGitStat.WikiPages, + NumCommits: repo.NumCommit, + NumIssues: int64(repo.NumIssues), + NumPulls: int64(repo.NumPulls), + IssueFixedRate: issueFixedRate, + NumContributor: repoGitStat.Contributors, + NumKeyContributor: repoGitStat.KeyContributors, + } + + if _, err = models.InsertRepoStat(&repoStat); err != nil { + log.Error("InsertRepoStat failed: %s", repo.Name) + log.Error("failed statistic: %s", repo.Name) + continue + } + + log.Info("finish statistic: %s", repo.Name) + } + +} + +func getDatasetSize(repo *models.Repository) (int64, error) { + dataset, err := models.GetDatasetByRepo(repo) + if err != nil { + return 0, err + } + + return models.GetAttachmentSizeByDatasetID(dataset.ID) +} + +func getStatTime(timeStr string) (string, string) { + t, _ := time.Parse("2006-01-02", timeStr) + timeNumber := t.Unix() + beginTimeNumber := timeNumber - 8*60*60 + endTimeNumber := timeNumber + 16*60*60 + beginTime := time.Unix(beginTimeNumber, 0).Format(time.RFC3339) + endTime := time.Unix(endTimeNumber, 0).Format(time.RFC3339) + log.Info("%s, %s", beginTime, endTime) + + return beginTime, endTime +} diff --git a/routers/repo/user_data_analysis.go b/routers/repo/user_data_analysis.go old mode 100644 new mode 100755 index 2d9c03e1d..3260780ac --- a/routers/repo/user_data_analysis.go +++ b/routers/repo/user_data_analysis.go @@ -8,7 +8,7 @@ import ( "code.gitea.io/gitea/modules/log" ) -func TimeingCountData() { +func TimingCountData() { //query wiki data log.Info("start to time count data") wikiMap := make(map[string]int) diff --git a/templates/repo/cloudbrain/index.tmpl b/templates/repo/cloudbrain/index.tmpl index 0626f57c6..3af96998c 100755 --- a/templates/repo/cloudbrain/index.tmpl +++ b/templates/repo/cloudbrain/index.tmpl @@ -318,7 +318,11 @@
- + {{if .User.Name}} + + {{else}} + + {{end}}
diff --git a/templates/repo/datasets/dataset_list.tmpl b/templates/repo/datasets/dataset_list.tmpl index 47716418a..5cb35aa77 100755 --- a/templates/repo/datasets/dataset_list.tmpl +++ b/templates/repo/datasets/dataset_list.tmpl @@ -5,7 +5,7 @@ {{range .Attachments}}
-
+
+ {{if .User.Name}} + {{else}} + + {{end}}
diff --git a/web_src/js/components/EditTopics.vue b/web_src/js/components/EditTopics.vue index 5aa5e6e7a..bf50452ec 100644 --- a/web_src/js/components/EditTopics.vue +++ b/web_src/js/components/EditTopics.vue @@ -148,29 +148,37 @@ export default { params:this.params }).then((res)=>{ this.array = res.data.topics - + this.array.forEach((element,index) => { + + if (this.arrayTopics.indexOf(element.topic_name)>-1){ - this.showInitTopic.push(true) - - }else{ + } + else{ this.showInitTopic.push(false) } + this.showInputValue = true + }); + let findelement = this.array.some((item)=>{ + + return item.topic_name===this.input + }) + this.showInputValue = !findelement - }); }) - this.showInputValue = true + this.showSearchTopic = true } this.showAddTopic = false + }, @@ -201,6 +209,9 @@ export default { }) }, postTopic(){ + if(!this.showInputValue){ + return + } const patter = /^[\u4e00-\u9fa5a-zA-Z0-9][\u4e00-\u9fa5a-zA-Z0-9-]{0,34}$/ let regexp = patter.test(this.input) if(!regexp){ @@ -249,7 +260,7 @@ export default { this.Post(data,topics) if(this.arrayTopics.length===0){ - console.log("add postTopic") + $('#repo-topics1').append('暂无标签') }else{ $('#repo-topics1').children('span').remove() @@ -282,7 +293,9 @@ export default { this.input = '' if (this.input === ''){ + this.array = this.arrayTopics + let data = [] this.showInitTopic = [] this.array.forEach((element,index) => { @@ -301,6 +314,7 @@ export default { this.showInputValue = false this.showSearchTopic = true + this.showAddTopic = false } stopPropagation(e); @@ -332,30 +346,30 @@ computed:{ }, watch: { - input(newValue){ + // input(newValue){ - if (newValue === ''){ - this.array = this.arrayTopics - let data = [] - this.showInitTopic = [] - this.array.forEach((element,index) => { + // if (newValue === ''){ + // this.array = this.arrayTopics + // let data = [] + // this.showInitTopic = [] + // this.array.forEach((element,index) => { - let item = {} - item.topic_name = element + // let item = {} + // item.topic_name = element - data.push(item) - this.showInitTopic.push(true) + // data.push(item) + // this.showInitTopic.push(true) - }); + // }); - this.array = data + // this.array = data - this.showInputValue = false - this.showSearchTopic = true - } - } + // this.showInputValue = false + // this.showSearchTopic = true + // } + // } }, mounted() { const context = this