| @@ -17,6 +17,7 @@ require ( | |||
| gitea.com/macaron/macaron v1.4.0 | |||
| gitea.com/macaron/session v0.0.0-20191207215012-613cebf0674d | |||
| gitea.com/macaron/toolbox v0.0.0-20190822013122-05ff0fc766b7 | |||
| github.com/360EntSecGroup-Skylar/excelize/v2 v2.0.2 | |||
| github.com/BurntSushi/toml v0.3.1 | |||
| github.com/PuerkitoBio/goquery v1.5.0 | |||
| github.com/RichardKnop/machinery v1.6.9 | |||
| @@ -107,7 +108,6 @@ require ( | |||
| github.com/unknwon/paginater v0.0.0-20151104151617-7748a72e0141 | |||
| github.com/urfave/cli v1.22.1 | |||
| github.com/xanzy/go-gitlab v0.31.0 | |||
| github.com/360EntSecGroup-Skylar/excelize/v2 v2.0.2 | |||
| github.com/yohcop/openid-go v1.0.0 | |||
| github.com/yuin/goldmark v1.1.27 | |||
| github.com/yuin/goldmark-meta v0.0.0-20191126180153-f0638e958b60 | |||
| @@ -87,7 +87,7 @@ type Cloudbrain struct { | |||
| LogUrl string //日志输出的obs路径 | |||
| PreVersionId int64 //父版本的版本id | |||
| FlavorCode string //modelarts上的规格id | |||
| Description string //描述 | |||
| Description string `xorm:"varchar(256)"` //描述 | |||
| WorkServerNumber int //节点数 | |||
| FlavorName string //规格名称 | |||
| EngineName string //引擎名称 | |||
| @@ -22,7 +22,6 @@ var customMigrations = []CustomMigration{ | |||
| } | |||
| var customMigrationsStatic = []CustomMigrationStatic{ | |||
| {"Alter user static table field type ", alterUserStaticTable}, | |||
| {"Delete organization user history data ", deleteNotDisplayUser}, | |||
| {"update issue_fixed_rate to 1 if num_issues is 0 ", updateIssueFixedRate}, | |||
| } | |||
| @@ -59,14 +58,6 @@ func syncTopicStruct(x *xorm.Engine) error { | |||
| return err | |||
| } | |||
| func alterUserStaticTable(x *xorm.Engine, static *xorm.Engine) error { | |||
| alterSql := "alter table public.user_business_analysis alter column open_i_index type double precision" | |||
| _, err := static.Exec(alterSql) | |||
| return err | |||
| } | |||
| func deleteNotDisplayUser(x *xorm.Engine, static *xorm.Engine) error { | |||
| querySQL := "select id,name from public.user where type=1" | |||
| @@ -139,6 +139,7 @@ func init() { | |||
| new(RepoStatistic), | |||
| new(SummaryStatistic), | |||
| new(UserBusinessAnalysis), | |||
| new(UserBusinessAnalysisAll), | |||
| new(UserLoginLog), | |||
| ) | |||
| @@ -172,3 +172,10 @@ func UpdateRepoStat(repoStat *RepoStatistic) error { | |||
| _, err := xStatistic.Exec(sql, repoStat.Impact, repoStat.Completeness, repoStat.Liveness, repoStat.ProjectHealth, repoStat.TeamHealth, repoStat.Growth, repoStat.RadarTotal, repoStat.RepoID, repoStat.Date) | |||
| return err | |||
| } | |||
| func UpdateRepoStatVisits(repoStat *RepoStatistic) error { | |||
| sql := "update repo_statistic set num_visits=? where repo_id=? and date=?" | |||
| _, err := xStatistic.Exec(sql, repoStat.NumVisits, repoStat.RepoID, repoStat.Date) | |||
| return err | |||
| } | |||
| @@ -4,13 +4,80 @@ import ( | |||
| "encoding/json" | |||
| "fmt" | |||
| "sort" | |||
| "strconv" | |||
| "time" | |||
| "code.gitea.io/gitea/modules/log" | |||
| "code.gitea.io/gitea/modules/timeutil" | |||
| "xorm.io/builder" | |||
| "xorm.io/xorm" | |||
| ) | |||
| type UserBusinessAnalysisAll struct { | |||
| ID int64 `xorm:"pk"` | |||
| CountDate int64 `xorm:"pk"` | |||
| //action :ActionMergePullRequest // 11 | |||
| CodeMergeCount int `xorm:"NOT NULL DEFAULT 0"` | |||
| //action :ActionCommitRepo // 5 | |||
| CommitCount int `xorm:"NOT NULL DEFAULT 0"` | |||
| //action :ActionCreateIssue // 10 | |||
| IssueCount int `xorm:"NOT NULL DEFAULT 0"` | |||
| //comment table current date | |||
| CommentCount int `xorm:"NOT NULL DEFAULT 0"` | |||
| //watch table current date | |||
| FocusRepoCount int `xorm:"NOT NULL DEFAULT 0"` | |||
| //star table current date | |||
| StarRepoCount int `xorm:"NOT NULL DEFAULT 0"` | |||
| //follow table | |||
| WatchedCount int `xorm:"NOT NULL DEFAULT 0"` | |||
| // user table | |||
| GiteaAgeMonth int `xorm:"NOT NULL DEFAULT 0"` | |||
| // | |||
| CommitCodeSize int `xorm:"NOT NULL DEFAULT 0"` | |||
| //attachement table | |||
| CommitDatasetSize int `xorm:"NOT NULL DEFAULT 0"` | |||
| //0 | |||
| CommitModelCount int `xorm:"NOT NULL DEFAULT 0"` | |||
| //issue, issueassignees | |||
| SolveIssueCount int `xorm:"NOT NULL DEFAULT 0"` | |||
| //baike | |||
| EncyclopediasCount int `xorm:"NOT NULL DEFAULT 0"` | |||
| //user | |||
| RegistDate timeutil.TimeStamp `xorm:"NOT NULL"` | |||
| //repo | |||
| CreateRepoCount int `xorm:"NOT NULL DEFAULT 0"` | |||
| //login count, from elk | |||
| LoginCount int `xorm:"NOT NULL DEFAULT 0"` | |||
| //openi index | |||
| OpenIIndex float64 `xorm:"NOT NULL DEFAULT 0"` | |||
| //user | |||
| Email string `xorm:"NOT NULL"` | |||
| //user | |||
| Name string `xorm:"NOT NULL"` | |||
| DataDate string `xorm:"NULL"` | |||
| } | |||
| type UserBusinessAnalysis struct { | |||
| ID int64 `xorm:"pk"` | |||
| @@ -93,46 +160,12 @@ func (ulist UserBusinessAnalysisList) Less(i, j int) bool { | |||
| return ulist[i].ID > ulist[j].ID | |||
| } | |||
| func QueryUserStaticData(startTime int64, endTime int64) []*UserBusinessAnalysis { | |||
| log.Info("query startTime =" + fmt.Sprint(startTime) + " endTime=" + fmt.Sprint(endTime)) | |||
| statictisSess := xStatistic.NewSession() | |||
| defer statictisSess.Close() | |||
| statictisSess.Select("*").Table("user_business_analysis").Where(" count_date>=" + fmt.Sprint(startTime) + " and count_date<=" + fmt.Sprint(endTime)).OrderBy("count_date desc") | |||
| type UserBusinessAnalysisAllList []*UserBusinessAnalysisAll | |||
| userBusinessAnalysisList := make([]*UserBusinessAnalysis, 0) | |||
| statictisSess.Find(&userBusinessAnalysisList) | |||
| resultMap := make(map[int64]*UserBusinessAnalysis) | |||
| log.Info("query result size=" + fmt.Sprint(len(userBusinessAnalysisList))) | |||
| for _, userRecord := range userBusinessAnalysisList { | |||
| if _, ok := resultMap[userRecord.ID]; !ok { | |||
| resultMap[userRecord.ID] = userRecord | |||
| } else { | |||
| resultMap[userRecord.ID].CodeMergeCount += userRecord.CodeMergeCount | |||
| resultMap[userRecord.ID].CommitCount += userRecord.CommitCount | |||
| resultMap[userRecord.ID].IssueCount += userRecord.IssueCount | |||
| resultMap[userRecord.ID].CommentCount += userRecord.CommentCount | |||
| resultMap[userRecord.ID].FocusRepoCount += userRecord.FocusRepoCount | |||
| resultMap[userRecord.ID].StarRepoCount += userRecord.StarRepoCount | |||
| resultMap[userRecord.ID].WatchedCount += userRecord.WatchedCount | |||
| resultMap[userRecord.ID].CommitCodeSize += userRecord.CommitCodeSize | |||
| resultMap[userRecord.ID].CommitDatasetSize += userRecord.CommitDatasetSize | |||
| resultMap[userRecord.ID].CommitModelCount += userRecord.CommitModelCount | |||
| resultMap[userRecord.ID].SolveIssueCount += userRecord.SolveIssueCount | |||
| resultMap[userRecord.ID].EncyclopediasCount += userRecord.EncyclopediasCount | |||
| resultMap[userRecord.ID].CreateRepoCount += userRecord.CreateRepoCount | |||
| resultMap[userRecord.ID].LoginCount += userRecord.LoginCount | |||
| } | |||
| } | |||
| userBusinessAnalysisReturnList := UserBusinessAnalysisList{} | |||
| for _, v := range resultMap { | |||
| userBusinessAnalysisReturnList = append(userBusinessAnalysisReturnList, v) | |||
| } | |||
| sort.Sort(userBusinessAnalysisReturnList) | |||
| log.Info("return size=" + fmt.Sprint(len(userBusinessAnalysisReturnList))) | |||
| return userBusinessAnalysisReturnList | |||
| func (ulist UserBusinessAnalysisAllList) Swap(i, j int) { ulist[i], ulist[j] = ulist[j], ulist[i] } | |||
| func (ulist UserBusinessAnalysisAllList) Len() int { return len(ulist) } | |||
| func (ulist UserBusinessAnalysisAllList) Less(i, j int) bool { | |||
| return ulist[i].ID > ulist[j].ID | |||
| } | |||
| func getLastCountDate() int64 { | |||
| @@ -153,6 +186,41 @@ func getLastCountDate() int64 { | |||
| return pageStartTime.Unix() | |||
| } | |||
| func QueryUserStaticDataAll(opts *UserBusinessAnalysisQueryOptions) ([]*UserBusinessAnalysisAll, int64) { | |||
| log.Info("query startTime =" + fmt.Sprint(opts.StartTime) + " endTime=" + fmt.Sprint(opts.EndTime) + " isAll=" + fmt.Sprint(opts.IsAll)) | |||
| statictisSess := xStatistic.NewSession() | |||
| defer statictisSess.Close() | |||
| allCount, err := statictisSess.Count(new(UserBusinessAnalysisAll)) | |||
| if err != nil { | |||
| log.Info("query error." + err.Error()) | |||
| return nil, 0 | |||
| } | |||
| log.Info("query return total:" + fmt.Sprint(allCount)) | |||
| if allCount == 0 { | |||
| RefreshUserStaticAllTabel() | |||
| } | |||
| pageSize := 1000 | |||
| totalPage := int(allCount) / pageSize | |||
| userBusinessAnalysisReturnList := UserBusinessAnalysisAllList{} | |||
| for i := 0; i <= int(totalPage); i++ { | |||
| userBusinessAnalysisAllList := make([]*UserBusinessAnalysisAll, 0) | |||
| if err := statictisSess.Table("user_business_analysis_all").OrderBy("id desc").Limit(pageSize, i*pageSize). | |||
| Find(&userBusinessAnalysisAllList); err != nil { | |||
| return nil, 0 | |||
| } | |||
| log.Info("query " + fmt.Sprint(i+1) + " result size=" + fmt.Sprint(len(userBusinessAnalysisAllList))) | |||
| for _, userRecord := range userBusinessAnalysisAllList { | |||
| userBusinessAnalysisReturnList = append(userBusinessAnalysisReturnList, userRecord) | |||
| } | |||
| } | |||
| sort.Sort(userBusinessAnalysisReturnList) | |||
| log.Info("return size=" + fmt.Sprint(len(userBusinessAnalysisReturnList))) | |||
| return userBusinessAnalysisReturnList, allCount | |||
| } | |||
| func QueryUserStaticDataPage(opts *UserBusinessAnalysisQueryOptions) ([]*UserBusinessAnalysis, int64) { | |||
| log.Info("query startTime =" + fmt.Sprint(opts.StartTime) + " endTime=" + fmt.Sprint(opts.EndTime) + " isAll=" + fmt.Sprint(opts.IsAll)) | |||
| @@ -219,32 +287,43 @@ func QueryUserStaticDataPage(opts *UserBusinessAnalysisQueryOptions) ([]*UserBus | |||
| builder.Lte{"count_date": opts.EndTime}, | |||
| ) | |||
| } | |||
| userBusinessAnalysisList = make([]*UserBusinessAnalysis, 0) | |||
| if err := statictisSess.Table("user_business_analysis").Where(newAndCond).OrderBy("count_date desc"). | |||
| Find(&userBusinessAnalysisList); err != nil { | |||
| allCount, err := statictisSess.Where(newAndCond).Count(new(UserBusinessAnalysis)) | |||
| if err != nil { | |||
| log.Info("query error." + err.Error()) | |||
| return nil, 0 | |||
| } | |||
| } | |||
| log.Info("query result size=" + fmt.Sprint(len(userBusinessAnalysisList))) | |||
| for _, userRecord := range userBusinessAnalysisList { | |||
| if _, ok := resultMap[userRecord.ID]; !ok { | |||
| resultMap[userRecord.ID] = userRecord | |||
| } else { | |||
| resultMap[userRecord.ID].CodeMergeCount += userRecord.CodeMergeCount | |||
| resultMap[userRecord.ID].CommitCount += userRecord.CommitCount | |||
| resultMap[userRecord.ID].IssueCount += userRecord.IssueCount | |||
| resultMap[userRecord.ID].CommentCount += userRecord.CommentCount | |||
| resultMap[userRecord.ID].FocusRepoCount += userRecord.FocusRepoCount | |||
| resultMap[userRecord.ID].StarRepoCount += userRecord.StarRepoCount | |||
| resultMap[userRecord.ID].WatchedCount += userRecord.WatchedCount | |||
| resultMap[userRecord.ID].CommitCodeSize += userRecord.CommitCodeSize | |||
| resultMap[userRecord.ID].CommitDatasetSize += userRecord.CommitDatasetSize | |||
| resultMap[userRecord.ID].CommitModelCount += userRecord.CommitModelCount | |||
| resultMap[userRecord.ID].SolveIssueCount += userRecord.SolveIssueCount | |||
| resultMap[userRecord.ID].EncyclopediasCount += userRecord.EncyclopediasCount | |||
| resultMap[userRecord.ID].CreateRepoCount += userRecord.CreateRepoCount | |||
| resultMap[userRecord.ID].LoginCount += userRecord.LoginCount | |||
| pageSize := 1000 | |||
| totalPage := int(allCount) / pageSize | |||
| for i := 0; i <= int(totalPage); i++ { | |||
| userBusinessAnalysisList = make([]*UserBusinessAnalysis, 0) | |||
| if err := statictisSess.Table("user_business_analysis").Where(newAndCond).OrderBy("count_date desc").Limit(pageSize, i*pageSize). | |||
| Find(&userBusinessAnalysisList); err != nil { | |||
| return nil, 0 | |||
| } | |||
| log.Info("query result size=" + fmt.Sprint(len(userBusinessAnalysisList))) | |||
| for _, userRecord := range userBusinessAnalysisList { | |||
| if _, ok := resultMap[userRecord.ID]; !ok { | |||
| resultMap[userRecord.ID] = userRecord | |||
| } else { | |||
| resultMap[userRecord.ID].CodeMergeCount += userRecord.CodeMergeCount | |||
| resultMap[userRecord.ID].CommitCount += userRecord.CommitCount | |||
| resultMap[userRecord.ID].IssueCount += userRecord.IssueCount | |||
| resultMap[userRecord.ID].CommentCount += userRecord.CommentCount | |||
| resultMap[userRecord.ID].FocusRepoCount += userRecord.FocusRepoCount | |||
| resultMap[userRecord.ID].StarRepoCount += userRecord.StarRepoCount | |||
| resultMap[userRecord.ID].WatchedCount += userRecord.WatchedCount | |||
| resultMap[userRecord.ID].CommitCodeSize += userRecord.CommitCodeSize | |||
| resultMap[userRecord.ID].CommitDatasetSize += userRecord.CommitDatasetSize | |||
| resultMap[userRecord.ID].CommitModelCount += userRecord.CommitModelCount | |||
| resultMap[userRecord.ID].SolveIssueCount += userRecord.SolveIssueCount | |||
| resultMap[userRecord.ID].EncyclopediasCount += userRecord.EncyclopediasCount | |||
| resultMap[userRecord.ID].CreateRepoCount += userRecord.CreateRepoCount | |||
| resultMap[userRecord.ID].LoginCount += userRecord.LoginCount | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -257,6 +336,50 @@ func QueryUserStaticDataPage(opts *UserBusinessAnalysisQueryOptions) ([]*UserBus | |||
| return userBusinessAnalysisReturnList, count | |||
| } | |||
| func RefreshUserStaticAllTabel() { | |||
| statictisSess := xStatistic.NewSession() | |||
| defer statictisSess.Close() | |||
| log.Info("delete all data from table: user_business_analysis_all") | |||
| statictisSess.Exec("delete from user_business_analysis_all") | |||
| currentTimeNow := time.Now() | |||
| pageStartTime := getLastCountDate() | |||
| pageEndTime := time.Date(currentTimeNow.Year(), currentTimeNow.Month(), currentTimeNow.Day(), 23, 59, 59, 0, currentTimeNow.Location()).Unix() | |||
| var cond = builder.NewCond() | |||
| cond = cond.And( | |||
| builder.Gte{"count_date": pageStartTime}, | |||
| ) | |||
| cond = cond.And( | |||
| builder.Lte{"count_date": pageEndTime}, | |||
| ) | |||
| userBusinessAnalysisList := make([]*UserBusinessAnalysis, 0) | |||
| if err := statictisSess.Table("user_business_analysis").Where(cond).OrderBy("id desc"). | |||
| Find(&userBusinessAnalysisList); err != nil { | |||
| return | |||
| } | |||
| log.Info("query all data from table: user_business_analysis,len=" + fmt.Sprint(len(userBusinessAnalysisList))) | |||
| for _, userRecord := range userBusinessAnalysisList { | |||
| log.Info("insert to UserBusinessAnalysisAll table,user id=" + fmt.Sprint(userRecord.ID)) | |||
| allData := getAllData(userRecord.ID, statictisSess) | |||
| allData.ID = userRecord.ID | |||
| allData.CountDate = 0 | |||
| allData.DataDate = userRecord.DataDate | |||
| allData.Email = userRecord.Email | |||
| allData.OpenIIndex = userRecord.OpenIIndex | |||
| allData.GiteaAgeMonth = userRecord.GiteaAgeMonth | |||
| allData.Name = userRecord.Name | |||
| allData.RegistDate = userRecord.RegistDate | |||
| _, err := statictisSess.Insert(&allData) | |||
| if err != nil { | |||
| log.Info("insert all data failed." + err.Error()) | |||
| } | |||
| } | |||
| log.Info("refresh all data finished.") | |||
| } | |||
| func CounDataByDateAndReCount(wikiCountMap map[string]int, startTime time.Time, endTime time.Time, isReCount bool) error { | |||
| log.Info("start to count other user info data") | |||
| @@ -410,10 +533,99 @@ func CounDataByDateAndReCount(wikiCountMap map[string]int, startTime time.Time, | |||
| log.Info("insert daterecord failed." + err.Error()) | |||
| return err | |||
| } | |||
| if isExistUserInAllTable(dateRecord.ID, statictisSess) { | |||
| updateCurrentData(dateRecord.ID, statictisSess, dateRecord) | |||
| } else { | |||
| log.Info("insert to UserBusinessAnalysisAll table,user id=" + fmt.Sprint(dateRecord.ID)) | |||
| allData := getAllData(dateRecord.ID, statictisSess) | |||
| allData.ID = dateRecord.ID | |||
| allData.CountDate = 0 | |||
| allData.DataDate = dateRecord.DataDate | |||
| allData.Email = dateRecord.Email | |||
| allData.OpenIIndex = dateRecord.OpenIIndex | |||
| allData.GiteaAgeMonth = dateRecord.GiteaAgeMonth | |||
| allData.Name = dateRecord.Name | |||
| allData.RegistDate = dateRecord.RegistDate | |||
| _, err = statictisSess.Insert(&allData) | |||
| if err != nil { | |||
| log.Info("insert all data failed." + err.Error()) | |||
| return err | |||
| } | |||
| } | |||
| } | |||
| return nil | |||
| } | |||
| func updateCurrentData(userId int64, statictisSess *xorm.Session, currentData UserBusinessAnalysis) { | |||
| _, err := statictisSess.Update("update user_business_analysis_all set code_merge_count+=" + fmt.Sprint(currentData.CodeMergeCount) + | |||
| ",commit_count+=" + fmt.Sprint(currentData.CommitCount) + | |||
| ",issue_count+=" + fmt.Sprint(currentData.IssueCount) + | |||
| ",comment_count+=" + fmt.Sprint(currentData.CommentCount) + | |||
| ",focus_repo_count+=" + fmt.Sprint(currentData.FocusRepoCount) + | |||
| ",star_repo_count+=" + fmt.Sprint(currentData.StarRepoCount) + | |||
| ",watched_count+=" + fmt.Sprint(currentData.WatchedCount) + | |||
| ",commit_code_size+=" + fmt.Sprint(currentData.CommitCodeSize) + | |||
| ",commit_dataset_size+=" + fmt.Sprint(currentData.CommitDatasetSize) + | |||
| ",commit_model_count+=" + fmt.Sprint(currentData.CommitModelCount) + | |||
| ",solve_issue_count+=" + fmt.Sprint(currentData.SolveIssueCount) + | |||
| ",encyclopedias_count+=" + fmt.Sprint(currentData.EncyclopediasCount) + | |||
| ",create_repo_count+=" + fmt.Sprint(currentData.CreateRepoCount) + | |||
| ",login_count+=" + fmt.Sprint(currentData.LoginCount) + | |||
| " where id=" + fmt.Sprint(userId)) | |||
| if err != nil { | |||
| log.Info("update table failed." + err.Error()) | |||
| } | |||
| } | |||
| func isExistUserInAllTable(userId int64, statictisSess *xorm.Session) bool { | |||
| allCount, err := statictisSess.Where("id=" + fmt.Sprint(userId)).Count(new(UserBusinessAnalysisAll)) | |||
| if err != nil { | |||
| return false | |||
| } | |||
| return allCount > 0 | |||
| } | |||
| func getAllData(userId int64, statictisSess *xorm.Session) UserBusinessAnalysisAll { | |||
| var dateRecord UserBusinessAnalysisAll | |||
| rows, err := statictisSess.Query("select sum(code_merge_count) as code_merge_count,sum(commit_count) as commit_count,sum(issue_count) as issue_count,sum(issue_count) as issue_count,sum(comment_count) as comment_count,sum(focus_repo_count) as focus_repo_count,sum(star_repo_count) as star_repo_count,sum(watched_count) as watched_count,sum(commit_code_size) as commit_code_size,sum(commit_dataset_size) as commit_dataset_size, sum(commit_model_count) as commit_model_count,sum(solve_issue_count) as solve_issue_count,sum(encyclopedias_count) as encyclopedias_count, sum(create_repo_count) as create_repo_count,sum(login_count) as login_count from public.user_business_analysis where id=" + fmt.Sprint(userId) + " group by id") | |||
| if err == nil { | |||
| for i, row := range rows { | |||
| log.Info("query user info, i=" + fmt.Sprint(i) + " code_merge_count=" + string(row["code_merge_count"])) | |||
| dateRecord.CodeMergeCount = getInt(string(row["code_merge_count"])) | |||
| dateRecord.CommitCount = getInt(string(row["commit_count"])) | |||
| dateRecord.IssueCount = getInt(string(row["issue_count"])) | |||
| dateRecord.CommentCount = getInt(string(row["comment_count"])) | |||
| dateRecord.FocusRepoCount = getInt(string(row["focus_repo_count"])) | |||
| dateRecord.StarRepoCount = getInt(string(row["star_repo_count"])) | |||
| dateRecord.WatchedCount = getInt(string(row["watched_count"])) | |||
| dateRecord.CommitCodeSize = getInt(string(row["commit_code_size"])) | |||
| dateRecord.CommitDatasetSize = getInt(string(row["commit_dataset_size"])) | |||
| dateRecord.CommitModelCount = getInt(string(row["commit_model_count"])) | |||
| dateRecord.SolveIssueCount = getInt(string(row["solve_issue_count"])) | |||
| dateRecord.EncyclopediasCount = getInt(string(row["encyclopedias_count"])) | |||
| dateRecord.CreateRepoCount = getInt(string(row["create_repo_count"])) | |||
| dateRecord.LoginCount = getInt(string(row["login_count"])) | |||
| } | |||
| } | |||
| return dateRecord | |||
| } | |||
| func getInt(str string) int { | |||
| re, err := strconv.ParseInt(str, 10, 32) | |||
| if err != nil { | |||
| return 0 | |||
| } | |||
| return int(re) | |||
| } | |||
| func CounDataByDate(wikiCountMap map[string]int, startTime time.Time, endTime time.Time) { | |||
| CounDataByDateAndReCount(wikiCountMap, startTime, endTime, false) | |||
| } | |||
| @@ -4,6 +4,7 @@ import ( | |||
| "bytes" | |||
| "encoding/base64" | |||
| "encoding/json" | |||
| "fmt" | |||
| "io/ioutil" | |||
| "net/http" | |||
| @@ -113,13 +114,23 @@ func GetResultFromElk(resultInfo ResultInfo, jsonStr []byte) (loaded int, totalV | |||
| client := &http.Client{} | |||
| resp, err := client.Do(req) | |||
| if err != nil { | |||
| panic(err) | |||
| // panic(err) | |||
| return 0, 0, err | |||
| } | |||
| defer resp.Body.Close() | |||
| body, _ := ioutil.ReadAll(resp.Body) | |||
| errs := json.Unmarshal([]byte(string(body)), &resultInfo) | |||
| log.Info("Get resultJson failed", errs) | |||
| if resp.StatusCode != 200 { | |||
| log.Error("ConnectToElk failed:%s", resp.Status) | |||
| return 0, 0, fmt.Errorf("ConnectToElk failed:%s", resp.Status) | |||
| } | |||
| body, err := ioutil.ReadAll(resp.Body) | |||
| if err != nil { | |||
| return 0, 0, err | |||
| } | |||
| err = json.Unmarshal([]byte(string(body)), &resultInfo) | |||
| if err != nil { | |||
| log.Error("Get resultJson failed", err) | |||
| return 0, 0, err | |||
| } | |||
| return resultInfo.Result.Loaded, resultInfo.Result.RawResponse.Hits.Total, err | |||
| } | |||
| @@ -138,6 +149,7 @@ func ProjectViewInit(User string, Project string, Gte string, Lte string) (proje | |||
| var timeRange Range | |||
| timeRange.Timestamptest.Gte = Gte | |||
| timeRange.Timestamptest.Lte = Lte | |||
| timeRange.Timestamptest.Format = "strict_date_optional_time" | |||
| inputStruct.Batch[0].Request.Params.Body.Query.BoolIn.Filter[0].Range = &timeRange | |||
| //限定用户 | |||
| var userName FilterMatchPhrase | |||
| @@ -208,9 +220,10 @@ func TagNameInit(MessageInfo string, Tagname string, Gte string, Lte string) (pr | |||
| //向elk发送请求,将获取的结果只保留访问量,输入是初始化后的数据结构,返回访问量 | |||
| func ViewInfo(viewInfo InputInfo) (totalView int, err error) { | |||
| jsons, errs := json.Marshal(viewInfo) | |||
| if errs != nil { | |||
| log.Info("errs:", errs) | |||
| jsons, err := json.Marshal(viewInfo) | |||
| if err != nil { | |||
| log.Error("jsons failed", err) | |||
| return 0, err | |||
| } | |||
| var jsonStr = []byte(jsons) | |||
| var resultInfo ResultInfo | |||
| @@ -221,7 +234,6 @@ func ViewInfo(viewInfo InputInfo) (totalView int, err error) { | |||
| if loaded == 0 { | |||
| loaded_next, totalView, err := GetResultFromElk(resultInfo, jsonStr) | |||
| time++ | |||
| log.Info("time:", time) | |||
| if loaded_next != 0 && time < 100 { | |||
| return totalView, err | |||
| } | |||
| @@ -176,10 +176,10 @@ func ObsModelDownload(JobName string, fileName string) (io.ReadCloser, error) { | |||
| } | |||
| } | |||
| func GetObsListObject(jobName, parentDir string) ([]FileInfo, error) { | |||
| func GetObsListObject(jobName, parentDir string, versionOutputPath string) ([]FileInfo, error) { | |||
| input := &obs.ListObjectsInput{} | |||
| input.Bucket = setting.Bucket | |||
| input.Prefix = strings.TrimPrefix(path.Join(setting.TrainJobModelPath, jobName, setting.OutPutPath, parentDir), "/") | |||
| input.Prefix = strings.TrimPrefix(path.Join(setting.TrainJobModelPath, jobName, setting.OutPutPath, versionOutputPath, parentDir), "/") | |||
| strPrefix := strings.Split(input.Prefix, "/") | |||
| output, err := ObsCli.ListObjects(input) | |||
| fileInfos := make([]FileInfo, 0) | |||
| @@ -303,8 +303,7 @@ func ModelList(ctx *context.APIContext) { | |||
| return | |||
| } | |||
| VersionOutputPath := modelarts.GetVersionOutputPathByTotalVersionCount(task.TotalVersionCount) | |||
| parentDir = VersionOutputPath + "/" + parentDir | |||
| models, err := storage.GetObsListObject(task.JobName, parentDir) | |||
| models, err := storage.GetObsListObject(task.JobName, parentDir, VersionOutputPath) | |||
| if err != nil { | |||
| log.Info("get TrainJobListModel failed:", err) | |||
| ctx.ServerError("GetObsListObject:", err) | |||
| @@ -43,7 +43,8 @@ func RegisterRoutes(m *macaron.Macaron) { | |||
| m.Post("/manager/restart", Restart) | |||
| m.Post("/manager/flush-queues", bind(private.FlushOptions{}), FlushQueues) | |||
| m.Post("/tool/update_all_repo_commit_cnt", UpdateAllRepoCommitCnt) | |||
| m.Post("/tool/repo_stat", RepoStatisticManually) | |||
| m.Post("/tool/repo_stat/:date", RepoStatisticManually) | |||
| m.Post("/tool/update_repo_visit/:date", UpdateRepoVisit) | |||
| }, CheckInternalToken) | |||
| } | |||
| @@ -39,8 +39,35 @@ func UpdateAllRepoCommitCnt(ctx *macaron.Context) { | |||
| } | |||
| func RepoStatisticManually(ctx *macaron.Context) { | |||
| date := ctx.Query("date") | |||
| date := ctx.Params("date") | |||
| repo.RepoStatisticDaily(date) | |||
| repo.SummaryStatisticDaily(date) | |||
| repo.TimingCountDataByDate(date) | |||
| } | |||
| func UpdateRepoVisit(ctx *macaron.Context) { | |||
| date := ctx.Params("date") | |||
| log.Info("date(%s)", date) | |||
| repos, err := models.GetAllRepositories() | |||
| if err != nil { | |||
| log.Error("GetAllRepositories failed:%v", err.Error(), ctx.Data["MsgID"]) | |||
| ctx.JSON(http.StatusInternalServerError, map[string]string{ | |||
| "error_msg": "GetAllRepositories failed", | |||
| }) | |||
| return | |||
| } | |||
| for i, repoStat := range repos { | |||
| log.Info("%d:begin UpdateRepoVisits(id = %d, name = %s)", i, repoStat.ID, repoStat.Name) | |||
| if err = repo.UpdateRepoVisits(ctx, repoStat, date); err != nil { | |||
| log.Error("UpdateRepoVisits(id = %d, name = %s) failed:%v", repoStat.ID, repoStat.Name, err.Error()) | |||
| continue | |||
| } | |||
| log.Info("%d:finish UpdateRepoVisits(id = %d, name = %s)", i, repoStat.ID, repoStat.Name) | |||
| } | |||
| ctx.JSON(http.StatusOK, map[string]string{ | |||
| "error_msg": "", | |||
| }) | |||
| } | |||
| @@ -477,6 +477,94 @@ func trainJobNewVersionDataPrepare(ctx *context.Context) error { | |||
| return nil | |||
| } | |||
| func ErrorDataPrepare(ctx *context.Context, form auth.CreateModelArtsTrainJobForm) error { | |||
| ctx.Data["PageIsCloudBrain"] = true | |||
| var jobID = ctx.Params(":jobid") | |||
| // var versionName = ctx.Params(":version-name") | |||
| var versionName = ctx.Query("version_name") | |||
| task, err := models.GetCloudbrainByJobIDAndVersionName(jobID, versionName) | |||
| if err != nil { | |||
| log.Error("GetCloudbrainByJobIDAndVersionName(%s) failed:%v", jobID, err.Error()) | |||
| return err | |||
| } | |||
| t := time.Now() | |||
| var jobName = cutString(ctx.User.Name, 5) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:] | |||
| ctx.Data["job_name"] = task.JobName | |||
| attachs, err := models.GetModelArtsUserAttachments(ctx.User.ID) | |||
| if err != nil { | |||
| ctx.ServerError("GetAllUserAttachments failed:", err) | |||
| return err | |||
| } | |||
| ctx.Data["attachments"] = attachs | |||
| var resourcePools modelarts.ResourcePool | |||
| if err = json.Unmarshal([]byte(setting.ResourcePools), &resourcePools); err != nil { | |||
| ctx.ServerError("json.Unmarshal failed:", err) | |||
| return err | |||
| } | |||
| ctx.Data["resource_pools"] = resourcePools.Info | |||
| var engines modelarts.Engine | |||
| if err = json.Unmarshal([]byte(setting.Engines), &engines); err != nil { | |||
| ctx.ServerError("json.Unmarshal failed:", err) | |||
| return err | |||
| } | |||
| ctx.Data["engines"] = engines.Info | |||
| var versionInfos modelarts.VersionInfo | |||
| if err = json.Unmarshal([]byte(setting.EngineVersions), &versionInfos); err != nil { | |||
| ctx.ServerError("json.Unmarshal failed:", err) | |||
| return err | |||
| } | |||
| ctx.Data["engine_versions"] = versionInfos.Version | |||
| var flavorInfos modelarts.Flavor | |||
| if err = json.Unmarshal([]byte(setting.TrainJobFLAVORINFOS), &flavorInfos); err != nil { | |||
| ctx.ServerError("json.Unmarshal failed:", err) | |||
| return err | |||
| } | |||
| ctx.Data["flavor_infos"] = flavorInfos.Info | |||
| var Parameters modelarts.Parameters | |||
| if err = json.Unmarshal([]byte(form.Params), &Parameters); err != nil { | |||
| ctx.ServerError("json.Unmarshal failed:", err) | |||
| return err | |||
| } | |||
| ctx.Data["params"] = Parameters.Parameter | |||
| outputObsPath := "/" + setting.Bucket + modelarts.JobPath + jobName + modelarts.OutputPath | |||
| ctx.Data["train_url"] = outputObsPath | |||
| Branches, err := ctx.Repo.GitRepo.GetBranches() | |||
| if err != nil { | |||
| ctx.ServerError("GetBranches error:", err) | |||
| return err | |||
| } | |||
| ctx.Data["branches"] = Branches | |||
| ctx.Data["description"] = form.Description | |||
| ctx.Data["dataset_name"] = task.DatasetName | |||
| ctx.Data["work_server_number"] = form.WorkServerNumber | |||
| ctx.Data["flavor_name"] = form.FlavorName | |||
| ctx.Data["engine_name"] = form.EngineName | |||
| ctx.Data["flavor_code"] = task.FlavorCode | |||
| ctx.Data["engine_id"] = task.EngineID | |||
| ctx.Data["bootFile"] = form.BootFile | |||
| ctx.Data["uuid"] = form.Attachment | |||
| ctx.Data["branch_name"] = form.BranchName | |||
| configList, err := getConfigList(modelarts.PerPage, 1, modelarts.SortByCreateTime, "desc", "", modelarts.ConfigTypeCustom) | |||
| if err != nil { | |||
| ctx.ServerError("getConfigList failed:", err) | |||
| return err | |||
| } | |||
| ctx.Data["config_list"] = configList.ParaConfigs | |||
| return nil | |||
| } | |||
| func TrainJobCreate(ctx *context.Context, form auth.CreateModelArtsTrainJobForm) { | |||
| ctx.Data["PageIsTrainJob"] = true | |||
| VersionOutputPath := modelarts.GetVersionOutputPathByTotalVersionCount(modelarts.TotalVersionCount) | |||
| @@ -492,6 +580,7 @@ func TrainJobCreate(ctx *context.Context, form auth.CreateModelArtsTrainJobForm) | |||
| isSaveParam := form.IsSaveParam | |||
| repo := ctx.Repo.Repository | |||
| codeLocalPath := setting.JobPath + jobName + modelarts.CodePath | |||
| // codeObsPath := "/" + setting.Bucket + modelarts.JobPath + jobName + modelarts.CodePath + VersionOutputPath + "/" | |||
| codeObsPath := "/" + setting.Bucket + modelarts.JobPath + jobName + modelarts.CodePath | |||
| outputObsPath := "/" + setting.Bucket + modelarts.JobPath + jobName + modelarts.OutputPath + VersionOutputPath + "/" | |||
| logObsPath := "/" + setting.Bucket + modelarts.JobPath + jobName + modelarts.LogPath + VersionOutputPath + "/" | |||
| @@ -529,13 +618,6 @@ func TrainJobCreate(ctx *context.Context, form auth.CreateModelArtsTrainJobForm) | |||
| }); err != nil { | |||
| log.Error("创建任务失败,服务器超时!: %s (%v)", repo.FullName(), err) | |||
| trainJobNewDataPrepare(ctx) | |||
| ctx.Data["bootFile"] = form.BootFile | |||
| ctx.Data["uuid"] = form.Attachment | |||
| ctx.Data["datasetName"] = attach.Name | |||
| ctx.Data["params"] = form.Params | |||
| ctx.Data["branch_name"] = branch_name | |||
| trainJobNewDataPrepare(ctx) | |||
| ctx.RenderWithErr("创建任务失败,服务器超时!", tplModelArtsTrainJobNew, &form) | |||
| return | |||
| } | |||
| @@ -555,7 +637,9 @@ func TrainJobCreate(ctx *context.Context, form auth.CreateModelArtsTrainJobForm) | |||
| return | |||
| } | |||
| // parentDir := VersionOutputPath + "/" | |||
| if err := uploadCodeToObs(codeLocalPath, jobName, ""); err != nil { | |||
| // if err := uploadCodeToObs(codeLocalPath, jobName, parentDir); err != nil { | |||
| log.Error("Failed to uploadCodeToObs: %s (%v)", repo.FullName(), err) | |||
| trainJobNewDataPrepare(ctx) | |||
| ctx.RenderWithErr("Failed to uploadCodeToObs", tplModelArtsTrainJobNew, &form) | |||
| @@ -651,6 +735,13 @@ func TrainJobCreate(ctx *context.Context, form auth.CreateModelArtsTrainJobForm) | |||
| TotalVersionCount: modelarts.TotalVersionCount, | |||
| } | |||
| //将params转换Parameters.Parameter,出错时返回给前端 | |||
| var Parameters modelarts.Parameters | |||
| if err := json.Unmarshal([]byte(params), &Parameters); err != nil { | |||
| ctx.ServerError("json.Unmarshal failed:", err) | |||
| return | |||
| } | |||
| err = modelarts.GenerateTrainJob(ctx, req) | |||
| if err != nil { | |||
| log.Error("GenerateTrainJob failed:%v", err.Error()) | |||
| @@ -658,7 +749,7 @@ func TrainJobCreate(ctx *context.Context, form auth.CreateModelArtsTrainJobForm) | |||
| ctx.Data["bootFile"] = form.BootFile | |||
| ctx.Data["uuid"] = form.Attachment | |||
| ctx.Data["datasetName"] = attach.Name | |||
| ctx.Data["params"] = form.Params | |||
| ctx.Data["params"] = Parameters.Parameter | |||
| ctx.Data["branch_name"] = branch_name | |||
| ctx.RenderWithErr(err.Error(), tplModelArtsTrainJobNew, &form) | |||
| return | |||
| @@ -689,7 +780,7 @@ func TrainJobCreateVersion(ctx *context.Context, form auth.CreateModelArtsTrainJ | |||
| isSaveParam := form.IsSaveParam | |||
| repo := ctx.Repo.Repository | |||
| codeLocalPath := setting.JobPath + jobName + modelarts.CodePath | |||
| codeObsPath := "/" + setting.Bucket + modelarts.JobPath + jobName + modelarts.CodePath | |||
| codeObsPath := "/" + setting.Bucket + modelarts.JobPath + jobName + modelarts.CodePath + VersionOutputPath + "/" | |||
| outputObsPath := "/" + setting.Bucket + modelarts.JobPath + jobName + modelarts.OutputPath + VersionOutputPath + "/" | |||
| logObsPath := "/" + setting.Bucket + modelarts.JobPath + jobName + modelarts.LogPath + VersionOutputPath + "/" | |||
| dataPath := "/" + setting.Bucket + "/" + setting.BasePath + path.Join(uuid[0:1], uuid[1:2]) + "/" + uuid + uuid + "/" | |||
| @@ -701,16 +792,16 @@ func TrainJobCreateVersion(ctx *context.Context, form auth.CreateModelArtsTrainJ | |||
| if err := paramCheckCreateTrainJob(form); err != nil { | |||
| log.Error("paramCheckCreateTrainJob failed:(%v)", err) | |||
| trainJobNewVersionDataPrepare(ctx) | |||
| ErrorDataPrepare(ctx, form) | |||
| ctx.RenderWithErr(err.Error(), tplModelArtsTrainJobVersionNew, &form) | |||
| return | |||
| } | |||
| attach, err := models.GetAttachmentByUUID(uuid) | |||
| if err != nil { | |||
| log.Error("GetAttachmentByUUID(%s) failed:%v", uuid, err.Error()) | |||
| return | |||
| } | |||
| // attach, err := models.GetAttachmentByUUID(uuid) | |||
| // if err != nil { | |||
| // log.Error("GetAttachmentByUUID(%s) failed:%v", uuid, err.Error()) | |||
| // return | |||
| // } | |||
| //todo: del the codeLocalPath | |||
| _, err = ioutil.ReadDir(codeLocalPath) | |||
| @@ -724,13 +815,7 @@ func TrainJobCreateVersion(ctx *context.Context, form auth.CreateModelArtsTrainJ | |||
| Branch: branch_name, | |||
| }); err != nil { | |||
| log.Error("创建任务失败,任务名称已存在!: %s (%v)", repo.FullName(), err) | |||
| trainJobNewVersionDataPrepare(ctx) | |||
| ctx.Data["bootFile"] = form.BootFile | |||
| ctx.Data["uuid"] = form.Attachment | |||
| ctx.Data["datasetName"] = attach.Name | |||
| ctx.Data["params"] = form.Params | |||
| ctx.Data["branch_name"] = branch_name | |||
| ErrorDataPrepare(ctx, form) | |||
| ctx.RenderWithErr("创建任务失败,任务名称已存在!", tplModelArtsTrainJobVersionNew, &form) | |||
| return | |||
| } | |||
| @@ -738,21 +823,23 @@ func TrainJobCreateVersion(ctx *context.Context, form auth.CreateModelArtsTrainJ | |||
| //todo: upload code (send to file_server todo this work?) | |||
| if err := obsMkdir(setting.CodePathPrefix + jobName + modelarts.OutputPath + VersionOutputPath + "/"); err != nil { | |||
| log.Error("Failed to obsMkdir_output: %s (%v)", repo.FullName(), err) | |||
| trainJobNewVersionDataPrepare(ctx) | |||
| ErrorDataPrepare(ctx, form) | |||
| ctx.RenderWithErr("Failed to obsMkdir_output", tplModelArtsTrainJobVersionNew, &form) | |||
| return | |||
| } | |||
| if err := obsMkdir(setting.CodePathPrefix + jobName + modelarts.LogPath + VersionOutputPath + "/"); err != nil { | |||
| log.Error("Failed to obsMkdir_log: %s (%v)", repo.FullName(), err) | |||
| trainJobNewVersionDataPrepare(ctx) | |||
| ErrorDataPrepare(ctx, form) | |||
| ctx.RenderWithErr("Failed to obsMkdir_log", tplModelArtsTrainJobVersionNew, &form) | |||
| return | |||
| } | |||
| if err := uploadCodeToObs(codeLocalPath, jobName, ""); err != nil { | |||
| parentDir := VersionOutputPath + "/" | |||
| // if err := uploadCodeToObs(codeLocalPath, jobName, ""); err != nil { | |||
| if err := uploadCodeToObs(codeLocalPath, jobName, parentDir); err != nil { | |||
| log.Error("Failed to uploadCodeToObs: %s (%v)", repo.FullName(), err) | |||
| trainJobNewVersionDataPrepare(ctx) | |||
| ErrorDataPrepare(ctx, form) | |||
| ctx.RenderWithErr("Failed to uploadCodeToObs", tplModelArtsTrainJobVersionNew, &form) | |||
| return | |||
| } | |||
| @@ -772,7 +859,7 @@ func TrainJobCreateVersion(ctx *context.Context, form auth.CreateModelArtsTrainJ | |||
| err := json.Unmarshal([]byte(params), ¶meters) | |||
| if err != nil { | |||
| log.Error("Failed to Unmarshal params: %s (%v)", params, err) | |||
| trainJobNewVersionDataPrepare(ctx) | |||
| ErrorDataPrepare(ctx, form) | |||
| ctx.RenderWithErr("运行参数错误", tplModelArtsTrainJobVersionNew, &form) | |||
| return | |||
| } | |||
| @@ -791,7 +878,7 @@ func TrainJobCreateVersion(ctx *context.Context, form auth.CreateModelArtsTrainJ | |||
| if isSaveParam == "on" { | |||
| if form.ParameterTemplateName == "" { | |||
| log.Error("ParameterTemplateName is empty") | |||
| trainJobNewVersionDataPrepare(ctx) | |||
| ErrorDataPrepare(ctx, form) | |||
| ctx.RenderWithErr("保存作业参数时,作业参数名称不能为空", tplModelArtsTrainJobVersionNew, &form) | |||
| return | |||
| } | |||
| @@ -815,7 +902,7 @@ func TrainJobCreateVersion(ctx *context.Context, form auth.CreateModelArtsTrainJ | |||
| if err != nil { | |||
| log.Error("Failed to CreateTrainJobConfig: %v", err) | |||
| trainJobNewVersionDataPrepare(ctx) | |||
| ErrorDataPrepare(ctx, form) | |||
| ctx.RenderWithErr("保存作业参数失败:"+err.Error(), tplModelArtsTrainJobVersionNew, &form) | |||
| return | |||
| } | |||
| @@ -862,15 +949,11 @@ func TrainJobCreateVersion(ctx *context.Context, form auth.CreateModelArtsTrainJ | |||
| err = modelarts.GenerateTrainJobVersion(ctx, req, jobID) | |||
| if err != nil { | |||
| log.Error("GenerateTrainJob failed:%v", err.Error()) | |||
| trainJobNewVersionDataPrepare(ctx) | |||
| ctx.Data["bootFile"] = form.BootFile | |||
| ctx.Data["uuid"] = form.Attachment | |||
| ctx.Data["datasetName"] = attach.Name | |||
| ctx.Data["params"] = form.Params | |||
| ErrorDataPrepare(ctx, form) | |||
| ctx.RenderWithErr(err.Error(), tplModelArtsTrainJobVersionNew, &form) | |||
| return | |||
| } | |||
| ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/modelarts/train-job") | |||
| ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/modelarts/train-job/" + jobID) | |||
| // ctx.HTML(http.StatusOK, tplModelArtsTrainJobShow) | |||
| } | |||
| @@ -963,7 +1046,6 @@ func paramCheckCreateTrainJob(form auth.CreateModelArtsTrainJobForm) error { | |||
| func TrainJobShow(ctx *context.Context) { | |||
| ctx.Data["PageIsCloudBrain"] = true | |||
| var jobID = ctx.Params(":jobid") | |||
| repo := ctx.Repo.Repository | |||
| @@ -1011,6 +1093,9 @@ func TrainJobShow(ctx *context.Context) { | |||
| } | |||
| } | |||
| pager := context.NewPagination(VersionListCount, setting.UI.IssuePagingNum, page, 5) | |||
| pager.SetDefaultParams(ctx) | |||
| ctx.Data["Page"] = pager | |||
| ctx.Data["jobID"] = jobID | |||
| ctx.Data["jobName"] = VersionListTasks[0].JobName | |||
| ctx.Data["version_list_task"] = VersionListTasks | |||
| @@ -1,15 +1,17 @@ | |||
| package repo | |||
| import ( | |||
| "errors" | |||
| "time" | |||
| "code.gitea.io/gitea/services/mailer" | |||
| "code.gitea.io/gitea/models" | |||
| "code.gitea.io/gitea/modules/log" | |||
| "code.gitea.io/gitea/modules/normalization" | |||
| "code.gitea.io/gitea/modules/repository" | |||
| "code.gitea.io/gitea/modules/setting" | |||
| "code.gitea.io/gitea/services/mailer" | |||
| "gitea.com/macaron/macaron" | |||
| ) | |||
| func StatisticAuto() { | |||
| @@ -48,7 +50,7 @@ func RepoStatisticDaily(date string) { | |||
| var maxRepoRadar models.RepoStatistic | |||
| for i, repo := range repos { | |||
| log.Info("start statistic: %s", repo.Name) | |||
| log.Info("start statistic: %s", getDistinctProjectName(repo)) | |||
| var numDevMonths, numWikiViews, numContributor, numKeyContributor, numCommitsGrowth, numCommitLinesGrowth, numContributorsGrowth int64 | |||
| repoGitStat, err := models.GetRepoKPIStats(repo) | |||
| if err != nil { | |||
| @@ -230,7 +232,7 @@ func RepoStatisticDaily(date string) { | |||
| } | |||
| log.Info("finish statistic: %s", repo.Name) | |||
| log.Info("finish statistic: %s", getDistinctProjectName(repo)) | |||
| } | |||
| //radar map | |||
| @@ -274,3 +276,29 @@ func getStatTime(timeStr string) (string, string) { | |||
| return beginTime, endTime | |||
| } | |||
| func UpdateRepoVisits(ctx *macaron.Context, repo *models.Repository, date string) error { | |||
| beginTime, endTime := getStatTime(date) | |||
| var numVisits int | |||
| numVisits, err := repository.AppointProjectView(repo.OwnerName, repo.Name, beginTime, endTime) | |||
| if err != nil { | |||
| log.Error("AppointProjectView failed(%s): %v", getDistinctProjectName(repo), err) | |||
| return err | |||
| } | |||
| repoStat, err := models.GetRepoStatisticByDate(date, repo.ID) | |||
| if err != nil { | |||
| log.Error("GetRepoStatisticByDate failed(%s): %v", getDistinctProjectName(repo), err) | |||
| return err | |||
| } else if len(repoStat) != 1 { | |||
| log.Error("GetRepoStatisticByDate failed(%s): %v", getDistinctProjectName(repo), err) | |||
| return errors.New("not find repo") | |||
| } | |||
| repoStat[0].NumVisits = int64(numVisits) | |||
| if err = models.UpdateRepoStatVisits(repoStat[0]); err != nil { | |||
| log.Error("UpdateRepoStatVisits failed(%s): %v", getDistinctProjectName(repo), err) | |||
| return err | |||
| } | |||
| return nil | |||
| } | |||
| @@ -16,17 +16,6 @@ import ( | |||
| "github.com/360EntSecGroup-Skylar/excelize/v2" | |||
| ) | |||
| func QueryUserStaticData(ctx *context.Context) { | |||
| startDate := ctx.Query("startDate") | |||
| endDate := ctx.Query("endDate") | |||
| log.Info("startDate=" + startDate + " endDate=" + endDate) | |||
| startTime, _ := time.Parse("2006-01-02", startDate) | |||
| endTime, _ := time.Parse("2006-01-02", endDate) | |||
| endTime = endTime.AddDate(0, 0, 1) | |||
| log.Info("startTime=" + fmt.Sprint(startTime.Unix()) + " endDate=" + fmt.Sprint(endTime.Unix())) | |||
| ctx.JSON(http.StatusOK, models.QueryUserStaticData(startTime.Unix(), endTime.Unix())) | |||
| } | |||
| func QueryUserStaticDataPage(ctx *context.Context) { | |||
| startDate := ctx.Query("startDate") | |||
| endDate := ctx.Query("endDate") | |||
| @@ -76,11 +65,10 @@ func QueryUserStaticDataPage(ctx *context.Context) { | |||
| EndTime: endTime.Unix(), | |||
| IsAll: isAll, | |||
| } | |||
| mapInterface := make(map[string]interface{}) | |||
| re, count := models.QueryUserStaticDataPage(pageOpts) | |||
| mapInterface["data"] = re | |||
| mapInterface["count"] = count | |||
| if IsReturnFile { | |||
| re, count := models.QueryUserStaticDataAll(pageOpts) | |||
| log.Info("return count=" + fmt.Sprint(count)) | |||
| //writer exec file. | |||
| xlsx := excelize.NewFile() | |||
| sheetName := ctx.Tr("user.static.sheetname") | |||
| @@ -132,8 +120,8 @@ func QueryUserStaticDataPage(ctx *context.Context) { | |||
| formatTime := userRecord.RegistDate.Format("2006-01-02 15:04:05") | |||
| xlsx.SetCellValue(sheetName, "P"+rows, formatTime[0:len(formatTime)-3]) | |||
| formatTime = time.Unix(userRecord.CountDate, 0).Format("2006-01-02 15:04:05") | |||
| xlsx.SetCellValue(sheetName, "Q"+rows, formatTime[0:len(formatTime)-3]) | |||
| formatTime = userRecord.DataDate | |||
| xlsx.SetCellValue(sheetName, "Q"+rows, formatTime+" 00:01") | |||
| } | |||
| //设置默认打开的表单 | |||
| @@ -163,11 +151,21 @@ func QueryUserStaticDataPage(ctx *context.Context) { | |||
| } | |||
| } else { | |||
| mapInterface := make(map[string]interface{}) | |||
| re, count := models.QueryUserStaticDataPage(pageOpts) | |||
| mapInterface["data"] = re | |||
| mapInterface["count"] = count | |||
| ctx.JSON(http.StatusOK, mapInterface) | |||
| } | |||
| } | |||
| func TimingCountDataByDateAndReCount(date string, isReCount bool) { | |||
| if date == "refreshAll" { | |||
| models.RefreshUserStaticAllTabel() | |||
| return | |||
| } | |||
| t, _ := time.Parse("2006-01-02", date) | |||
| startTime := time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, t.Location()) | |||
| @@ -220,6 +218,10 @@ func TimingCountDataByDateAndReCount(date string, isReCount bool) { | |||
| log.Error("count user info error." + err.Error()) | |||
| mailer.SendWarnNotifyMail(setting.Warn_Notify_Mails, warnEmailMessage) | |||
| } | |||
| if isReCount { | |||
| models.RefreshUserStaticAllTabel() | |||
| } | |||
| } | |||
| func TimingCountDataByDate(date string) { | |||
| @@ -792,7 +792,6 @@ func RegisterRoutes(m *macaron.Macaron) { | |||
| }, reqSignIn, context.RepoAssignment(), context.UnitTypes(), reqRepoAdmin, context.RepoRef()) | |||
| m.Post("/:username/:reponame/action/:action", reqSignIn, context.RepoAssignment(), context.UnitTypes(), repo.Action) | |||
| m.Get("/tool/query_user_static", adminReq, repo.QueryUserStaticData) | |||
| m.Get("/tool/query_user_static_page", adminReq, repo.QueryUserStaticDataPage) | |||
| // Grouping for those endpoints not requiring authentication | |||
| m.Group("/:username/:reponame", func() { | |||
| @@ -0,0 +1,42 @@ | |||
| <footer> | |||
| <div class="ui fluid container" style="padding: 0px 10px;"> | |||
| <div class="ui grid"> | |||
| <div class="sixteen wide mobile eight wide tablet eight wide computer column"> | |||
| <div class="ui three column grid"> | |||
| <div class="column ui vertical text menu"> | |||
| <div class="header item">{{.i18n.Tr "custom.head.community"}}</div> | |||
| <a href="https://openi.org.cn/html/Club/2019/0227/14.html" class="item">{{.i18n.Tr "custom.foot.council"}}</a> | |||
| <a href="https://openi.org.cn/html/Club/2019/0227/14.html" class="item">{{.i18n.Tr "custom.foot.technical_committee"}}</a> | |||
| <a href="https://openi.org.cn/html/Club/2019/0228/17.html" class="item">{{.i18n.Tr "custom.foot.join"}}</a> | |||
| </div> | |||
| <div class="column ui vertical text menu"> | |||
| <div class="header item">{{.i18n.Tr "custom.foot.news"}}</div> | |||
| <a href="https://openi.org.cn/html/news/dongtai/" class="item">{{.i18n.Tr "custom.foot.community_news"}}</a> | |||
| <a href="https://openi.org.cn/html/news/huodong/" class="item">{{.i18n.Tr "custom.foot.member_news"}}</a> | |||
| <a href="https://openi.org.cn/html/news/zixun/" class="item">{{.i18n.Tr "custom.foot.industry_advisory"}}</a> | |||
| </div> | |||
| <div class="column ui vertical text menu"> | |||
| <div class="header item">{{.i18n.Tr "custom.foot.help"}}</div> | |||
| <div class="ui language bottom floating slide up dropdown link item"> | |||
| <i class="world icon"></i> | |||
| <div class="text">{{.LangName}}</div> | |||
| <div class="menu"> | |||
| {{range .AllLangs}} | |||
| <a lang="{{.Lang}}" class="item {{if eq $.Lang .Lang}}active selected{{end}}" href="{{if eq $.Lang .Lang}}#{{else}}{{$.Link}}?lang={{.Lang}}{{end}}">{{.Name}}</a> | |||
| {{end}} | |||
| </div> | |||
| </div> | |||
| {{if .EnableSwagger}}<a href="/api/swagger" class="ui item">API</a>{{end}} | |||
| {{template "custom/extra_links_footer" .}} | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <div class="sixteen wide mobile eight wide tablet eight wide computer column" style=" margin:2.0rem 0"> | |||
| {{.i18n.Tr "custom.foot.copyright"}} <a href="http://beian.miit.gov.cn/" target="_blank">京ICP备18004880号</a> | |||
| <br> | |||
| {{.i18n.Tr "Powered_by 鹏城实验室云脑、"}}<a href="https://www.trustie.net/" target="_blank">Trustie确实</a>{{.i18n.Tr "、gitea"}} | |||
| <br> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </footer> | |||
| @@ -0,0 +1,48 @@ | |||
| {{/* | |||
| <html> | |||
| <body> | |||
| <div> | |||
| */}} | |||
| {{template "custom/body_inner_post" .}} | |||
| </div> | |||
| {{template "custom/body_outer_post" .}} | |||
| {{template "base/footer_content_fluid" .}} | |||
| <script src="{{StaticUrlPrefix}}/js/jquery.js?v={{MD5 AppVer}}"></script> | |||
| {{if .RequireSimpleMDE}} | |||
| <script src="{{StaticUrlPrefix}}/vendor/plugins/simplemde/simplemde.min.js"></script> | |||
| <script src="{{StaticUrlPrefix}}/vendor/plugins/codemirror/addon/mode/loadmode.js"></script> | |||
| <script src="{{StaticUrlPrefix}}/vendor/plugins/codemirror/mode/meta.js"></script> | |||
| <script> | |||
| CodeMirror.modeURL = "{{StaticUrlPrefix}}/vendor/plugins/codemirror/mode/%N/%N.js"; | |||
| </script> | |||
| {{end}} | |||
| <!-- Third-party libraries --> | |||
| {{if .RequireMinicolors}} | |||
| <script src="{{StaticUrlPrefix}}/vendor/plugins/jquery.minicolors/jquery.minicolors.min.js"></script> | |||
| {{end}} | |||
| {{if .RequireU2F}} | |||
| <script src="{{StaticUrlPrefix}}/vendor/plugins/u2f/index.js"></script> | |||
| {{end}} | |||
| {{if .EnableCaptcha}} | |||
| {{if eq .CaptchaType "recaptcha"}} | |||
| <script src='{{ URLJoin .RecaptchaURL "api.js"}}' async></script> | |||
| {{end}} | |||
| {{end}} | |||
| {{if .RequireTribute}} | |||
| <script src="{{StaticUrlPrefix}}/vendor/plugins/tribute/tribute.min.js"></script> | |||
| {{end}} | |||
| {{if .PageIsHome}} | |||
| <script rel="stylesheet" src="{{StaticUrlPrefix}}/vendor/plugins/jquery.particleground/jquery.particleground.min.js"></script> | |||
| {{end}} | |||
| <script src="{{StaticUrlPrefix}}/fomantic/semantic.min.js?v={{MD5 AppVer}}"></script> | |||
| <script src="{{StaticUrlPrefix}}/js/index.js?v={{MD5 AppVer}}"></script> | |||
| {{template "custom/footer" .}} | |||
| </body> | |||
| </html> | |||
| @@ -0,0 +1,208 @@ | |||
| <!DOCTYPE html> | |||
| <html lang="{{.Language}}"> | |||
| <head data-suburl="{{AppSubUrl}}"> | |||
| <meta charset="utf-8"> | |||
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |||
| <meta http-equiv="x-ua-compatible" content="ie=edge"> | |||
| <title>{{if .Title}}{{.Title}} - {{end}} {{if .Repository.Name}}{{.Repository.Name}} - {{end}}{{AppName}}</title> | |||
| <link rel="manifest" href="{{AppSubUrl}}/manifest.json" crossorigin="use-credentials"> | |||
| {{if UseServiceWorker}} | |||
| <script> | |||
| if ('serviceWorker' in navigator) { | |||
| navigator.serviceWorker.register('{{AppSubUrl}}/serviceworker.js').then(function(registration) { | |||
| // Registration was successful | |||
| console.info('ServiceWorker registration successful with scope: ', registration.scope); | |||
| }, function(err) { | |||
| // registration failed :( | |||
| console.info('ServiceWorker registration failed: ', err); | |||
| }); | |||
| } | |||
| </script> | |||
| {{else}} | |||
| <script> | |||
| if ('serviceWorker' in navigator) { | |||
| navigator.serviceWorker.getRegistrations().then(function(registrations) { | |||
| registrations.forEach(function(registration) { | |||
| registration.unregister(); | |||
| console.info('ServiceWorker unregistered'); | |||
| }); | |||
| }); | |||
| } | |||
| </script> | |||
| {{end}} | |||
| <meta name="theme-color" content="{{ThemeColorMetaTag}}"> | |||
| <meta name="author" content="{{if .Repository}}{{.Owner.Name}}{{else}}{{MetaAuthor}}{{end}}" /> | |||
| <meta name="description" content="{{if .Repository}}{{.Repository.Name}}{{if .Repository.Description}} - {{.Repository.Description}}{{end}}{{else}}{{MetaDescription}}{{end}}" /> | |||
| <meta name="keywords" content="{{MetaKeywords}}"> | |||
| <meta name="referrer" content="no-referrer" /> | |||
| <meta name="_csrf" content="{{.CsrfToken}}" /> | |||
| {{if .IsSigned}} | |||
| <meta name="_uid" content="{{.SignedUser.ID}}" /> | |||
| {{end}} | |||
| {{if .ContextUser}} | |||
| <meta name="_context_uid" content="{{.ContextUser.ID}}" /> | |||
| {{end}} | |||
| {{if .SearchLimit}} | |||
| <meta name="_search_limit" content="{{.SearchLimit}}" /> | |||
| {{end}} | |||
| {{if .GoGetImport}} | |||
| <meta name="go-import" content="{{.GoGetImport}} git {{.CloneLink.HTTPS}}"> | |||
| <meta name="go-source" content="{{.GoGetImport}} _ {{.GoDocDirectory}} {{.GoDocFile}}"> | |||
| {{end}} | |||
| <script> | |||
| {{SafeJS `/* | |||
| @licstart The following is the entire license notice for the | |||
| JavaScript code in this page. | |||
| Copyright (c) 2016 The Gitea Authors | |||
| Copyright (c) 2015 The Gogs Authors | |||
| Permission is hereby granted, free of charge, to any person obtaining a copy | |||
| of this software and associated documentation files (the "Software"), to deal | |||
| in the Software without restriction, including without limitation the rights | |||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |||
| copies of the Software, and to permit persons to whom the Software is | |||
| furnished to do so, subject to the following conditions: | |||
| The above copyright notice and this permission notice shall be included in | |||
| all copies or substantial portions of the Software. | |||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |||
| THE SOFTWARE. | |||
| --- | |||
| Licensing information for additional javascript libraries can be found at: | |||
| {{StaticUrlPrefix}}/vendor/librejs.html | |||
| @licend The above is the entire license notice | |||
| for the JavaScript code in this page. | |||
| */`}} | |||
| </script> | |||
| <script> | |||
| window.config = { | |||
| AppSubUrl: '{{AppSubUrl}}', | |||
| StaticUrlPrefix: '{{StaticUrlPrefix}}', | |||
| csrf: '{{.CsrfToken}}', | |||
| HighlightJS: {{if .RequireHighlightJS}}true{{else}}false{{end}}, | |||
| Minicolors: {{if .RequireMinicolors}}true{{else}}false{{end}}, | |||
| SimpleMDE: {{if .RequireSimpleMDE}}true{{else}}false{{end}}, | |||
| Tribute: {{if .RequireTribute}}true{{else}}false{{end}}, | |||
| U2F: {{if .RequireU2F}}true{{else}}false{{end}}, | |||
| Heatmap: {{if .EnableHeatmap}}true{{else}}false{{end}}, | |||
| heatmapUser: {{if .HeatmapUser}}'{{.HeatmapUser}}'{{else}}null{{end}}, | |||
| NotificationSettings: { | |||
| MinTimeout: {{NotificationSettings.MinTimeout}}, | |||
| TimeoutStep: {{NotificationSettings.TimeoutStep}}, | |||
| MaxTimeout: {{NotificationSettings.MaxTimeout}}, | |||
| EventSourceUpdateTime: {{NotificationSettings.EventSourceUpdateTime}}, | |||
| }, | |||
| {{if .RequireTribute}} | |||
| tributeValues: [ | |||
| {{ range .Assignees }} | |||
| {key: '{{.Name}} {{.FullName}}', value: '{{.Name}}', | |||
| name: '{{.Name}}', fullname: '{{.FullName}}', avatar: '{{.RelAvatarLink}}'}, | |||
| {{ end }} | |||
| ], | |||
| {{end}} | |||
| }; | |||
| </script> | |||
| <link rel="shortcut icon" href="{{StaticUrlPrefix}}/img/favicon.png"> | |||
| <link rel="mask-icon" href="{{StaticUrlPrefix}}/img/openi-safari.svg" color="#609926"> | |||
| <link rel="fluid-icon" href="{{StaticUrlPrefix}}/img/gitea-lg.png" title="{{AppName}}"> | |||
| <link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/assets/font-awesome/css/font-awesome.min.css"> | |||
| <link rel="preload" as="font" href="{{StaticUrlPrefix}}/fomantic/themes/default/assets/fonts/icons.woff2" type="font/woff2" crossorigin="anonymous"> | |||
| <link rel="preload" as="font" href="{{StaticUrlPrefix}}/fomantic/themes/default/assets/fonts/outline-icons.woff2" type="font/woff2" crossorigin="anonymous"> | |||
| {{if .RequireSimpleMDE}} | |||
| <link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/plugins/simplemde/simplemde.min.css"> | |||
| {{end}} | |||
| {{if .RequireTribute}} | |||
| <link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/plugins/tribute/tribute.css"> | |||
| {{end}} | |||
| <link rel="stylesheet" href="{{StaticUrlPrefix}}/fomantic/semantic.min.css?v={{MD5 AppVer}}"> | |||
| <link rel="stylesheet" href="{{StaticUrlPrefix}}/css/index.css?v={{MD5 AppVer}}"> | |||
| <noscript> | |||
| <style> | |||
| .dropdown:hover > .menu { display: block; } | |||
| .ui.secondary.menu .dropdown.item > .menu { margin-top: 0; } | |||
| </style> | |||
| </noscript> | |||
| {{if .RequireMinicolors}} | |||
| <link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/plugins/jquery.minicolors/jquery.minicolors.css"> | |||
| {{end}} | |||
| <style class="list-search-style"></style> | |||
| {{if .PageIsUserProfile}} | |||
| <meta property="og:title" content="{{.Owner.Name}}" /> | |||
| <meta property="og:type" content="profile" /> | |||
| <meta property="og:image" content="{{.Owner.AvatarLink}}" /> | |||
| <meta property="og:url" content="{{.Owner.HTMLURL}}" /> | |||
| {{if .Owner.Description}} | |||
| <meta property="og:description" content="{{.Owner.Description}}"> | |||
| {{end}} | |||
| {{else if .Repository}} | |||
| {{if .Issue}} | |||
| <meta property="og:title" content="{{.Issue.Title}}" /> | |||
| <meta property="og:url" content="{{.Issue.HTMLURL}}" /> | |||
| {{if .Issue.Content}} | |||
| <meta property="og:description" content="{{.Issue.Content}}" /> | |||
| {{end}} | |||
| {{else}} | |||
| <meta property="og:title" content="{{.Repository.Name}}" /> | |||
| <meta property="og:url" content="{{.Repository.HTMLURL}}" /> | |||
| {{if .Repository.Description}} | |||
| <meta property="og:description" content="{{.Repository.Description}}" /> | |||
| {{end}} | |||
| {{end}} | |||
| <meta property="og:type" content="object" /> | |||
| <meta property="og:image" content="{{.Repository.Owner.AvatarLink}}" /> | |||
| {{else}} | |||
| <meta property="og:title" content="{{AppName}}"> | |||
| <meta property="og:type" content="website" /> | |||
| <meta property="og:image" content="{{StaticUrlPrefix}}/img/gitea-lg.png" /> | |||
| <meta property="og:url" content="{{AppUrl}}" /> | |||
| <meta property="og:description" content="{{MetaDescription}}"> | |||
| {{end}} | |||
| <meta property="og:site_name" content="{{AppName}}" /> | |||
| {{if .IsSigned }} | |||
| {{ if ne .SignedUser.Theme "gitea" }} | |||
| <link rel="stylesheet" href="{{StaticUrlPrefix}}/css/theme-{{.SignedUser.Theme}}.css?v={{MD5 AppVer}}"> | |||
| {{end}} | |||
| {{else if ne DefaultTheme "gitea"}} | |||
| <link rel="stylesheet" href="{{StaticUrlPrefix}}/css/theme-{{DefaultTheme}}.css?v={{MD5 AppVer}}"> | |||
| {{end}} | |||
| {{template "custom/header" .}} | |||
| <script> | |||
| var _hmt = _hmt || []; | |||
| (function() { | |||
| var hm = document.createElement("script"); | |||
| hm.src = "https://hm.baidu.com/hm.js?46149a0b61fdeddfe427ff4de63794ba"; | |||
| var s = document.getElementsByTagName("script")[0]; | |||
| s.parentNode.insertBefore(hm, s); | |||
| })(); | |||
| </script> | |||
| <script src="/self/func.js" type="text/javascript"></script> | |||
| </head> | |||
| <body> | |||
| {{template "custom/body_outer_pre" .}} | |||
| <div class="full height"> | |||
| <noscript>{{.i18n.Tr "enable_javascript"}}</noscript> | |||
| {{template "custom/body_inner_pre" .}} | |||
| {{if not .PageIsInstall}} | |||
| <div class="ui top secondary stackable main menu following bar dark"> | |||
| {{template "base/head_navbar_fluid" .}} | |||
| </div><!-- end bar --> | |||
| {{end}} | |||
| {{/* | |||
| </div> | |||
| </body> | |||
| </html> | |||
| */}} | |||
| @@ -0,0 +1,177 @@ | |||
| <div class="ui fluid container" style = "padding: 0px 20px;" id="navbar"> | |||
| <div class="item brand" style="justify-content: space-between;"> | |||
| <a href="https://openi.org.cn/"> | |||
| <img class="ui mini image" src="{{StaticUrlPrefix}}/img/logo-w.svg"> | |||
| </a> | |||
| <div class="ui basic icon button mobile-only" id="navbar-expand-toggle"> | |||
| <i class="sidebar icon"></i> | |||
| </div> | |||
| </div> | |||
| <div style="width:1px;background:#606266;height:80%;margin:auto 0.5rem"></div> | |||
| <div class="item brand" style="margin-left: 0.9rem;"> | |||
| <a href="/"> | |||
| <img class="ui mini image" style="height: 1.3rem;" src="{{StaticUrlPrefix}}/img/git-logo.svg"> | |||
| </a> | |||
| </div> | |||
| {{if .IsSigned}} | |||
| <a class="item {{if .PageIsDashboard}}active{{end}}" href="/dashboard">{{.i18n.Tr "index"}}</a> | |||
| <a class="item" href="{{AppSubUrl}}/OpenI">{{.i18n.Tr "custom.head.openi"}}</a> | |||
| {{if not .UnitIssuesGlobalDisabled}} | |||
| <a class="item {{if .PageIsIssues}}active{{end}}" href="{{AppSubUrl}}/issues">{{.i18n.Tr "issues"}}</a> | |||
| {{end}} | |||
| {{if not .UnitPullsGlobalDisabled}} | |||
| <a class="item {{if .PageIsPulls}}active{{end}}" href="{{AppSubUrl}}/pulls">{{.i18n.Tr "pull_requests"}}</a> | |||
| {{end}} | |||
| {{if not (and .UnitIssuesGlobalDisabled .UnitPullsGlobalDisabled)}} | |||
| {{if .ShowMilestonesDashboardPage}}<a class="item {{if .PageIsMilestonesDashboard}}active{{end}}" href="{{AppSubUrl}}/milestones">{{.i18n.Tr "milestones"}}</a>{{end}} | |||
| {{end}} | |||
| <div class="ui dropdown item"> | |||
| {{.i18n.Tr "explore"}} | |||
| <i class="dropdown icon"></i> | |||
| <div class="menu"> | |||
| <a class="item" href="{{AppSubUrl}}/explore/repos">{{.i18n.Tr "custom.head.project"}}</a> | |||
| <a class="item" href="{{AppSubUrl}}/explore/datasets">{{.i18n.Tr "custom.head.dataset"}}</a> | |||
| <a class="item" href="{{AppSubUrl}}/explore/users">{{.i18n.Tr "explore.users"}}</a> | |||
| <a class="item" href="{{AppSubUrl}}/explore/organizations">{{.i18n.Tr "explore.organizations"}}</a> | |||
| <a class="item" href="{{AppSubUrl}}/explore/images">{{.i18n.Tr "explore.images"}}</a> | |||
| {{if .IsAdmin}} | |||
| <a class="item" href="{{AppSubUrl}}/explore/data_analysis">{{.i18n.Tr "explore.data_analysis"}}</a> | |||
| {{end}} | |||
| </div> | |||
| </div> | |||
| {{else if .IsLandingPageHome}} | |||
| <a class="item {{if .PageIsHome}}active{{end}}" href="{{AppSubUrl}}/dashboard">{{.i18n.Tr "home"}}</a> | |||
| <a class="item" href="{{AppSubUrl}}/OpenI">{{.i18n.Tr "custom.head.openi"}}</a> | |||
| <div class="ui dropdown item"> | |||
| {{.i18n.Tr "explore"}} | |||
| <i class="dropdown icon"></i> | |||
| <div class="menu"> | |||
| <a class="item" href="{{AppSubUrl}}/explore/repos">{{.i18n.Tr "custom.head.project"}}</a> | |||
| <a class="item" href="{{AppSubUrl}}/explore/datasets">{{.i18n.Tr "datasets"}}</a> | |||
| <a class="item" href="{{AppSubUrl}}/explore/users">{{.i18n.Tr "explore.users"}}</a> | |||
| <a class="item" href="{{AppSubUrl}}/explore/organizations">{{.i18n.Tr "explore.organizations"}}</a> | |||
| <a class="item" href="{{AppSubUrl}}/explore/images">{{.i18n.Tr "explore.images"}}</a> | |||
| {{if .IsAdmin}} | |||
| <a class="item" href="{{AppSubUrl}}/explore/data_analysis">{{.i18n.Tr "explore.data_analysis"}}</a> | |||
| {{end}} | |||
| </div> | |||
| </div> | |||
| {{else if .IsLandingPageExplore}} | |||
| <a class="item {{if .PageIsExplore}}active{{end}}" href="{{AppSubUrl}}/explore/repos">{{.i18n.Tr "home"}}</a> | |||
| {{else if .IsLandingPageOrganizations}} | |||
| <a class="item {{if .PageIsExplore}}active{{end}}" href="{{AppSubUrl}}/explore/organizations">{{.i18n.Tr "home"}}</a> | |||
| {{end}} | |||
| {{template "custom/extra_links" .}} | |||
| {{/* | |||
| <div class="item"> | |||
| <div class="ui icon input"> | |||
| <input class="searchbox" type="text" placeholder="{{.i18n.Tr "search_project"}}"> | |||
| <i class="search icon"></i> | |||
| </div> | |||
| </div> | |||
| */}} | |||
| {{if .IsSigned}} | |||
| <div class="right stackable menu"> | |||
| <a href="{{AppSubUrl}}/notifications" class="item poping up" data-content='{{.i18n.Tr "notifications"}}' data-variation="tiny inverted"> | |||
| <span class="text"> | |||
| <span class="fitted">{{svg "octicon-bell" 16}}</span> | |||
| <span class="sr-mobile-only">{{.i18n.Tr "notifications"}}</span> | |||
| {{$notificationUnreadCount := 0}} | |||
| {{if .NotificationUnreadCount}}{{$notificationUnreadCount = call .NotificationUnreadCount}}{{end}} | |||
| <span class="ui red label {{if not $notificationUnreadCount}}hidden{{end}} notification_count"> | |||
| {{$notificationUnreadCount}} | |||
| </span> | |||
| </span> | |||
| </a> | |||
| <div class="ui dropdown jump item poping up" data-content="{{.i18n.Tr "create_new"}}" data-variation="tiny inverted"> | |||
| <span class="text"> | |||
| <span class="fitted">{{svg "octicon-plus" 16}}</span> | |||
| <span class="sr-mobile-only">{{.i18n.Tr "create_new"}}</span> | |||
| <span class="fitted not-mobile">{{svg "octicon-triangle-down" 16}}</span> | |||
| </span> | |||
| <div class="menu"> | |||
| <a class="item" href="{{AppSubUrl}}/repo/create"> | |||
| <span class="fitted">{{svg "octicon-plus" 16}}</span> {{.i18n.Tr "new_repo"}} | |||
| </a> | |||
| <a class="item" href="{{AppSubUrl}}/repo/migrate"> | |||
| <span class="fitted">{{svg "octicon-repo-clone" 16}}</span> {{.i18n.Tr "new_migrate"}} | |||
| </a> | |||
| {{if .SignedUser.CanCreateOrganization}} | |||
| <a class="item" href="{{AppSubUrl}}/org/create"> | |||
| <span class="fitted">{{svg "octicon-organization" 16}}</span> {{.i18n.Tr "new_org"}} | |||
| </a> | |||
| {{end}} | |||
| </div><!-- end content create new menu --> | |||
| </div><!-- end dropdown menu create new --> | |||
| <div class="ui dropdown jump item poping up" tabindex="-1" data-content="{{.i18n.Tr "user_profile_and_more"}}" data-variation="tiny inverted"> | |||
| <span class="text"> | |||
| <img class="ui tiny avatar image" width="24" height="24" src="{{.SignedUser.RelAvatarLink}}"> | |||
| <span class="sr-only">{{.i18n.Tr "user_profile_and_more"}}</span> | |||
| <span class="mobile-only">{{.SignedUser.Name}}</span> | |||
| <span class="fitted not-mobile" tabindex="-1">{{svg "octicon-triangle-down" 16}}</span> | |||
| </span> | |||
| <div class="menu user-menu" tabindex="-1"> | |||
| <div class="ui header"> | |||
| {{.i18n.Tr "signed_in_as"}} <strong>{{.SignedUser.Name}}</strong> | |||
| </div> | |||
| <div class="divider"></div> | |||
| <a class="item" href="{{AppSubUrl}}/{{.SignedUser.Name}}"> | |||
| {{svg "octicon-person" 16}} | |||
| {{.i18n.Tr "your_profile"}}<!-- Your profile --> | |||
| </a> | |||
| <a class="item" href="{{AppSubUrl}}/{{.SignedUser.Name}}?tab=stars"> | |||
| {{svg "octicon-star" 16}} | |||
| {{.i18n.Tr "your_starred"}} | |||
| </a> | |||
| <a class="{{if .PageIsUserSettings}}active{{end}} item" href="{{AppSubUrl}}/user/settings"> | |||
| {{svg "octicon-settings" 16}} | |||
| {{.i18n.Tr "your_settings"}}<!-- Your settings --> | |||
| </a> | |||
| <!--a class="item" target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io"> | |||
| {{svg "octicon-question" 16}} | |||
| {{.i18n.Tr "help"}}<!-- Help --> | |||
| </a--> | |||
| {{if .IsAdmin}} | |||
| <div class="divider"></div> | |||
| <a class="{{if .PageIsAdmin}}active{{end}} item" href="{{AppSubUrl}}/admin"> | |||
| <i class="icon settings"></i> | |||
| {{.i18n.Tr "admin_panel"}}<!-- Admin Panel --> | |||
| </a> | |||
| {{end}} | |||
| <div class="divider"></div> | |||
| <a class="item link-action" href data-url="{{AppSubUrl}}/user/logout" data-redirect="{{AppSubUrl}}/"> | |||
| {{svg "octicon-sign-out" 16}} | |||
| {{.i18n.Tr "sign_out"}}<!-- Sign Out --> | |||
| </a> | |||
| </div><!-- end content avatar menu --> | |||
| </div><!-- end dropdown avatar menu --> | |||
| </div><!-- end signed user right menu --> | |||
| {{else}} | |||
| <!--a class="item" target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io">{{.i18n.Tr "help"}}</a--> | |||
| <div class="right stackable menu"> | |||
| {{if .ShowRegistrationButton}} | |||
| <a class="item{{if .PageIsSignUp}} active{{end}}" href="{{AppSubUrl}}/user/sign_up"> | |||
| {{svg "octicon-person" 16}} {{.i18n.Tr "register"}} | |||
| </a> | |||
| {{end}} | |||
| <a class="item{{if .PageIsSignIn}} active{{end}}" rel="nofollow" href="{{AppSubUrl}}/user/login"> | |||
| {{svg "octicon-sign-in" 16}} {{.i18n.Tr "sign_in"}} | |||
| </a> | |||
| </div><!-- end anonymous right menu --> | |||
| {{end}} | |||
| </div> | |||
| @@ -1,14 +1,15 @@ | |||
| {{template "base/head" .}} | |||
| {{template "base/head_fluid" .}} | |||
| <div id="data_analysis" style="height: 100%;"> | |||
| </div> | |||
| {{template "base/footer" .}} | |||
| {{template "base/footer_fluid" .}} | |||
| <style> | |||
| .full.height { | |||
| flex-grow: 1; | |||
| /* flex-grow: 1; */ | |||
| padding-bottom: 53px; | |||
| } | |||
| </style> | |||
| </style> | |||
| @@ -11,7 +11,7 @@ | |||
| {{.i18n.Tr "repo.cloudbrain"}} | |||
| </a> | |||
| <div class="divider"> / </div> | |||
| <a class="section" href="{{.RepoLink}}/modelarts/notebook"> | |||
| <a class="section" href="{{.RepoLink}}/cloudbrain"> | |||
| {{$.i18n.Tr "repo.modelarts.notebook"}} | |||
| </a> | |||
| <div class="divider"> / </div> | |||
| @@ -11,7 +11,7 @@ | |||
| {{.i18n.Tr "repo.cloudbrain"}} | |||
| </a> | |||
| <div class="divider"> / </div> | |||
| <a class="section" href="{{.RepoLink}}/cloudbrain"> | |||
| <a class="section" href="{{.RepoLink}}/modelarts/notebook"> | |||
| {{$.i18n.Tr "repo.modelarts.notebook"}} | |||
| </a> | |||
| <div class="divider"> / </div> | |||
| @@ -328,7 +328,7 @@ | |||
| </div> | |||
| <!-- 版本数量 --> | |||
| <div class="one wide column text center padding0"> | |||
| <span>{{.VersionCount}} </span> | |||
| <span style="font-size: 12px;">{{.VersionCount}} </span> | |||
| </div> | |||
| <!-- 任务状态 --> | |||
| <div class="two wide column padding0" style="padding-left: 2.2rem !important;"> | |||
| @@ -87,7 +87,7 @@ | |||
| padding-right: 20px; | |||
| color: #8a8e99; | |||
| font-size: 12px; | |||
| white-space: nowrap; | |||
| white-space: nowrap !important; | |||
| width: 80px; | |||
| line-height: 30px; | |||
| } | |||
| @@ -103,6 +103,7 @@ td, th { | |||
| padding: 0; | |||
| } | |||
| .ac-grid-col .text-span { | |||
| width: 450px; | |||
| overflow: hidden; | |||
| text-overflow: ellipsis; | |||
| white-space: nowrap; | |||
| @@ -212,10 +213,10 @@ td, th { | |||
| <span class="cti-mgRight-sm">{{TimeSinceUnix1 .Cloudbrain.CreatedUnix}}</span> | |||
| <span class="cti-mgRight-sm"> {{$.i18n.Tr "repo.modelarts.current_version"}}:{{.VersionName}}</span> | |||
| <span class="cti-mgRight-sm"> {{$.i18n.Tr "repo.modelarts.parent_version"}}:{{.PreVersionName}}</span> | |||
| <span class="cti-mgRight-sm ac-text-normal title_text">{{$.i18n.Tr "repo.modelarts.status"}}: | |||
| <span class="cti-mgRight-sm">{{$.i18n.Tr "repo.modelarts.status"}}: | |||
| <span id="{{.VersionName}}-status-span"><i id="icon" style="vertical-align: middle;" class="{{.Status}}"></i><span id="text" style="margin-left: 0.4em;font-size: 12px;">{{.Status}}</span></span> | |||
| </span> | |||
| <span class="ac-text-normal title_text">{{$.i18n.Tr "repo.modelarts.train_job.dura_time"}}:</span> | |||
| <span class="cti-mgRight-sm">{{$.i18n.Tr "repo.modelarts.train_job.dura_time"}}:</span> | |||
| <span class="cti-mgRight-sm uc-accordionTitle-black" id="{{.VersionName}}-duration-span">{{.TrainJobDuration}}</span> | |||
| <span data-tooltip="刷新" style="cursor: pointer;" data-inverted="" onclick="refreshStatus({{.VersionName}})"><i class="redo icon redo-color"></i></span> | |||
| @@ -368,12 +369,12 @@ td, th { | |||
| </td> | |||
| </tr> | |||
| <tr class="ti-no-ng-animate"> | |||
| <td class="ti-no-ng-animate ti-text-form-label text-width80"> | |||
| <td class="ti-no-ng-animate ti-text-form-label text-width80" > | |||
| {{$.i18n.Tr "repo.modelarts.train_job.run_parameter"}} | |||
| </td> | |||
| <td class="ti-text-form-content"> | |||
| <div class="text-span text-span-w"> | |||
| <div class="text-span text-span-w" title="{{.Parameters}}"> | |||
| {{.Parameters}} | |||
| </div> | |||
| </td> | |||
| @@ -395,7 +396,7 @@ td, th { | |||
| </td> | |||
| <td class="ti-text-form-content"> | |||
| <div class="text-span text-span-w"> | |||
| <div class="text-span text-span-w" title="{{.Cloudbrain.Description}}"> | |||
| {{.Cloudbrain.Description}} | |||
| </div> | |||
| </td> | |||
| @@ -410,7 +411,7 @@ td, th { | |||
| </div> | |||
| <div class="ui tab" data-tab="second{{$k}}"> | |||
| <div> | |||
| <div class="ui message{{.VersionName}}" style="display: none;"> | |||
| <div class="ui message message{{.VersionName}}" style="display: none;"> | |||
| <div id="header"></div> | |||
| </div> | |||
| <div class="ui top attached segment" style="background: #f0f0f0;"> | |||
| @@ -449,7 +450,7 @@ td, th { | |||
| </div> | |||
| </div> | |||
| </div> | |||
| {{end}} | |||
| {{end}} {{template "base/paginate" .}} | |||
| </div> | |||
| <!-- 确认模态框 --> | |||
| <div id="deletemodel"> | |||
| @@ -339,7 +339,7 @@ | |||
| {{template "base/footer" .}} | |||
| <script> | |||
| let url_href = {{.RepoLink}}+'/modelarts/train-job' | |||
| let url_href = location.pathname.split('create_version')[0] | |||
| let url_post = location.pathname | |||
| let version_name = location.search.split('?version_name=')[1] | |||
| $("#parents_version").val(version_name) | |||
| @@ -207,44 +207,46 @@ | |||
| </el-col> | |||
| <el-col :span=6 > | |||
| <div class="item_r"> | |||
| <div style="font-size:14px;color:rgb(0,0,0);margin:20px 0px">贡献者TOP10</div> | |||
| <div> | |||
| <el-table | |||
| :data="tableDataContTop10" | |||
| style="width: 100%" | |||
| stripe | |||
| :header-cell-style="tableHeaderStyle" | |||
| > | |||
| <el-table-column | |||
| label="用户名" | |||
| align="left" | |||
| prop="user"> | |||
| <template slot-scope="scope"> | |||
| <a v-if="scope.row.relAvatarLink!=''" :href="AppSubUrl +'../../../'+ scope.row.user"><img class="ui avatar s16 image js-popover-card" :src="scope.row.relAvatarLink">{{scope.row.user}} </a> | |||
| <a v-else :href="'mailto:'+ scope.row.email "> <img class="ui avatar s16 image js-popover-card" :avatar="scope.row.email"> {{scope.row.user}}</a> | |||
| </template> | |||
| </el-table-column> | |||
| <el-table-column | |||
| label="身份" | |||
| align="center" | |||
| prop="mode" | |||
| v-if='0'> | |||
| <template slot-scope="scope"> | |||
| {{scope.row.mode | showMode}} | |||
| </template> | |||
| </el-table-column> | |||
| <el-table-column | |||
| prop="pr" | |||
| label="PR" | |||
| align="center"> | |||
| </el-table-column> | |||
| <el-table-column | |||
| prop="commit" | |||
| label="commit" | |||
| align="center"> | |||
| </el-table-column> | |||
| </el-table> | |||
| <div style="margin:0 5px;"> | |||
| <div style="font-size:14px;color:rgb(0,0,0);margin:10px 0px">贡献者TOP10</div> | |||
| <div> | |||
| <el-table | |||
| :data="tableDataContTop10" | |||
| style="width: 100%" | |||
| stripe | |||
| :header-cell-style="tableHeaderStyle" | |||
| > | |||
| <el-table-column | |||
| label="用户名" | |||
| align="left" | |||
| prop="user"> | |||
| <template slot-scope="scope"> | |||
| <a v-if="scope.row.relAvatarLink!=''" :href="AppSubUrl +'../../../'+ scope.row.user"><img class="ui avatar s16 image js-popover-card" :src="scope.row.relAvatarLink">{{scope.row.user}} </a> | |||
| <a v-else :href="'mailto:'+ scope.row.email "> <img class="ui avatar s16 image js-popover-card" :avatar="scope.row.email"> {{scope.row.user}}</a> | |||
| </template> | |||
| </el-table-column> | |||
| <el-table-column | |||
| label="身份" | |||
| align="center" | |||
| prop="mode" | |||
| v-if='0'> | |||
| <template slot-scope="scope"> | |||
| {{scope.row.mode | showMode}} | |||
| </template> | |||
| </el-table-column> | |||
| <el-table-column | |||
| prop="pr" | |||
| label="PR" | |||
| align="center"> | |||
| </el-table-column> | |||
| <el-table-column | |||
| prop="commit" | |||
| label="commit" | |||
| align="center"> | |||
| </el-table-column> | |||
| </el-table> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </el-col> | |||
| @@ -1206,6 +1208,11 @@ | |||
| height: 30px; | |||
| border-radius:0px 4px 4px 0px; | |||
| } | |||
| .btnFirst, .btn, .btnLast { | |||
| cursor: pointer; | |||
| } | |||
| /* | |||
| .btn:focus, | |||
| .btn:active{ | |||
| @@ -1229,6 +1236,7 @@ | |||
| .colorChange { | |||
| background-color: #409effd6; | |||
| color: #FFFF; | |||
| cursor: default; | |||
| } | |||
| .items{ | |||
| text-align: center; | |||
| @@ -504,6 +504,10 @@ | |||
| height: 30px; | |||
| border-radius:0px 4px 4px 0px; | |||
| } | |||
| .btnFirst,.btn,.btnLast { | |||
| cursor: pointer; | |||
| } | |||
| /* .btn:focus, | |||
| .btn:active{ | |||
| @@ -524,8 +528,9 @@ | |||
| } | |||
| .colorChange { | |||
| background-color: #409effd6; | |||
| color: #FFFF; | |||
| background-color: #409effd6; | |||
| color: #FFFF; | |||
| cursor: default; | |||
| } | |||
| </style> | |||