| @@ -182,6 +182,7 @@ func CreateOrganization(org, owner *User) (err error) { | |||||
| if _, err = sess.Insert(&OrgUser{ | if _, err = sess.Insert(&OrgUser{ | ||||
| UID: owner.ID, | UID: owner.ID, | ||||
| OrgID: org.ID, | OrgID: org.ID, | ||||
| IsPublic: setting.Service.DefaultOrgMemberVisible, | |||||
| }); err != nil { | }); err != nil { | ||||
| return fmt.Errorf("insert org-user relation: %v", err) | return fmt.Errorf("insert org-user relation: %v", err) | ||||
| } | } | ||||
| @@ -210,9 +210,12 @@ type Repository struct { | |||||
| Balance string `xorm:"NOT NULL DEFAULT '0'"` | Balance string `xorm:"NOT NULL DEFAULT '0'"` | ||||
| BlockChainStatus RepoBlockChainStatus `xorm:"NOT NULL DEFAULT 0"` | BlockChainStatus RepoBlockChainStatus `xorm:"NOT NULL DEFAULT 0"` | ||||
| // git clone total count | |||||
| // git clone and git pull total count | |||||
| CloneCnt int64 `xorm:"NOT NULL DEFAULT 0"` | CloneCnt int64 `xorm:"NOT NULL DEFAULT 0"` | ||||
| // only git clone total count | |||||
| GitCloneCnt int64 `xorm:"NOT NULL DEFAULT 0"` | |||||
| CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` | CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` | ||||
| UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` | UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` | ||||
| @@ -2473,6 +2476,24 @@ func (repo *Repository) IncreaseCloneCnt() { | |||||
| return | return | ||||
| } | } | ||||
| func (repo *Repository) IncreaseGitCloneCnt() { | |||||
| sess := x.NewSession() | |||||
| defer sess.Close() | |||||
| if err := sess.Begin(); err != nil { | |||||
| return | |||||
| } | |||||
| if _, err := sess.Exec("UPDATE `repository` SET git_clone_cnt = git_clone_cnt + 1 WHERE id = ?", repo.ID); err != nil { | |||||
| return | |||||
| } | |||||
| if err := sess.Commit(); err != nil { | |||||
| return | |||||
| } | |||||
| return | |||||
| } | |||||
| func UpdateRepositoryCommitNum(repo *Repository) error { | func UpdateRepositoryCommitNum(repo *Repository) error { | ||||
| if _, err := x.Exec("UPDATE `repository` SET num_commit = ? where id = ?", repo.NumCommit, repo.ID); err != nil { | if _, err := x.Exec("UPDATE `repository` SET num_commit = ? where id = ?", repo.NumCommit, repo.ID); err != nil { | ||||
| return err | return err | ||||
| @@ -163,6 +163,7 @@ var ( | |||||
| // UI settings | // UI settings | ||||
| UI = struct { | UI = struct { | ||||
| ExplorePagingNum int | ExplorePagingNum int | ||||
| ContributorPagingNum int | |||||
| IssuePagingNum int | IssuePagingNum int | ||||
| RepoSearchPagingNum int | RepoSearchPagingNum int | ||||
| MembersPagingNum int | MembersPagingNum int | ||||
| @@ -203,19 +204,20 @@ var ( | |||||
| Keywords string | Keywords string | ||||
| } `ini:"ui.meta"` | } `ini:"ui.meta"` | ||||
| }{ | }{ | ||||
| ExplorePagingNum: 20, | |||||
| IssuePagingNum: 10, | |||||
| RepoSearchPagingNum: 10, | |||||
| MembersPagingNum: 20, | |||||
| FeedMaxCommitNum: 5, | |||||
| GraphMaxCommitNum: 100, | |||||
| CodeCommentLines: 4, | |||||
| ReactionMaxUserNum: 10, | |||||
| ThemeColorMetaTag: `#6cc644`, | |||||
| MaxDisplayFileSize: 8388608, | |||||
| DefaultTheme: `gitea`, | |||||
| Themes: []string{`gitea`, `arc-green`}, | |||||
| Reactions: []string{`+1`, `-1`, `laugh`, `hooray`, `confused`, `heart`, `rocket`, `eyes`}, | |||||
| ExplorePagingNum: 20, | |||||
| ContributorPagingNum: 50, | |||||
| IssuePagingNum: 10, | |||||
| RepoSearchPagingNum: 10, | |||||
| MembersPagingNum: 20, | |||||
| FeedMaxCommitNum: 5, | |||||
| GraphMaxCommitNum: 100, | |||||
| CodeCommentLines: 4, | |||||
| ReactionMaxUserNum: 10, | |||||
| ThemeColorMetaTag: `#6cc644`, | |||||
| MaxDisplayFileSize: 8388608, | |||||
| DefaultTheme: `gitea`, | |||||
| Themes: []string{`gitea`, `arc-green`}, | |||||
| Reactions: []string{`+1`, `-1`, `laugh`, `hooray`, `confused`, `heart`, `rocket`, `eyes`}, | |||||
| Notification: struct { | Notification: struct { | ||||
| MinTimeout time.Duration | MinTimeout time.Duration | ||||
| TimeoutStep time.Duration | TimeoutStep time.Duration | ||||
| @@ -10,11 +10,11 @@ import ( | |||||
| "strconv" | "strconv" | ||||
| "strings" | "strings" | ||||
| "github.com/unknwon/com" | |||||
| "code.gitea.io/gitea/modules/log" | "code.gitea.io/gitea/modules/log" | ||||
| "code.gitea.io/gitea/modules/obs" | "code.gitea.io/gitea/modules/obs" | ||||
| "code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
| "github.com/unknwon/com" | |||||
| ) | ) | ||||
| type FileInfo struct { | type FileInfo struct { | ||||
| @@ -178,30 +178,45 @@ func GetObsListObject(jobName, parentDir string) ([]FileInfo, error) { | |||||
| input := &obs.ListObjectsInput{} | input := &obs.ListObjectsInput{} | ||||
| input.Bucket = setting.Bucket | 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, parentDir), "/") | ||||
| strPrefix := strings.Split(input.Prefix, "/") | |||||
| output, err := ObsCli.ListObjects(input) | output, err := ObsCli.ListObjects(input) | ||||
| fileInfos := make([]FileInfo, 0) | fileInfos := make([]FileInfo, 0) | ||||
| if err == nil { | if err == nil { | ||||
| for _, val := range output.Contents { | for _, val := range output.Contents { | ||||
| str1 := strings.Split(val.Key, "/") | str1 := strings.Split(val.Key, "/") | ||||
| var isDir bool | var isDir bool | ||||
| var fileName,nextParentDir string | |||||
| var fileName, nextParentDir string | |||||
| if strings.HasSuffix(val.Key, "/") { | if strings.HasSuffix(val.Key, "/") { | ||||
| //dirs in next level dir | |||||
| if len(str1)-len(strPrefix) > 2 { | |||||
| continue | |||||
| } | |||||
| fileName = str1[len(str1)-2] | fileName = str1[len(str1)-2] | ||||
| isDir = true | isDir = true | ||||
| nextParentDir = fileName | |||||
| if fileName == parentDir || (fileName + "/") == setting.OutPutPath { | |||||
| if parentDir == "" { | |||||
| nextParentDir = fileName | |||||
| } else { | |||||
| nextParentDir = parentDir + "/" + fileName | |||||
| } | |||||
| if fileName == strPrefix[len(strPrefix)-1] || (fileName+"/") == setting.OutPutPath { | |||||
| continue | continue | ||||
| } | } | ||||
| } else { | } else { | ||||
| //files in next level dir | |||||
| if len(str1)-len(strPrefix) > 1 { | |||||
| continue | |||||
| } | |||||
| fileName = str1[len(str1)-1] | fileName = str1[len(str1)-1] | ||||
| isDir = false | isDir = false | ||||
| nextParentDir = parentDir | |||||
| } | } | ||||
| fileInfo := FileInfo{ | fileInfo := FileInfo{ | ||||
| ModTime: val.LastModified.Format("2006-01-02 15:04:05"), | |||||
| ModTime: val.LastModified.Local().Format("2006-01-02 15:04:05"), | |||||
| FileName: fileName, | FileName: fileName, | ||||
| Size: val.Size, | |||||
| IsDir:isDir, | |||||
| Size: val.Size, | |||||
| IsDir: isDir, | |||||
| ParenDir: nextParentDir, | ParenDir: nextParentDir, | ||||
| } | } | ||||
| fileInfos = append(fileInfos, fileInfo) | fileInfos = append(fileInfos, fileInfo) | ||||
| @@ -242,7 +257,7 @@ func GetObsCreateSignedUrl(jobName, parentDir, fileName string) (string, error) | |||||
| input := &obs.CreateSignedUrlInput{} | input := &obs.CreateSignedUrlInput{} | ||||
| input.Bucket = setting.Bucket | input.Bucket = setting.Bucket | ||||
| input.Key = strings.TrimPrefix(path.Join(setting.TrainJobModelPath, jobName, setting.OutPutPath, parentDir, fileName), "/") | input.Key = strings.TrimPrefix(path.Join(setting.TrainJobModelPath, jobName, setting.OutPutPath, parentDir, fileName), "/") | ||||
| input.Expires = 60 * 60 | input.Expires = 60 * 60 | ||||
| input.Method = obs.HttpMethodGet | input.Method = obs.HttpMethodGet | ||||
| @@ -218,6 +218,7 @@ show_only_private = Showing only private | |||||
| show_only_public = Showing only public | show_only_public = Showing only public | ||||
| issues.in_your_repos = In your repositories | issues.in_your_repos = In your repositories | ||||
| contributors = Contributors | |||||
| [explore] | [explore] | ||||
| repos = Repositories | repos = Repositories | ||||
| @@ -755,6 +756,7 @@ unit_disabled = The site administrator has disabled this repository section. | |||||
| language_other = Other | language_other = Other | ||||
| datasets = Datasets | datasets = Datasets | ||||
| datasets.desc = Enable Dataset | datasets.desc = Enable Dataset | ||||
| cloudbrain_helper=Use GPU/NPU resources to open notebooks, model training tasks, etc. | |||||
| debug=Debug | debug=Debug | ||||
| stop=Stop | stop=Stop | ||||
| @@ -220,6 +220,8 @@ show_only_public=只显示公开的 | |||||
| issues.in_your_repos=属于该用户项目的 | issues.in_your_repos=属于该用户项目的 | ||||
| contributors=贡献者 | |||||
| [explore] | [explore] | ||||
| repos=项目 | repos=项目 | ||||
| users=用户 | users=用户 | ||||
| @@ -757,6 +759,7 @@ unit_disabled=站点管理员已禁用此项目单元。 | |||||
| language_other=其它 | language_other=其它 | ||||
| datasets=数据集 | datasets=数据集 | ||||
| datasets.desc=数据集功能 | datasets.desc=数据集功能 | ||||
| cloudbrain_helper=使用GPU/NPU资源,开启Notebook、模型训练任务等 | |||||
| debug=调试 | debug=调试 | ||||
| stop=停止 | stop=停止 | ||||
| @@ -0,0 +1,41 @@ | |||||
| <?xml version="1.0" encoding="utf-8"?> | |||||
| <!-- Generator: Adobe Illustrator 25.4.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> | |||||
| <svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" | |||||
| viewBox="0 0 96 17.3" style="enable-background:new 0 0 96 17.3;" xml:space="preserve"> | |||||
| <style type="text/css"> | |||||
| .st0{fill:#5BB973;} | |||||
| </style> | |||||
| <g> | |||||
| <path class="st0" d="M5.9,12.5l-1,3.8h-3L6.6,1.5H10l4.7,14.8h-3.1l-1-3.8H5.9z M6.5,10.2H10L9.6,8.5C9.4,7.8,9.1,7,8.9,6.1 | |||||
| C8.7,5.3,8.5,4.5,8.3,3.7H8.2C8,4.5,7.8,5.3,7.6,6.2S7.2,7.8,6.9,8.5L6.5,10.2z"/> | |||||
| <path class="st0" d="M19.5,1.5v14.8h-3V1.5H19.5z"/> | |||||
| <path class="st0" d="M27.7,6.6v10.6h-2.1V6.6h-1.8v-2h1.8V0.3h2.1v4.3h1.7v2H27.7z M31.6,7.4c-0.2,0.9-0.5,1.8-0.8,2.7 | |||||
| c-0.3,0.9-0.7,1.6-1.1,2.2c-0.1-0.1-0.2-0.2-0.4-0.3s-0.3-0.2-0.4-0.3c-0.2-0.1-0.3-0.2-0.5-0.3c-0.2-0.1-0.3-0.2-0.4-0.2 | |||||
| c0.4-0.5,0.7-1.1,1-1.9s0.5-1.5,0.6-2.3L31.6,7.4z M34.6,5.8c0,0.9-0.1,1.9-0.3,2.9c-0.1,1-0.4,2-0.7,3s-0.8,2-1.4,2.9 | |||||
| c-0.6,0.9-1.4,1.8-2.4,2.6c-0.1-0.1-0.2-0.2-0.3-0.4c-0.1-0.1-0.3-0.3-0.4-0.4c-0.1-0.1-0.3-0.3-0.4-0.4s-0.3-0.2-0.4-0.3 | |||||
| c0.9-0.7,1.6-1.5,2.1-2.3c0.6-0.8,1-1.7,1.3-2.5c0.3-0.9,0.5-1.7,0.7-2.6s0.2-1.7,0.3-2.5h-2.7V3.7h2.7V0.5h2v3.2h3.7 | |||||
| c0,0.1,0,0.3,0,0.4c0,0.1,0,0.2,0,0.3s0,0.2,0,0.3l-0.1,2.7l1.3-0.3c0.1,0.4,0.3,0.9,0.4,1.3c0.1,0.5,0.3,0.9,0.4,1.4 | |||||
| c0.1,0.5,0.2,0.9,0.3,1.3c0.1,0.4,0.2,0.8,0.2,1.1L39,12.8c-0.1-0.5-0.2-1.1-0.3-1.8s-0.3-1.4-0.5-2.1c0,1.2-0.1,2.1-0.1,3 | |||||
| c0,0.8-0.1,1.5-0.2,2.1c-0.1,0.6-0.1,1-0.2,1.4c-0.1,0.3-0.2,0.6-0.3,0.8c-0.2,0.3-0.4,0.5-0.7,0.7c-0.2,0.1-0.5,0.2-0.8,0.3 | |||||
| C35.6,17,35.3,17,34.8,17s-0.9,0-1.3,0c0-0.3-0.1-0.6-0.2-1c-0.1-0.4-0.3-0.7-0.4-1c0.4,0,0.9,0.1,1.2,0.1c0.4,0,0.7,0,0.8,0 | |||||
| c0.2,0,0.3,0,0.4-0.1c0.1,0,0.2-0.1,0.3-0.2c0.1-0.1,0.2-0.4,0.3-0.8c0.1-0.4,0.1-0.9,0.2-1.6s0.1-1.6,0.1-2.7 | |||||
| c0-1.1,0.1-2.4,0.1-3.9H34.6z"/> | |||||
| <path class="st0" d="M47.8,1.1C47.6,1.7,47.3,2.4,47,3c-0.3,0.6-0.6,1.2-0.9,1.9v12.4h-2.2v-9c-0.2,0.2-0.4,0.5-0.6,0.7 | |||||
| S43,9.3,42.8,9.5c0-0.1-0.1-0.3-0.2-0.5c-0.1-0.2-0.2-0.4-0.3-0.6c-0.1-0.2-0.2-0.4-0.3-0.6s-0.2-0.4-0.3-0.5 | |||||
| c0.4-0.4,0.8-0.9,1.2-1.4c0.4-0.5,0.8-1.1,1.1-1.6c0.4-0.6,0.7-1.2,1-1.8c0.3-0.6,0.6-1.3,0.8-1.9L47.8,1.1z M53.5,13.2v4h-2.2V5.3 | |||||
| h-0.7c-0.4,0.7-0.7,1.3-1.1,1.9s-0.8,1.1-1.2,1.6c-0.1-0.1-0.2-0.2-0.3-0.4c-0.1-0.1-0.3-0.3-0.4-0.4S47.2,7.8,47,7.7 | |||||
| c-0.2-0.1-0.3-0.2-0.4-0.3C47,6.9,47.4,6.5,47.8,6c0.4-0.5,0.7-1.1,1-1.7s0.6-1.2,0.9-1.8c0.3-0.6,0.5-1.3,0.7-1.9l2.1,0.5 | |||||
| c-0.1,0.4-0.3,0.8-0.4,1.1s-0.3,0.7-0.5,1.1h7v2h-5.1v1.9h4.7v1.9h-4.7v2h4.9v2H53.5z"/> | |||||
| <path class="st0" d="M69.3,11.3v6h-2.2v-6h-7V9.1h7V3.6H61V1.5h14.4v2.1h-6v5.5h7.1v2.2H69.3z M64.1,4.2c0.1,0.3,0.3,0.6,0.4,0.9 | |||||
| s0.3,0.6,0.4,1c0.1,0.3,0.2,0.6,0.4,0.9c0.1,0.3,0.2,0.6,0.2,0.8l-2.1,0.6c0-0.2-0.1-0.5-0.2-0.8s-0.2-0.6-0.3-1 | |||||
| c-0.1-0.3-0.2-0.7-0.4-1c-0.1-0.3-0.3-0.7-0.4-1L64.1,4.2z M74.6,4.7c-0.3,0.7-0.7,1.4-1,2.1c-0.3,0.7-0.7,1.2-1,1.7l-1.9-0.5 | |||||
| c0.1-0.3,0.3-0.6,0.4-0.9s0.3-0.6,0.4-1c0.1-0.3,0.3-0.7,0.4-1c0.1-0.3,0.2-0.6,0.3-0.9L74.6,4.7z"/> | |||||
| <path class="st0" d="M89.4,2c0.4,0.4,0.9,0.8,1.3,1.3c0.5,0.5,0.9,0.9,1.3,1.4s0.8,0.9,1.2,1.4c0.4,0.5,0.7,0.9,0.9,1.3l-1.8,1.3 | |||||
| c-0.1-0.2-0.3-0.4-0.4-0.6c-0.2-0.2-0.3-0.5-0.5-0.7c-1.6,0.1-3,0.1-4.1,0.2c-1.2,0.1-2.1,0.1-3,0.2c-0.8,0-1.5,0.1-2,0.1 | |||||
| s-1,0.1-1.3,0.1s-0.6,0.1-0.8,0.1c-0.2,0-0.4,0.1-0.5,0.1c0-0.1-0.1-0.2-0.1-0.4c-0.1-0.2-0.1-0.4-0.2-0.6 | |||||
| c-0.1-0.2-0.1-0.4-0.2-0.6C79,6.3,78.9,6.2,78.9,6c0.3-0.1,0.6-0.2,0.9-0.5c0.3-0.3,0.7-0.6,1-1c0.4-0.4,0.7-0.8,1.1-1.2 | |||||
| c0.4-0.4,0.7-0.9,1-1.3c0.3-0.4,0.6-0.8,0.8-1.2c0.2-0.4,0.4-0.6,0.5-0.8L86.4,1c-0.6,0.8-1.2,1.7-1.9,2.4s-1.4,1.5-2,2.2l7.4-0.2 | |||||
| c-0.3-0.4-0.7-0.8-1.1-1.2c-0.4-0.4-0.7-0.7-1-1.1L89.4,2z M82.4,16.3v0.9h-2.2V9.3h12.2v7.9H90v-0.9H82.4z M82.4,14.2H90v-2.9 | |||||
| h-7.6V14.2z"/> | |||||
| </g> | |||||
| </svg> | |||||
| @@ -317,6 +317,12 @@ func HTTP(ctx *context.Context) { | |||||
| go repo.IncreaseCloneCnt() | go repo.IncreaseCloneCnt() | ||||
| } | } | ||||
| if ctx.Req.Method == "POST" { | |||||
| if strings.HasSuffix(ctx.Req.URL.Path, "git-upload-pack") { | |||||
| go repo.IncreaseGitCloneCnt() | |||||
| } | |||||
| } | |||||
| w := ctx.Resp | w := ctx.Resp | ||||
| r := ctx.Req.Request | r := ctx.Req.Request | ||||
| cfg := &serviceConfig{ | cfg := &serviceConfig{ | ||||
| @@ -1,13 +1,27 @@ | |||||
| package repo | package repo | ||||
| import ( | import ( | ||||
| "fmt" | |||||
| "net/http" | |||||
| "time" | "time" | ||||
| "code.gitea.io/gitea/models" | "code.gitea.io/gitea/models" | ||||
| "code.gitea.io/gitea/modules/context" | |||||
| "code.gitea.io/gitea/modules/git" | "code.gitea.io/gitea/modules/git" | ||||
| "code.gitea.io/gitea/modules/log" | "code.gitea.io/gitea/modules/log" | ||||
| ) | ) | ||||
| 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) | |||||
| log.Info("startTime=" + fmt.Sprint(startTime.Unix()) + " endDate=" + fmt.Sprint(endTime.Unix())) | |||||
| ctx.JSON(http.StatusOK, models.QueryUserStaticData(startTime.Unix(), endTime.Unix())) | |||||
| } | |||||
| func TimingCountDataByDate(date string) { | func TimingCountDataByDate(date string) { | ||||
| t, _ := time.Parse("2006-01-02", date) | t, _ := time.Parse("2006-01-02", date) | ||||
| @@ -12,6 +12,7 @@ import ( | |||||
| "fmt" | "fmt" | ||||
| gotemplate "html/template" | gotemplate "html/template" | ||||
| "io/ioutil" | "io/ioutil" | ||||
| "net/http" | |||||
| "net/url" | "net/url" | ||||
| "path" | "path" | ||||
| "strings" | "strings" | ||||
| @@ -31,11 +32,12 @@ import ( | |||||
| ) | ) | ||||
| const ( | const ( | ||||
| tplRepoEMPTY base.TplName = "repo/empty" | |||||
| tplRepoHome base.TplName = "repo/home" | |||||
| tplWatchers base.TplName = "repo/watchers" | |||||
| tplForks base.TplName = "repo/forks" | |||||
| tplMigrating base.TplName = "repo/migrating" | |||||
| tplRepoEMPTY base.TplName = "repo/empty" | |||||
| tplRepoHome base.TplName = "repo/home" | |||||
| tplWatchers base.TplName = "repo/watchers" | |||||
| tplForks base.TplName = "repo/forks" | |||||
| tplMigrating base.TplName = "repo/migrating" | |||||
| tplContributors base.TplName = "repo/contributors" | |||||
| ) | ) | ||||
| type namedBlob struct { | type namedBlob struct { | ||||
| @@ -243,6 +245,11 @@ func renderDirectory(ctx *context.Context, treeLink string) { | |||||
| ctx.Data["ReadmeInList"] = true | ctx.Data["ReadmeInList"] = true | ||||
| ctx.Data["ReadmeExist"] = true | ctx.Data["ReadmeExist"] = true | ||||
| ctx.Data["FileIsSymlink"] = readmeFile.isSymlink | ctx.Data["FileIsSymlink"] = readmeFile.isSymlink | ||||
| ctx.Data["ReadmeName"] = readmeFile.name | |||||
| if ctx.Repo.CanEnableEditor() { | |||||
| ctx.Data["CanEditFile"] = true | |||||
| } | |||||
| dataRc, err := readmeFile.blob.DataAsync() | dataRc, err := readmeFile.blob.DataAsync() | ||||
| if err != nil { | if err != nil { | ||||
| @@ -570,19 +577,29 @@ func safeURL(address string) string { | |||||
| } | } | ||||
| type ContributorInfo struct { | type ContributorInfo struct { | ||||
| UserInfo *models.User // nil for contributor who is not a registered user | |||||
| Email string | |||||
| CommitCnt int | |||||
| UserInfo *models.User // nil for contributor who is not a registered user | |||||
| RelAvatarLink string `json:"rel_avatar_link"` | |||||
| UserName string `json:"user_name"` | |||||
| Email string `json:"email"` | |||||
| CommitCnt int `json:"commit_cnt"` | |||||
| } | |||||
| type GetContributorsInfo struct { | |||||
| ErrorCode int `json:"error_code"` | |||||
| ErrorMsg string `json:"error_msg"` | |||||
| Count int `json:"count"` | |||||
| ContributorInfo []*ContributorInfo `json:"contributor_info"` | |||||
| } | } | ||||
| func getContributorInfo(contributorInfos []*ContributorInfo, email string) *ContributorInfo{ | |||||
| func getContributorInfo(contributorInfos []*ContributorInfo, email string) *ContributorInfo { | |||||
| for _, c := range contributorInfos { | for _, c := range contributorInfos { | ||||
| if strings.Compare(c.Email,email) == 0 { | |||||
| if strings.Compare(c.Email, email) == 0 { | |||||
| return c | return c | ||||
| } | } | ||||
| } | } | ||||
| return nil | return nil | ||||
| } | } | ||||
| // Home render repository home page | // Home render repository home page | ||||
| func Home(ctx *context.Context) { | func Home(ctx *context.Context) { | ||||
| if len(ctx.Repo.Units) > 0 { | if len(ctx.Repo.Units) > 0 { | ||||
| @@ -591,35 +608,41 @@ func Home(ctx *context.Context) { | |||||
| if err == nil && contributors != nil { | if err == nil && contributors != nil { | ||||
| startTime := time.Now() | startTime := time.Now() | ||||
| var contributorInfos []*ContributorInfo | var contributorInfos []*ContributorInfo | ||||
| contributorInfoHash:= make(map[string]*ContributorInfo) | |||||
| contributorInfoHash := make(map[string]*ContributorInfo) | |||||
| count := 0 | |||||
| for _, c := range contributors { | for _, c := range contributors { | ||||
| if strings.Compare(c.Email,"") == 0 { | |||||
| if count >= 25 { | |||||
| continue | |||||
| } | |||||
| if strings.Compare(c.Email, "") == 0 { | |||||
| continue | continue | ||||
| } | } | ||||
| // get user info from committer email | // get user info from committer email | ||||
| user, err := models.GetUserByActivateEmail(c.Email) | user, err := models.GetUserByActivateEmail(c.Email) | ||||
| if err == nil { | if err == nil { | ||||
| // committer is system user, get info through user's primary email | // committer is system user, get info through user's primary email | ||||
| if existedContributorInfo,ok:=contributorInfoHash[user.Email];ok { | |||||
| if existedContributorInfo, ok := contributorInfoHash[user.Email]; ok { | |||||
| // existed: same primary email, different committer name | // existed: same primary email, different committer name | ||||
| existedContributorInfo.CommitCnt += c.CommitCnt | existedContributorInfo.CommitCnt += c.CommitCnt | ||||
| }else{ | |||||
| } else { | |||||
| // new committer info | // new committer info | ||||
| var newContributor = &ContributorInfo{ | var newContributor = &ContributorInfo{ | ||||
| user, user.Email,c.CommitCnt, | |||||
| user, user.RelAvatarLink(), user.Name, user.Email, c.CommitCnt, | |||||
| } | } | ||||
| contributorInfos = append(contributorInfos, newContributor ) | |||||
| count++ | |||||
| contributorInfos = append(contributorInfos, newContributor) | |||||
| contributorInfoHash[user.Email] = newContributor | contributorInfoHash[user.Email] = newContributor | ||||
| } | } | ||||
| } else { | } else { | ||||
| // committer is not system user | // committer is not system user | ||||
| if existedContributorInfo,ok:=contributorInfoHash[c.Email];ok { | |||||
| if existedContributorInfo, ok := contributorInfoHash[c.Email]; ok { | |||||
| // existed: same primary email, different committer name | // existed: same primary email, different committer name | ||||
| existedContributorInfo.CommitCnt += c.CommitCnt | existedContributorInfo.CommitCnt += c.CommitCnt | ||||
| }else{ | |||||
| } else { | |||||
| var newContributor = &ContributorInfo{ | var newContributor = &ContributorInfo{ | ||||
| user, c.Email,c.CommitCnt, | |||||
| user, "", "",c.Email, c.CommitCnt, | |||||
| } | } | ||||
| count++ | |||||
| contributorInfos = append(contributorInfos, newContributor) | contributorInfos = append(contributorInfos, newContributor) | ||||
| contributorInfoHash[c.Email] = newContributor | contributorInfoHash[c.Email] = newContributor | ||||
| } | } | ||||
| @@ -627,7 +650,7 @@ func Home(ctx *context.Context) { | |||||
| } | } | ||||
| ctx.Data["ContributorInfo"] = contributorInfos | ctx.Data["ContributorInfo"] = contributorInfos | ||||
| var duration = time.Since(startTime) | var duration = time.Since(startTime) | ||||
| log.Info("getContributorInfo cost: %v seconds",duration.Seconds()) | |||||
| log.Info("getContributorInfo cost: %v seconds", duration.Seconds()) | |||||
| } | } | ||||
| if ctx.Repo.Repository.IsBeingCreated() { | if ctx.Repo.Repository.IsBeingCreated() { | ||||
| task, err := models.GetMigratingTask(ctx.Repo.Repository.ID) | task, err := models.GetMigratingTask(ctx.Repo.Repository.ID) | ||||
| @@ -694,13 +717,13 @@ func renderLicense(ctx *context.Context) { | |||||
| log.Error("failed to get license content: %v, err:%v", f, err) | log.Error("failed to get license content: %v, err:%v", f, err) | ||||
| continue | continue | ||||
| } | } | ||||
| if bytes.Compare(buf,license) == 0 { | |||||
| log.Info("got matched license:%v",f) | |||||
| if bytes.Compare(buf, license) == 0 { | |||||
| log.Info("got matched license:%v", f) | |||||
| ctx.Data["LICENSE"] = f | ctx.Data["LICENSE"] = f | ||||
| return | return | ||||
| } | } | ||||
| } | } | ||||
| log.Info("not found matched license,repo:%v",ctx.Repo.Repository.Name) | |||||
| log.Info("not found matched license,repo:%v", ctx.Repo.Repository.Name) | |||||
| } | } | ||||
| func renderLanguageStats(ctx *context.Context) { | func renderLanguageStats(ctx *context.Context) { | ||||
| @@ -801,31 +824,31 @@ func renderCode(ctx *context.Context) { | |||||
| baseGitRepo, err := git.OpenRepository(ctx.Repo.Repository.BaseRepo.RepoPath()) | baseGitRepo, err := git.OpenRepository(ctx.Repo.Repository.BaseRepo.RepoPath()) | ||||
| defer baseGitRepo.Close() | defer baseGitRepo.Close() | ||||
| if err != nil { | if err != nil { | ||||
| log.Error("error open baseRepo:%s",ctx.Repo.Repository.BaseRepo.RepoPath()) | |||||
| log.Error("error open baseRepo:%s", ctx.Repo.Repository.BaseRepo.RepoPath()) | |||||
| ctx.Data["FetchUpstreamCnt"] = -1 // minus value indicates error | ctx.Data["FetchUpstreamCnt"] = -1 // minus value indicates error | ||||
| }else{ | |||||
| if _,error:= baseGitRepo.GetBranch(ctx.Repo.BranchName);error==nil{ | |||||
| } else { | |||||
| if _, error := baseGitRepo.GetBranch(ctx.Repo.BranchName); error == nil { | |||||
| //base repo has the same branch, then compare between current repo branch and base repo's branch | //base repo has the same branch, then compare between current repo branch and base repo's branch | ||||
| compareUrl := ctx.Repo.BranchName + "..." + ctx.Repo.Repository.BaseRepo.OwnerName + "/" + ctx.Repo.Repository.BaseRepo.Name + ":" + ctx.Repo.BranchName | |||||
| ctx.SetParams("*",compareUrl) | |||||
| compareUrl := ctx.Repo.BranchName + "..." + ctx.Repo.Repository.BaseRepo.OwnerName + "/" + ctx.Repo.Repository.BaseRepo.Name + ":" + ctx.Repo.BranchName | |||||
| ctx.SetParams("*", compareUrl) | |||||
| ctx.Data["UpstreamSameBranchName"] = true | ctx.Data["UpstreamSameBranchName"] = true | ||||
| }else{ | |||||
| } else { | |||||
| //else, compare between current repo branch and base repo's default branch | //else, compare between current repo branch and base repo's default branch | ||||
| compareUrl := ctx.Repo.BranchName + "..." + ctx.Repo.Repository.BaseRepo.OwnerName + "/" + ctx.Repo.Repository.BaseRepo.Name + ":" + ctx.Repo.Repository.BaseRepo.DefaultBranch | |||||
| ctx.SetParams("*",compareUrl) | |||||
| compareUrl := ctx.Repo.BranchName + "..." + ctx.Repo.Repository.BaseRepo.OwnerName + "/" + ctx.Repo.Repository.BaseRepo.Name + ":" + ctx.Repo.Repository.BaseRepo.DefaultBranch | |||||
| ctx.SetParams("*", compareUrl) | |||||
| ctx.Data["UpstreamSameBranchName"] = false | ctx.Data["UpstreamSameBranchName"] = false | ||||
| } | } | ||||
| _, _, headGitRepo, compareInfo, _, _ := ParseCompareInfo(ctx) | _, _, headGitRepo, compareInfo, _, _ := ParseCompareInfo(ctx) | ||||
| defer headGitRepo.Close() | defer headGitRepo.Close() | ||||
| if compareInfo!= nil { | |||||
| if compareInfo.Commits!=nil { | |||||
| log.Info("compareInfoCommits数量:%d",compareInfo.Commits.Len()) | |||||
| if compareInfo != nil { | |||||
| if compareInfo.Commits != nil { | |||||
| log.Info("compareInfoCommits数量:%d", compareInfo.Commits.Len()) | |||||
| ctx.Data["FetchUpstreamCnt"] = compareInfo.Commits.Len() | ctx.Data["FetchUpstreamCnt"] = compareInfo.Commits.Len() | ||||
| }else{ | |||||
| } else { | |||||
| log.Info("compareInfo nothing different") | log.Info("compareInfo nothing different") | ||||
| ctx.Data["FetchUpstreamCnt"] = 0 | ctx.Data["FetchUpstreamCnt"] = 0 | ||||
| } | } | ||||
| }else{ | |||||
| } else { | |||||
| ctx.Data["FetchUpstreamCnt"] = -1 // minus value indicates error | ctx.Data["FetchUpstreamCnt"] = -1 // minus value indicates error | ||||
| } | } | ||||
| } | } | ||||
| @@ -893,3 +916,64 @@ func Forks(ctx *context.Context) { | |||||
| ctx.HTML(200, tplForks) | ctx.HTML(200, tplForks) | ||||
| } | } | ||||
| func Contributors(ctx *context.Context) { | |||||
| ctx.HTML(http.StatusOK, tplContributors) | |||||
| } | |||||
| func ContributorsAPI(ctx *context.Context) { | |||||
| count := 0 | |||||
| errorCode := 0 | |||||
| errorMsg := "" | |||||
| contributors, err := git.GetContributors(ctx.Repo.Repository.RepoPath()) | |||||
| var contributorInfos []*ContributorInfo | |||||
| if err == nil && contributors != nil { | |||||
| contributorInfoHash := make(map[string]*ContributorInfo) | |||||
| for _, c := range contributors { | |||||
| if strings.Compare(c.Email, "") == 0 { | |||||
| continue | |||||
| } | |||||
| // get user info from committer email | |||||
| user, err := models.GetUserByActivateEmail(c.Email) | |||||
| if err == nil { | |||||
| // committer is system user, get info through user's primary email | |||||
| if existedContributorInfo, ok := contributorInfoHash[user.Email]; ok { | |||||
| // existed: same primary email, different committer name | |||||
| existedContributorInfo.CommitCnt += c.CommitCnt | |||||
| } else { | |||||
| // new committer info | |||||
| var newContributor = &ContributorInfo{ | |||||
| user, user.RelAvatarLink(),user.Name, user.Email,c.CommitCnt, | |||||
| } | |||||
| count++ | |||||
| contributorInfos = append(contributorInfos, newContributor) | |||||
| contributorInfoHash[user.Email] = newContributor | |||||
| } | |||||
| } else { | |||||
| // committer is not system user | |||||
| if existedContributorInfo, ok := contributorInfoHash[c.Email]; ok { | |||||
| // existed: same primary email, different committer name | |||||
| existedContributorInfo.CommitCnt += c.CommitCnt | |||||
| } else { | |||||
| var newContributor = &ContributorInfo{ | |||||
| user, "", "",c.Email,c.CommitCnt, | |||||
| } | |||||
| count++ | |||||
| contributorInfos = append(contributorInfos, newContributor) | |||||
| contributorInfoHash[c.Email] = newContributor | |||||
| } | |||||
| } | |||||
| } | |||||
| } else { | |||||
| log.Error("GetContributors failed: %v", err) | |||||
| errorCode = -1 | |||||
| errorMsg = err.Error() | |||||
| } | |||||
| ctx.JSON(http.StatusOK, GetContributorsInfo{ | |||||
| ErrorCode: errorCode, | |||||
| ErrorMsg: errorMsg, | |||||
| Count: count, | |||||
| ContributorInfo: contributorInfos, | |||||
| }) | |||||
| } | |||||
| @@ -311,7 +311,7 @@ func RegisterRoutes(m *macaron.Macaron) { | |||||
| m.Head("/", func() string { | m.Head("/", func() string { | ||||
| return "" | return "" | ||||
| }) | }) | ||||
| m.Get("/", routers.Dashboard) | |||||
| m.Get("/", routers.Home) | |||||
| m.Get("/dashboard", routers.Dashboard) | m.Get("/dashboard", routers.Dashboard) | ||||
| m.Group("/explore", func() { | m.Group("/explore", func() { | ||||
| m.Get("", func(ctx *context.Context) { | m.Get("", func(ctx *context.Context) { | ||||
| @@ -615,6 +615,11 @@ func RegisterRoutes(m *macaron.Macaron) { | |||||
| //reqRepoBlockChainWriter := context.RequireRepoWriter(models.UnitTypeBlockChain) | //reqRepoBlockChainWriter := context.RequireRepoWriter(models.UnitTypeBlockChain) | ||||
| // ***** START: Organization ***** | // ***** START: Organization ***** | ||||
| m.Group("/org", func() { | |||||
| m.Group("/:org", func() { | |||||
| m.Get("/members", org.Members) | |||||
| }, context.OrgAssignment()) | |||||
| }) | |||||
| m.Group("/org", func() { | m.Group("/org", func() { | ||||
| m.Group("", func() { | m.Group("", func() { | ||||
| m.Get("/create", org.Create) | m.Get("/create", org.Create) | ||||
| @@ -625,7 +630,7 @@ func RegisterRoutes(m *macaron.Macaron) { | |||||
| m.Get("/dashboard", user.Dashboard) | m.Get("/dashboard", user.Dashboard) | ||||
| m.Get("/^:type(issues|pulls)$", user.Issues) | m.Get("/^:type(issues|pulls)$", user.Issues) | ||||
| m.Get("/milestones", reqMilestonesDashboardPageEnabled, user.Milestones) | m.Get("/milestones", reqMilestonesDashboardPageEnabled, user.Milestones) | ||||
| m.Get("/members", org.Members) | |||||
| //m.Get("/members", org.Members) | |||||
| m.Post("/members/action/:action", org.MembersAction) | m.Post("/members/action/:action", org.MembersAction) | ||||
| m.Get("/teams", org.Teams) | m.Get("/teams", org.Teams) | ||||
| @@ -786,9 +791,11 @@ func RegisterRoutes(m *macaron.Macaron) { | |||||
| }, reqSignIn, context.RepoAssignment(), context.UnitTypes(), reqRepoAdmin, context.RepoRef()) | }, reqSignIn, context.RepoAssignment(), context.UnitTypes(), reqRepoAdmin, context.RepoRef()) | ||||
| m.Post("/:username/:reponame/action/:action", reqSignIn, context.RepoAssignment(), context.UnitTypes(), repo.Action) | m.Post("/:username/:reponame/action/:action", reqSignIn, context.RepoAssignment(), context.UnitTypes(), repo.Action) | ||||
| m.Get("/tool/query_user_static", repo.QueryUserStaticData) | |||||
| // Grouping for those endpoints not requiring authentication | // Grouping for those endpoints not requiring authentication | ||||
| m.Group("/:username/:reponame", func() { | m.Group("/:username/:reponame", func() { | ||||
| m.Get("/contributors", repo.Contributors) | |||||
| m.Get("/contributors/list", repo.ContributorsAPI) | |||||
| m.Group("/milestone", func() { | m.Group("/milestone", func() { | ||||
| m.Get("/:id", repo.MilestoneIssuesAndPulls) | m.Get("/:id", repo.MilestoneIssuesAndPulls) | ||||
| }, reqRepoIssuesOrPullsReader, context.RepoRef()) | }, reqRepoIssuesOrPullsReader, context.RepoRef()) | ||||
| @@ -544,7 +544,7 @@ func handleSignInFull(ctx *context.Context, u *models.User, remember bool, obeyR | |||||
| if err := models.UpdateUserCols(u, "language"); err != nil { | if err := models.UpdateUserCols(u, "language"); err != nil { | ||||
| log.Error(fmt.Sprintf("Error updating user language [user: %d, locale: %s]", u.ID, u.Language)) | log.Error(fmt.Sprintf("Error updating user language [user: %d, locale: %s]", u.ID, u.Language)) | ||||
| return setting.AppSubURL + "/" | |||||
| return setting.AppSubURL + "/dashboard" | |||||
| } | } | ||||
| } else { | } else { | ||||
| // Language setting of the user use the one previously set | // Language setting of the user use the one previously set | ||||
| @@ -562,7 +562,7 @@ func handleSignInFull(ctx *context.Context, u *models.User, remember bool, obeyR | |||||
| u.SetLastLogin() | u.SetLastLogin() | ||||
| if err := models.UpdateUserCols(u, "last_login_unix"); err != nil { | if err := models.UpdateUserCols(u, "last_login_unix"); err != nil { | ||||
| ctx.ServerError("UpdateUserCols", err) | ctx.ServerError("UpdateUserCols", err) | ||||
| return setting.AppSubURL + "/" | |||||
| return setting.AppSubURL + "/dashboard" | |||||
| } | } | ||||
| if redirectTo := ctx.GetCookie("redirect_to"); len(redirectTo) > 0 && !util.IsExternalURL(redirectTo) { | if redirectTo := ctx.GetCookie("redirect_to"); len(redirectTo) > 0 && !util.IsExternalURL(redirectTo) { | ||||
| @@ -574,9 +574,9 @@ func handleSignInFull(ctx *context.Context, u *models.User, remember bool, obeyR | |||||
| } | } | ||||
| if obeyRedirect { | if obeyRedirect { | ||||
| ctx.Redirect(setting.AppSubURL + "/") | |||||
| ctx.Redirect(setting.AppSubURL + "/dashboard") | |||||
| } | } | ||||
| return setting.AppSubURL + "/" | |||||
| return setting.AppSubURL + "/dashboard" | |||||
| } | } | ||||
| // SignInOAuth handles the OAuth2 login buttons | // SignInOAuth handles the OAuth2 login buttons | ||||
| @@ -180,8 +180,8 @@ | |||||
| var _hmt = _hmt || []; | var _hmt = _hmt || []; | ||||
| (function() { | (function() { | ||||
| var hm = document.createElement("script"); | var hm = document.createElement("script"); | ||||
| hm.src = "https://hm.baidu.com/hm.js?7c4ef0a24be6109ab22e63c832ab21cf"; | |||||
| var s = document.getElementsByTagName("script")[0]; | |||||
| hm.src = "https://hm.baidu.com/hm.js?46149a0b61fdeddfe427ff4de63794ba"; | |||||
| var s = document.getElementsByTagName("script")[0]; | |||||
| s.parentNode.insertBefore(hm, s); | s.parentNode.insertBefore(hm, s); | ||||
| })(); | })(); | ||||
| </script> | </script> | ||||
| @@ -181,8 +181,8 @@ | |||||
| var _hmt = _hmt || []; | var _hmt = _hmt || []; | ||||
| (function() { | (function() { | ||||
| var hm = document.createElement("script"); | var hm = document.createElement("script"); | ||||
| hm.src = "https://hm.baidu.com/hm.js?7c4ef0a24be6109ab22e63c832ab21cf"; | |||||
| var s = document.getElementsByTagName("script")[0]; | |||||
| hm.src = "https://hm.baidu.com/hm.js?46149a0b61fdeddfe427ff4de63794ba"; | |||||
| var s = document.getElementsByTagName("script")[0]; | |||||
| s.parentNode.insertBefore(hm, s); | s.parentNode.insertBefore(hm, s); | ||||
| })(); | })(); | ||||
| </script> | </script> | ||||
| @@ -7,6 +7,14 @@ | |||||
| <i class="sidebar icon"></i> | <i class="sidebar icon"></i> | ||||
| </div> | </div> | ||||
| </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}} | {{if .IsSigned}} | ||||
| <a class="item {{if .PageIsDashboard}}active{{end}}" href="/dashboard">{{.i18n.Tr "index"}}</a> | <a class="item {{if .PageIsDashboard}}active{{end}}" href="/dashboard">{{.i18n.Tr "index"}}</a> | ||||
| @@ -38,11 +38,12 @@ | |||||
| <div class="ui sixteen wide mobile six wide tablet five wide computer column"> | <div class="ui sixteen wide mobile six wide tablet five wide computer column"> | ||||
| <h4 class="ui top attached header"> | <h4 class="ui top attached header"> | ||||
| <strong>{{.i18n.Tr "org.people"}}</strong> | <strong>{{.i18n.Tr "org.people"}}</strong> | ||||
| {{if .IsOrganizationMember}} | |||||
| <div class="ui right"> | |||||
| <a class="text grey" href="{{.OrgLink}}/members">{{.Org.NumMembers}} {{svg "octicon-chevron-right" 16}}</a> | |||||
| </div> | |||||
| {{end}} | |||||
| <div class="ui right"> | |||||
| <a class="text grey" href="{{.OrgLink}}/members">{{.MembersTotal}} {{svg "octicon-chevron-right" 16}}</a> | |||||
| </div> | |||||
| <!-- {{if .IsOrganizationMember}} --> | |||||
| <!-- {{end}} --> | |||||
| </h4> | </h4> | ||||
| <div class="ui attached segment members"> | <div class="ui attached segment members"> | ||||
| {{$isMember := .IsOrganizationMember}} | {{$isMember := .IsOrganizationMember}} | ||||
| @@ -3,10 +3,10 @@ | |||||
| <a class="{{if $.PageIsOrgHome}}active{{end}} item" href="{{.HomeLink}}"> | <a class="{{if $.PageIsOrgHome}}active{{end}} item" href="{{.HomeLink}}"> | ||||
| {{svg "octicon-home" 16}} {{$.i18n.Tr "org.home"}} | {{svg "octicon-home" 16}} {{$.i18n.Tr "org.home"}} | ||||
| </a> | </a> | ||||
| <a class="{{if $.PageIsOrgMembers}}active{{end}} item" href="{{$.OrgLink}}/members"> | |||||
| {{svg "octicon-organization" 16}} {{$.i18n.Tr "org.people"}} | |||||
| </a> | |||||
| {{if or ($.IsOrganizationMember) ($.IsOrganizationOwner)}} | {{if or ($.IsOrganizationMember) ($.IsOrganizationOwner)}} | ||||
| <a class="{{if $.PageIsOrgMembers}}active{{end}} item" href="{{$.OrgLink}}/members"> | |||||
| {{svg "octicon-organization" 16}} {{$.i18n.Tr "org.people"}} | |||||
| </a> | |||||
| <a class="{{if $.PageIsOrgTeams}}active{{end}} item" href="{{$.OrgLink}}/teams"> | <a class="{{if $.PageIsOrgTeams}}active{{end}} item" href="{{$.OrgLink}}/teams"> | ||||
| {{svg "octicon-jersey" 16}} {{$.i18n.Tr "org.teams"}} | {{svg "octicon-jersey" 16}} {{$.i18n.Tr "org.teams"}} | ||||
| </a> | </a> | ||||
| @@ -23,10 +23,10 @@ | |||||
| {{svg "octicon-home" 16}} {{$.i18n.Tr "org.home"}} | {{svg "octicon-home" 16}} {{$.i18n.Tr "org.home"}} | ||||
| </a> | </a> | ||||
| {{end}} | {{end}} | ||||
| <a class="{{if $.PageIsOrgMembers}}active{{end}} item" href="{{$.OrgLink}}/members"> | |||||
| {{svg "octicon-organization" 16}} {{$.i18n.Tr "org.people"}} | |||||
| </a> | |||||
| {{if or ($.IsOrganizationMember) ($.IsOrganizationOwner)}} | {{if or ($.IsOrganizationMember) ($.IsOrganizationOwner)}} | ||||
| <a class="{{if $.PageIsOrgMembers}}active{{end}} item" href="{{$.OrgLink}}/members"> | |||||
| {{svg "octicon-organization" 16}} {{$.i18n.Tr "org.people"}} | |||||
| </a> | |||||
| <a class="{{if $.PageIsOrgTeams}}active{{end}} item" href="{{$.OrgLink}}/teams"> | <a class="{{if $.PageIsOrgTeams}}active{{end}} item" href="{{$.OrgLink}}/teams"> | ||||
| {{svg "octicon-jersey" 16}} {{$.i18n.Tr "org.teams"}} | {{svg "octicon-jersey" 16}} {{$.i18n.Tr "org.teams"}} | ||||
| </a> | </a> | ||||
| @@ -2,8 +2,18 @@ | |||||
| <div class="repository commits"> | <div class="repository commits"> | ||||
| {{template "repo/header" .}} | {{template "repo/header" .}} | ||||
| <div class="ui container"> | <div class="ui container"> | ||||
| <h2 class="ui header">{{.DateFrom}} - {{.DateUntil}} | |||||
| <div class="ui right"> | |||||
| <div class="ui three column stackable grid" style="align-items: center;"> | |||||
| <div class="column"> | |||||
| <div class="ui breadcrumb"> | |||||
| <a class="section" href="{{.RepoLink}}{{if (ne .BranchName .Repository.DefaultBranch)}}/src/{{.BranchNameSubURL | EscapePound}}{{end}}">{{.i18n.Tr "repo.code"}}</a> | |||||
| <div class="divider"> / </div> | |||||
| <div class="active section" href="{{.RepoLink}}/activity">{{.i18n.Tr "repo.activity"}}</div> | |||||
| </div> | |||||
| </div> | |||||
| <div class="column center aligned" style="font-weight: 800;"> | |||||
| {{.DateFrom}} - {{.DateUntil}} | |||||
| </div> | |||||
| <div class="column right aligned"> | |||||
| <!-- Period --> | <!-- Period --> | ||||
| <div class="ui floating dropdown jump filter"> | <div class="ui floating dropdown jump filter"> | ||||
| <div class="ui basic compact button"> | <div class="ui basic compact button"> | ||||
| @@ -23,7 +33,7 @@ | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| </h2> | |||||
| </div> | |||||
| <div class="ui divider"></div> | <div class="ui divider"></div> | ||||
| {{if (or (.Permission.CanRead $.UnitTypeIssues) (.Permission.CanRead $.UnitTypePullRequests))}} | {{if (or (.Permission.CanRead $.UnitTypeIssues) (.Permission.CanRead $.UnitTypePullRequests))}} | ||||
| @@ -0,0 +1,9 @@ | |||||
| {{template "base/head" .}} | |||||
| <div class="repository watchers"> | |||||
| {{template "repo/header" .}} | |||||
| <div class="ui container" id="Contributors"> | |||||
| </div> | |||||
| </div> | |||||
| {{template "base/footer" .}} | |||||
| @@ -92,16 +92,27 @@ | |||||
| {{if not .Repository.IsBeingCreated}} | {{if not .Repository.IsBeingCreated}} | ||||
| <div class="ui tabular stackable menu navbar"> | <div class="ui tabular stackable menu navbar"> | ||||
| {{if .Permission.CanRead $.UnitTypeCode}} | {{if .Permission.CanRead $.UnitTypeCode}} | ||||
| <a class="{{if .PageIsViewCode}}active{{end}} item" href="{{.RepoLink}}{{if (ne .BranchName .Repository.DefaultBranch)}}/src/{{.BranchNameSubURL | EscapePound}}{{end}}"> | |||||
| {{svg "octicon-code" 16}} {{.i18n.Tr "repo.code"}} | |||||
| <div class="dropdown-menu"> | |||||
| <a class="{{if or .PageIsViewCode .PageIsReleaseList .PageIsWiki .PageIsActivity}}active{{end}} item" href="{{.RepoLink}}{{if (ne .BranchName .Repository.DefaultBranch)}}/src/{{.BranchNameSubURL | EscapePound}}{{end}}"> | |||||
| <span>{{svg "octicon-code" 16}} {{.i18n.Tr "repo.code"}} <i class="dropdown icon"></i></span> | |||||
| </a> | </a> | ||||
| {{end}} | |||||
| <div class="dropdown-content"> | |||||
| <a style="border: none;" class="{{if .PageIsReleaseList}}active{{end}} item" href="{{.RepoLink}}/releases"> | |||||
| {{svg "octicon-tag" 16}} {{.i18n.Tr "repo.releases"}} <span class="ui {{if not .NumReleases}}gray{{else}}blue{{end}} small label">{{.NumReleases}}</span> | |||||
| </a> | |||||
| <a style="border: none;" class="{{if .PageIsWiki}}active{{end}} item" href="{{.RepoLink}}/wiki" {{if (.Permission.CanRead $.UnitTypeExternalWiki)}} target="_blank" rel="noopener noreferrer" {{end}}> | |||||
| {{svg "octicon-book" 16}} {{.i18n.Tr "repo.wiki"}} | |||||
| </a> | |||||
| <a style="border: none;" class="{{if .PageIsActivity}}active{{end}} item" href="{{.RepoLink}}/activity"> | |||||
| {{svg "octicon-pulse" 16}} {{.i18n.Tr "repo.activity"}} | |||||
| </a> | |||||
| {{if .Permission.CanRead $.UnitTypeDatasets}} | |||||
| <a class="{{if .PageIsDataset}}active{{end}} item" href="{{.RepoLink}}/datasets?type=0"> | |||||
| {{svg "octicon-inbox" 16}} {{.i18n.Tr "datasets"}} | |||||
| </a> | |||||
| </div> | |||||
| </div> | |||||
| {{end}} | {{end}} | ||||
| {{if .Permission.CanRead $.UnitTypeIssues}} | {{if .Permission.CanRead $.UnitTypeIssues}} | ||||
| <a class="{{if .PageIsIssueList}}active{{end}} item" href="{{.RepoLink}}/issues"> | <a class="{{if .PageIsIssueList}}active{{end}} item" href="{{.RepoLink}}/issues"> | ||||
| @@ -109,11 +120,11 @@ | |||||
| </a> | </a> | ||||
| {{end}} | {{end}} | ||||
| {{if .Permission.CanRead $.UnitTypeExternalTracker}} | |||||
| <!-- {{if .Permission.CanRead $.UnitTypeExternalTracker}} | |||||
| <a class="{{if .PageIsIssueList}}active{{end}} item" href="{{.RepoExternalIssuesLink}}" target="_blank" rel="noopener noreferrer"> | <a class="{{if .PageIsIssueList}}active{{end}} item" href="{{.RepoExternalIssuesLink}}" target="_blank" rel="noopener noreferrer"> | ||||
| {{svg "octicon-link-external" 16}} {{.i18n.Tr "repo.issues"}} </span> | {{svg "octicon-link-external" 16}} {{.i18n.Tr "repo.issues"}} </span> | ||||
| </a> | </a> | ||||
| {{end}} | |||||
| {{end}} --> | |||||
| {{if and .Repository.CanEnablePulls (.Permission.CanRead $.UnitTypePullRequests)}} | {{if and .Repository.CanEnablePulls (.Permission.CanRead $.UnitTypePullRequests)}} | ||||
| <a class="{{if .PageIsPullList}}active{{end}} item" href="{{.RepoLink}}/pulls"> | <a class="{{if .PageIsPullList}}active{{end}} item" href="{{.RepoLink}}/pulls"> | ||||
| @@ -121,35 +132,22 @@ | |||||
| </a> | </a> | ||||
| {{end}} | {{end}} | ||||
| {{if and (.Permission.CanRead $.UnitTypeReleases) (not .IsEmptyRepo) }} | |||||
| <a class="{{if .PageIsReleaseList}}active{{end}} item" href="{{.RepoLink}}/releases"> | |||||
| {{svg "octicon-tag" 16}} {{.i18n.Tr "repo.releases"}} <span class="ui {{if not .NumReleases}}gray{{else}}blue{{end}} small label">{{.NumReleases}}</span> | |||||
| {{if .Permission.CanRead $.UnitTypeDatasets}} | |||||
| <a class="{{if .PageIsDataset}}active{{end}} item" href="{{.RepoLink}}/datasets?type=0"> | |||||
| {{svg "octicon-inbox" 16}} {{.i18n.Tr "datasets"}} | |||||
| </a> | </a> | ||||
| {{end}} | {{end}} | ||||
| {{if or (.Permission.CanRead $.UnitTypeWiki) (.Permission.CanRead $.UnitTypeExternalWiki)}} | |||||
| <a class="{{if .PageIsWiki}}active{{end}} item" href="{{.RepoLink}}/wiki" {{if (.Permission.CanRead $.UnitTypeExternalWiki)}} target="_blank" rel="noopener noreferrer" {{end}}> | |||||
| {{svg "octicon-book" 16}} {{.i18n.Tr "repo.wiki"}} | |||||
| </a> | |||||
| {{end}} | |||||
| {{if and (.Permission.CanReadAny $.UnitTypePullRequests $.UnitTypeIssues $.UnitTypeReleases) (not .IsEmptyRepo)}} | |||||
| <a class="{{if .PageIsActivity}}active{{end}} item" href="{{.RepoLink}}/activity"> | |||||
| {{svg "octicon-pulse" 16}} {{.i18n.Tr "repo.activity"}} | |||||
| </a> | |||||
| {{end}} | |||||
| {{if .Permission.CanRead $.UnitTypeCloudBrain}} | {{if .Permission.CanRead $.UnitTypeCloudBrain}} | ||||
| <a class="{{if .PageIsCloudBrain}}active{{end}} item" href="{{.RepoLink}}/cloudbrain"> | <a class="{{if .PageIsCloudBrain}}active{{end}} item" href="{{.RepoLink}}/cloudbrain"> | ||||
| {{svg "octicon-server" 16}} {{.i18n.Tr "repo.cloudbrain"}} | |||||
| <span>{{svg "octicon-server" 16}} {{.i18n.Tr "repo.cloudbrain"}}<i class="question circle icon link cloudbrain-question" data-content={{.i18n.Tr "repo.cloudbrain_helper"}} data-position="top center" data-variation="mini"></i></span> | |||||
| </a> | </a> | ||||
| {{end}} | {{end}} | ||||
| {{if .IsSigned}} | |||||
| <!-- {{if .IsSigned}} | |||||
| <a class="{{if .PageIsBlockChain}}active{{end}} item " href="{{.RepoLink}}/blockchain"> | <a class="{{if .PageIsBlockChain}}active{{end}} item " href="{{.RepoLink}}/blockchain"> | ||||
| {{svg "octicon-law" 16}} | {{svg "octicon-law" 16}} | ||||
| {{.i18n.Tr "repo.balance"}} | {{.i18n.Tr "repo.balance"}} | ||||
| </a> | </a> | ||||
| {{end}} | |||||
| {{end}} --> | |||||
| {{template "custom/extra_tabs" .}} | {{template "custom/extra_tabs" .}} | ||||
| @@ -243,4 +241,9 @@ | |||||
| window.location.href = repolink + "/datasets?type=" + checked_radio | window.location.href = repolink + "/datasets?type=" + checked_radio | ||||
| }) | }) | ||||
| }) | }) | ||||
| $('.question.circle.icon').hover(function(){ | |||||
| $(this).popup('show') | |||||
| $('.ui.popup.mini.top.center').css({"border-color":'rgba(50, 145, 248, 100)',"color":"rgba(3, 102, 214, 100)","border-radius":"5px"}) | |||||
| }); | |||||
| </script> | </script> | ||||
| @@ -4,7 +4,7 @@ | |||||
| font-size: 1.0em; | font-size: 1.0em; | ||||
| margin-bottom: 1.0rem; | margin-bottom: 1.0rem; | ||||
| } | } | ||||
| #contributorInfo > a:nth-child(n+25){ | |||||
| #contributorInfo > a:nth-child(n+26){ | |||||
| display:none; | display:none; | ||||
| } | } | ||||
| #contributorInfo > a{ | #contributorInfo > a{ | ||||
| @@ -329,9 +329,15 @@ | |||||
| <div> | <div> | ||||
| <h4 class="ui header"> | <h4 class="ui header"> | ||||
| {{$lenCon := len .ContributorInfo}} | |||||
| {{if lt $lenCon 25 }} | |||||
| <strong>贡献者 ({{len .ContributorInfo}})</strong> | <strong>贡献者 ({{len .ContributorInfo}})</strong> | ||||
| {{else}} | |||||
| <strong>贡献者 ({{len .ContributorInfo}}+)</strong> | |||||
| {{end}} | |||||
| <div class="ui right"> | <div class="ui right"> | ||||
| <a class="membersmore text grey" href="javascript:;">全部 {{svg "octicon-chevron-right" 16}}</a> | |||||
| <a class="membersmore text grey" href="{{.RepoLink}}/contributors">全部 {{svg "octicon-chevron-right" 16}}</a> | |||||
| </div> | </div> | ||||
| </h4> | </h4> | ||||
| <div class="ui members" id="contributorInfo"> | <div class="ui members" id="contributorInfo"> | ||||
| @@ -353,10 +359,10 @@ | |||||
| </div> | </div> | ||||
| <script type="text/javascript"> | <script type="text/javascript"> | ||||
| $(document).ready(function(){ | |||||
| $(".membersmore").click(function(){ | |||||
| $("#contributorInfo > a:nth-child(n+25)").show(); | |||||
| }); | |||||
| }); | |||||
| // $(document).ready(function(){ | |||||
| // $(".membersmore").click(function(){ | |||||
| // $("#contributorInfo > a:nth-child(n+25)").show(); | |||||
| // }); | |||||
| // }); | |||||
| </script> | </script> | ||||
| {{template "base/footer" .}} | {{template "base/footer" .}} | ||||
| @@ -4,7 +4,11 @@ | |||||
| <div class="ui container"> | <div class="ui container"> | ||||
| {{template "base/alert" .}} | {{template "base/alert" .}} | ||||
| <h2 class="ui header"> | <h2 class="ui header"> | ||||
| {{.i18n.Tr "repo.release.releases"}} | |||||
| <div class="ui breadcrumb"> | |||||
| <a class="section" href="{{.RepoLink}}{{if (ne .BranchName .Repository.DefaultBranch)}}/src/{{.BranchNameSubURL | EscapePound}}{{end}}">{{.i18n.Tr "repo.code"}}</a> | |||||
| <div class="divider"> / </div> | |||||
| <div class="active section" href="{{.RepoLink}}/releases">{{.i18n.Tr "repo.releases"}}</div> | |||||
| </div> | |||||
| {{if .CanCreateRelease}} | {{if .CanCreateRelease}} | ||||
| <div class="ui right"> | <div class="ui right"> | ||||
| <a class="ui small green button" href="{{$.RepoLink}}/releases/new"> | <a class="ui small green button" href="{{$.RepoLink}}/releases/new"> | ||||
| @@ -34,6 +34,21 @@ | |||||
| </div> | </div> | ||||
| {{end}} | {{end}} | ||||
| </div> | </div> | ||||
| {{if .ReadmeInList}} | |||||
| <div class="file-header-right"> | |||||
| <div class="ui right file-actions"> | |||||
| {{if .Repository.CanEnableEditor}} | |||||
| {{if .CanEditFile}} | |||||
| <a href="{{.RepoLink}}/_edit/{{EscapePound .BranchName}}/{{EscapePound .ReadmeName}}"><span class="btn-octicon poping up" data-content="{{.EditFileTooltip}}" data-position="bottom center" data-variation="tiny inverted">{{svg "octicon-pencil" 16}}</span></a> | |||||
| {{else}} | |||||
| <span class="btn-octicon poping up disabled" data-content="{{.EditFileTooltip}}" data-position="bottom center" data-variation="tiny inverted">{{svg "octicon-pencil" 16}}</span> | |||||
| {{end}} | |||||
| {{end}} | |||||
| </div> | |||||
| </div> | |||||
| {{end}} | |||||
| {{if not .ReadmeInList}} | {{if not .ReadmeInList}} | ||||
| <div class="file-header-right"> | <div class="file-header-right"> | ||||
| <div class="ui right file-actions"> | <div class="ui right file-actions"> | ||||
| @@ -2,6 +2,13 @@ | |||||
| <div class="repository wiki start"> | <div class="repository wiki start"> | ||||
| {{template "repo/header" .}} | {{template "repo/header" .}} | ||||
| <div class="ui container"> | <div class="ui container"> | ||||
| <h2 class="ui header"> | |||||
| <div class="ui breadcrumb"> | |||||
| <a class="section" href="{{.RepoLink}}{{if (ne .BranchName .Repository.DefaultBranch)}}/src/{{.BranchNameSubURL | EscapePound}}{{end}}">{{.i18n.Tr "repo.code"}}</a> | |||||
| <div class="divider"> / </div> | |||||
| <div class="active section" href="{{.RepoLink}}/wiki">{{.i18n.Tr "repo.wiki"}}</div> | |||||
| </div> | |||||
| </h2> | |||||
| <div class="ui center segment"> | <div class="ui center segment"> | ||||
| {{svg "octicon-book" 32}} | {{svg "octicon-book" 32}} | ||||
| <h2>{{.i18n.Tr "repo.wiki.welcome"}}</h2> | <h2>{{.i18n.Tr "repo.wiki.welcome"}}</h2> | ||||
| @@ -3,6 +3,14 @@ | |||||
| {{template "repo/header" .}} | {{template "repo/header" .}} | ||||
| {{ $title := .title}} | {{ $title := .title}} | ||||
| <div class="ui container"> | <div class="ui container"> | ||||
| <h2 class="ui header"> | |||||
| <div class="ui breadcrumb"> | |||||
| <a class="section" href="{{.RepoLink}}{{if (ne .BranchName .Repository.DefaultBranch)}}/src/{{.BranchNameSubURL | EscapePound}}{{end}}">{{.i18n.Tr "repo.code"}}</a> | |||||
| <div class="divider"> / </div> | |||||
| <div class="active section" href="{{.RepoLink}}/wiki">{{.i18n.Tr "repo.wiki"}}</div> | |||||
| </div> | |||||
| </h2> | |||||
| <div class="ui divider"></div> | |||||
| <div class="ui stackable grid"> | <div class="ui stackable grid"> | ||||
| <div class="ui ten wide column"> | <div class="ui ten wide column"> | ||||
| <div class="choose page"> | <div class="choose page"> | ||||
| @@ -28,7 +36,7 @@ | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| <div class="ui six wide column"> | |||||
| <div class="ui six wide column right aligned"> | |||||
| <div class="ui action small input" id="clone-panel"> | <div class="ui action small input" id="clone-panel"> | ||||
| {{if not $.DisableHTTP}} | {{if not $.DisableHTTP}} | ||||
| <button class="ui basic clone button" id="repo-clone-https" data-link="{{.WikiCloneLink.HTTPS}}"> | <button class="ui basic clone button" id="repo-clone-https" data-link="{{.WikiCloneLink.HTTPS}}"> | ||||
| @@ -0,0 +1,109 @@ | |||||
| <template> | |||||
| <div class="ui container"> | |||||
| <div class="row git-user-content"> | |||||
| <h3 class="ui header"> | |||||
| <div class="ui breadcrumb"> | |||||
| <a class="section" href="/">代码</a> | |||||
| <div class="divider"> / </div> | |||||
| <div class="active section" >贡献者({{totalNum}})</div> | |||||
| </div> | |||||
| </h3> | |||||
| <div class="ui horizontal relaxed list"> | |||||
| <div class="item user-list-item" v-for="(contributor,i) in contributors_list_page" > | |||||
| <a v-if="contributor.user_name" :href="AppSubUrl +'/'+ contributor.user_name"><img class="ui avatar s16 image js-popover-card" :src="contributor.rel_avatar_link"></a> | |||||
| <a v-else :href="'mailto:' + contributor.email "><img class="ui avatar s16 image js-popover-card" :avatar="contributor.email"></a> | |||||
| <div class="content"> | |||||
| <div class="header" > | |||||
| <a v-if="contributor.user_name" :href="AppSubUrl +'/'+ contributor.user_name">{{contributor.user_name}}</a> | |||||
| <a v-else :href="'mailto:' + contributor.email ">{{contributor.email}}</a> | |||||
| </div> | |||||
| <span class="commit-btn">Commits: {{contributor.commit_cnt}}</span> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| <div class="ui container" style="margin-top:50px;text-align:center"> | |||||
| <el-pagination | |||||
| background | |||||
| @current-change="handleCurrentChange" | |||||
| :current-page="currentPage" | |||||
| :page-size="pageSize" | |||||
| layout="total, prev, pager, next" | |||||
| :total="totalNum"> | |||||
| </el-pagination> | |||||
| </div> | |||||
| </div> | |||||
| </template> | |||||
| <script> | |||||
| const {AppSubUrl, StaticUrlPrefix, csrf} = window.config; | |||||
| export default { | |||||
| data() { | |||||
| return { | |||||
| url:'', | |||||
| contributors_list:[], | |||||
| contributors_list_page:[], | |||||
| currentPage:1, | |||||
| pageSize:50, | |||||
| totalNum:0, | |||||
| AppSubUrl:AppSubUrl | |||||
| }; | |||||
| }, | |||||
| methods: { | |||||
| getContributorsList(){ | |||||
| this.$axios.get(this.url+'/contributors/list').then((res)=>{ | |||||
| this.contributors_list = res.data.contributor_info | |||||
| this.totalNum = this.contributors_list.length | |||||
| this.contributors_list_page = this.contributors_list.slice(0,this.pageSize) | |||||
| }) | |||||
| }, | |||||
| handleCurrentChange(val){ | |||||
| this.contributors_list_page = this.contributors_list.slice((val-1)*this.pageSize,val*this.pageSize) | |||||
| }, | |||||
| }, | |||||
| computed:{ | |||||
| }, | |||||
| watch: { | |||||
| }, | |||||
| created(){ | |||||
| this.url=document.head.querySelector("[property~='og:url'][content]").content | |||||
| this.getContributorsList() | |||||
| }, | |||||
| updated(){ | |||||
| if(document.querySelectorAll('img[avatar]').length!==0){ | |||||
| window.LetterAvatar.transform() | |||||
| } | |||||
| } | |||||
| }; | |||||
| </script> | |||||
| <style scoped> | |||||
| /deep/ .el-pagination.is-background .el-pager li:not(.disabled).active { | |||||
| background-color: #5bb973; | |||||
| color: #FFF; | |||||
| } | |||||
| /deep/ .el-pagination.is-background .el-pager li.active { | |||||
| color: #fff; | |||||
| cursor: default; | |||||
| } | |||||
| /deep/ .el-pagination.is-background .el-pager li:hover { | |||||
| color: #5bb973; | |||||
| } | |||||
| /deep/ .el-pagination.is-background .el-pager li:not(.disabled):hover { | |||||
| color: #5bb973; | |||||
| } | |||||
| /deep/ .el-pagination.is-background .el-pager li:not(.disabled).active:hover { | |||||
| background-color: #5bb973; | |||||
| color: #FFF; | |||||
| } | |||||
| </style> | |||||
| @@ -1,9 +1,9 @@ | |||||
| <template> | <template> | ||||
| <div> | <div> | ||||
| <h4 id="about-desc" class="ui header">简介 | |||||
| <!-- <a class="edit-icon" href="javascript:void(0)" @click="editClick"> | |||||
| <i class="gray edit outline icon"></i> | |||||
| </a> --> | |||||
| <h4 id="about-desc" class="ui header desc-home">简介 | |||||
| <a class="edit-icon" href="javascript:void(0)" @click="editClick"> | |||||
| <i class="gray edit outline icon" style="margin-right: 0;"></i> | |||||
| </a> | |||||
| </h4> | </h4> | ||||
| <edit-dialog-cmpt | <edit-dialog-cmpt | ||||
| :vmContext="vmContext" | :vmContext="vmContext" | ||||
| @@ -11,8 +11,8 @@ | |||||
| v-model="editDataDialog" | v-model="editDataDialog" | ||||
| :deleteCallback="editDataFunc" | :deleteCallback="editDataFunc" | ||||
| :deleteLoading ="editDataListLoading" | :deleteLoading ="editDataListLoading" | ||||
| deleteParam = "ruleForm" | |||||
| @input="initForm" | |||||
| deleteParam = "ruleForm" | |||||
| @input="initForm" | |||||
| > | > | ||||
| <div slot="title"> | <div slot="title"> | ||||
| @@ -20,7 +20,7 @@ | |||||
| <div slot="content"> | <div slot="content"> | ||||
| <el-form label-position="top" :model="info" :rules="rule" ref="ruleForm"> | <el-form label-position="top" :model="info" :rules="rule" ref="ruleForm"> | ||||
| <el-form-item label="简介" prop="desc"> | <el-form-item label="简介" prop="desc"> | ||||
| <el-input v-model="info.desc" type="textarea" :autosize="{minRows:2,maxRows:6}"></el-input> | |||||
| <el-input v-model="info.desc" type="textarea" placeholder="请输入内容" :autosize="{minRows:4,maxRows:6}" maxlength="255" show-word-limit></el-input> | |||||
| </el-form-item> | </el-form-item> | ||||
| <el-form-item label="主页" prop="index_web" > | <el-form-item label="主页" prop="index_web" > | ||||
| <el-input v-model="info.index_web" placeholder="主页(eg: https://git.openi.org.cn)"></el-input> | <el-input v-model="info.index_web" placeholder="主页(eg: https://git.openi.org.cn)"></el-input> | ||||
| @@ -70,7 +70,7 @@ export default { | |||||
| this.info.desc = el; | this.info.desc = el; | ||||
| }, | }, | ||||
| getWeb() { | getWeb() { | ||||
| const el = $('a.link').text(); | |||||
| const el = $('a.link.edit-link').text(); | |||||
| this.info.index_web = el; | this.info.index_web = el; | ||||
| }, | }, | ||||
| getRepoName() { | getRepoName() { | ||||
| @@ -79,7 +79,6 @@ export default { | |||||
| }, | }, | ||||
| initForm(diaolog) { | initForm(diaolog) { | ||||
| if (diaolog === false) { | if (diaolog === false) { | ||||
| console.log("--watch----------") | |||||
| this.getRepoName(); | this.getRepoName(); | ||||
| this.getDesc(); | this.getDesc(); | ||||
| this.getWeb(); | this.getWeb(); | ||||
| @@ -133,12 +132,11 @@ export default { | |||||
| <style scoped> | <style scoped> | ||||
| .edit-icon{ | .edit-icon{ | ||||
| float: right; | |||||
| font-size: 16px; | |||||
| display: block; | |||||
| top: -2px; | |||||
| color: #8c92a4; | color: #8c92a4; | ||||
| background-color: transparent; | |||||
| } | |||||
| } | |||||
| .desc-home{ | |||||
| display: flex; | |||||
| justify-content: space-between; | |||||
| } | |||||
| </style> | </style> | ||||
| @@ -14,8 +14,8 @@ | |||||
| <slot name="content"></slot> | <slot name="content"></slot> | ||||
| <div slot="footer" class="dialog-footer"> | <div slot="footer" class="dialog-footer"> | ||||
| <el-button @click="deleteDialog = false">{{"取消"}}</el-button> | |||||
| <el-button type="primary" @click="deleteCallback.call(vmContext,deleteParam)">{{"确定"}}</el-button> | |||||
| <el-button size="small" @click="deleteDialog = false">{{"取消"}}</el-button> | |||||
| <el-button size="small" style="background-color: #21ba45;color: #fff;" @click="deleteCallback.call(vmContext,deleteParam)">{{"确定"}}</el-button> | |||||
| </div> | </div> | ||||
| </el-dialog> | </el-dialog> | ||||
| </template> | </template> | ||||
| @@ -80,26 +80,31 @@ export default { | |||||
| .message-box__content .message-box-title{font-size:16px;padding:2px 0;color:#333;} | .message-box__content .message-box-title{font-size:16px;padding:2px 0;color:#333;} | ||||
| .message-box__content .message-box-p{font-size:16px;padding:20px 0;color:#333;} | .message-box__content .message-box-p{font-size:16px;padding:20px 0;color:#333;} | ||||
| .message-box__content .message-box-info{color:#999;padding:2px 0;} | .message-box__content .message-box-info{color:#999;padding:2px 0;} | ||||
| .dialog-footer,.el-message-box__btns{text-align:center;} | |||||
| /deep/ .el-dialog__body{ | |||||
| padding: 1rem; | |||||
| } | |||||
| /deep/ .el-dialog__header { | /deep/ .el-dialog__header { | ||||
| background: #0067b3; | |||||
| padding: 12px 30px; | |||||
| line-height: 25px;} | |||||
| background: #f0f0f0; | |||||
| padding: 1rem; | |||||
| } | |||||
| /deep/ .el-dialog__title { | /deep/ .el-dialog__title { | ||||
| font-family: PingFangSC-Regular; | font-family: PingFangSC-Regular; | ||||
| font-size: 18px; | |||||
| color: #fff; | |||||
| font-size: 1.28571429rem; | |||||
| color: rgba(0,0,0,.87); | |||||
| font-weight: 200; | font-weight: 200; | ||||
| line-height: 25px; | line-height: 25px; | ||||
| height: 25px; | height: 25px; | ||||
| } | } | ||||
| /deep/ .el-dialog__footer { | /deep/ .el-dialog__footer { | ||||
| background: #eff3f9; | background: #eff3f9; | ||||
| padding: 20px 30px; | |||||
| padding: 1rem; | |||||
| } | } | ||||
| /deep/ .el-dialog{ | /deep/ .el-dialog{ | ||||
| width: 40%; | |||||
| width: 30%; | |||||
| } | |||||
| /deep/ .el-form-item__label{ | |||||
| padding: 0; | |||||
| } | } | ||||
| </style> | </style> | ||||
| @@ -0,0 +1,74 @@ | |||||
| /** | |||||
| * LetterAvatar | |||||
| * | |||||
| * Artur Heinze | |||||
| * Create Letter avatar based on Initials | |||||
| * based on https://gist.github.com/leecrossley/6027780 | |||||
| */ | |||||
| (function(w, d){ | |||||
| function LetterAvatar (name, size, color) { | |||||
| name = name || ''; | |||||
| size = size || 60; | |||||
| var colours = [ | |||||
| "#1abc9c", "#2ecc71", "#3498db", "#9b59b6", "#34495e", "#16a085", "#27ae60", "#2980b9", "#8e44ad", "#2c3e50", | |||||
| "#f1c40f", "#e67e22", "#e74c3c", "#00bcd4", "#95a5a6", "#f39c12", "#d35400", "#c0392b", "#bdc3c7", "#7f8c8d" | |||||
| ], | |||||
| nameSplit = String(name).split(' '), | |||||
| initials, charIndex, colourIndex, canvas, context, dataURI; | |||||
| if (nameSplit.length == 1) { | |||||
| initials = nameSplit[0] ? nameSplit[0].charAt(0):'?'; | |||||
| } else { | |||||
| initials = nameSplit[0].charAt(0) + nameSplit[1].charAt(0); | |||||
| } | |||||
| if (w.devicePixelRatio) { | |||||
| size = (size * w.devicePixelRatio); | |||||
| } | |||||
| charIndex = (initials == '?' ? 72 : initials.charCodeAt(0)) - 64; | |||||
| colourIndex = charIndex % 20; | |||||
| canvas = d.createElement('canvas'); | |||||
| canvas.width = size; | |||||
| canvas.height = size; | |||||
| context = canvas.getContext("2d"); | |||||
| context.fillStyle = color ? color : colours[colourIndex - 1]; | |||||
| context.fillRect (0, 0, canvas.width, canvas.height); | |||||
| context.font = Math.round(canvas.width/2)+"px 'Microsoft Yahei'"; | |||||
| context.textAlign = "center"; | |||||
| context.fillStyle = "#FFF"; | |||||
| context.fillText(initials, size / 2, size / 1.5); | |||||
| dataURI = canvas.toDataURL(); | |||||
| canvas = null; | |||||
| return dataURI; | |||||
| } | |||||
| LetterAvatar.transform = function() { | |||||
| Array.prototype.forEach.call(d.querySelectorAll('img[avatar]'), function(img, name, color) { | |||||
| name = img.getAttribute('avatar'); | |||||
| color = img.getAttribute('color'); | |||||
| img.src = LetterAvatar(name, img.getAttribute('width'), color); | |||||
| img.removeAttribute('avatar'); | |||||
| img.setAttribute('alt', name); | |||||
| }); | |||||
| }; | |||||
| // AMD support | |||||
| if (typeof define === 'function' && define.amd) { | |||||
| define(function () { return LetterAvatar; }); | |||||
| // CommonJS and Node.js module support. | |||||
| } else if (typeof exports !== 'undefined') { | |||||
| // Support Node.js specific `module.exports` (which can be a function) | |||||
| if (typeof module != 'undefined' && module.exports) { | |||||
| exports = module.exports = LetterAvatar; | |||||
| } | |||||
| // But always support CommonJS module 1.1.1 spec (`exports` cannot be a function) | |||||
| exports.LetterAvatar = LetterAvatar; | |||||
| } else { | |||||
| window.LetterAvatar = LetterAvatar; | |||||
| d.addEventListener('DOMContentLoaded', function(event) { | |||||
| LetterAvatar.transform(); | |||||
| }); | |||||
| } | |||||
| })(window, document); | |||||
| @@ -4,7 +4,7 @@ | |||||
| import './publicpath.js'; | import './publicpath.js'; | ||||
| import './polyfills.js'; | import './polyfills.js'; | ||||
| import './features/letteravatar.js' | |||||
| import Vue from 'vue'; | import Vue from 'vue'; | ||||
| import ElementUI from 'element-ui'; | import ElementUI from 'element-ui'; | ||||
| import 'element-ui/lib/theme-chalk/index.css'; | import 'element-ui/lib/theme-chalk/index.css'; | ||||
| @@ -37,6 +37,7 @@ import ObsUploader from './components/ObsUploader.vue'; | |||||
| import EditAboutInfo from './components/EditAboutInfo.vue'; | import EditAboutInfo from './components/EditAboutInfo.vue'; | ||||
| import Images from './components/Images.vue' | import Images from './components/Images.vue' | ||||
| import EditTopics from './components/EditTopics.vue' | import EditTopics from './components/EditTopics.vue' | ||||
| import Contributors from './components/Contributors.vue' | |||||
| Vue.use(ElementUI); | Vue.use(ElementUI); | ||||
| Vue.prototype.$axios = axios; | Vue.prototype.$axios = axios; | ||||
| @@ -2969,6 +2970,7 @@ $(document).ready(async () => { | |||||
| initObsUploader(); | initObsUploader(); | ||||
| initVueEditAbout(); | initVueEditAbout(); | ||||
| initVueEditTopic(); | initVueEditTopic(); | ||||
| initVueContributors(); | |||||
| initVueImages(); | initVueImages(); | ||||
| initTeamSettings(); | initTeamSettings(); | ||||
| initCtrlEnterSubmit(); | initCtrlEnterSubmit(); | ||||
| @@ -3682,6 +3684,21 @@ function initVueEditTopic() { | |||||
| render:h=>h(EditTopics) | render:h=>h(EditTopics) | ||||
| }) | }) | ||||
| } | } | ||||
| function initVueContributors() { | |||||
| const el = document.getElementById('Contributors'); | |||||
| if (!el) { | |||||
| return; | |||||
| } | |||||
| new Vue({ | |||||
| el:'#Contributors', | |||||
| render:h=>h(Contributors) | |||||
| }) | |||||
| } | |||||
| function initVueImages() { | function initVueImages() { | ||||
| const el = document.getElementById('images'); | const el = document.getElementById('images'); | ||||
| console.log("el",el) | console.log("el",el) | ||||
| @@ -243,4 +243,77 @@ footer .column{margin-bottom:0!important; padding-bottom:0!important;} | |||||
| display: inline-block; | display: inline-block; | ||||
| width: 100%; | width: 100%; | ||||
| } | } | ||||
| .git-user-content{ | |||||
| margin-bottom: 16px; | |||||
| word-break: break-all; | |||||
| } | |||||
| .row.git-user-content .ui.avatar.s16.image { | |||||
| width: 50px !important; | |||||
| height: 50px !important; | |||||
| vertical-align: middle; | |||||
| border-radius: 500rem;} | |||||
| .user-list-item { | |||||
| padding: 0.3em 0px !important; | |||||
| margin: 15px 0 !important; | |||||
| width: 220px !important; | |||||
| } | |||||
| .row.git-user-content .content { | |||||
| margin-left: 6px; | |||||
| display: inline-block; | |||||
| vertical-align: top !important; | |||||
| overflow: hidden; | |||||
| } | |||||
| .row.git-user-content .content .header { | |||||
| font-weight: bold; | |||||
| } | |||||
| .item.user-list-item .header { | |||||
| line-height: 23px !important; | |||||
| font-size: 16px !important; | |||||
| text-overflow: ellipsis; | |||||
| overflow: hidden; | |||||
| width: 145px; | |||||
| white-space:nowrap; | |||||
| } | |||||
| .item.user-list-item .header a { | |||||
| color: #587284 !important; | |||||
| } | |||||
| .row.git-user-content .content .commit-btn { | |||||
| margin-top: 6px; | |||||
| float: left; | |||||
| font-size: 11px; | |||||
| color: #40485b !important; | |||||
| } | |||||
| .dropdown-menu { | |||||
| position: relative; | |||||
| display: inline-block; | |||||
| margin-top: 4px; | |||||
| } | |||||
| .dropdown-menu:hover .dropdown-content { | |||||
| display: block; | |||||
| } | |||||
| .dropdown-content{ | |||||
| display: none; | |||||
| position: absolute; | |||||
| background-color: #ffffff; | |||||
| min-width: 180px; | |||||
| z-index: 999; | |||||
| border: 1px solid transparent; | |||||
| border-color: #d4d4d5; | |||||
| border-top: none; | |||||
| } | |||||
| .dropdown-content a { | |||||
| color: black; | |||||
| padding: 12px 16px; | |||||
| text-decoration: none; | |||||
| display: block; | |||||
| } | |||||
| .dropdown-content a:hover {background-color: #f1f1f1} | |||||
| .cloudbrain-question{ | |||||
| margin-left: 4px !important; | |||||
| color: #3291F8; | |||||
| } | |||||