diff --git a/.gitignore b/.gitignore index 572212e0e..9f34fea2a 100644 --- a/.gitignore +++ b/.gitignore @@ -95,3 +95,6 @@ prime/ # Make evidence files /.make_evidence + +/templates/home_bak.tmpl +/==bak \ No newline at end of file diff --git a/custom/public/css/git.openi.css b/custom/public/css/git.openi.css new file mode 100644 index 000000000..ab5c92c01 --- /dev/null +++ b/custom/public/css/git.openi.css @@ -0,0 +1,184 @@ +.bg-gray{ background-color:#F8F8F8!important;} +.am-mb-0{ margin-bottom: 0 !important;} +.am-mb-05{ margin-bottom: 0.5rem !important;} +.am-mb-10{ margin-bottom: 1.0rem !important;} +.am-mb-15{ margin-bottom: 1.5rem !important;} +.am-mb-20{ margin-bottom: 2.0rem !important;} +.am-mb-30{ margin-bottom: 3.0rem !important;} +.am-mt-0{ margin-top: 0 !important;} +.am-mt-05{ margin-top: 0.5rem !important;} +.am-mt-10{ margin-top: 1.0rem !important;} +.am-mt-15{ margin-top: 1.5rem !important;} +.am-mt-20{ margin-top: 2.0rem !important;} +.am-mt-30{ margin-top: 3.0rem !important;} +.am-pb-0{ padding-bottom: 0 !important;} +.am-pb-05{ padding-bottom: 0.5rem !important;} +.am-pb-10{ padding-bottom: 1.0rem !important;} +.am-pb-15{ padding-bottom: 1.5rem !important;} +.am-pb-20{ padding-bottom: 2.0rem !important;} +.am-pb-30{ padding-bottom: 3.0rem !important;} +.am-pt-0{ padding-top: 0 !important;} +.am-pt-05{ padding-top: 0.5rem !important;} +.am-pt-10{ padding-top: 1.0rem !important;} +.am-pt-15{ padding-top: 1.5rem !important;} +.am-pt-20{ padding-top: 2.0rem !important;} +.am-pt-30{ padding-top: 3.0rem !important;} +.am-pl-30{ padding-left: 3.0rem !important;} +.am-ml-30{ margin-left: 3.0rem !important;} +.am-pr-30{ padding-right: 3.0rem !important;} +.am-mr-30{ margin-right: 3.0rem !important;} +.am-lh-18{ line-height: 1.8em;} + +.opacity5{ opacity:0.5;} +.radius15{ border-radius:1.5rem !important; } +.radius10{ border-radius:1.0rem !important; } +.radius5{ border-radius:0.5rem !important; } +.am-shadow-1{ + -webkit-box-shadow: 0 1px 2px 0 rgba(34,36,38,.15); + box-shadow: 0 1px 2px 0 rgba(34,36,38,.15); +} +.am-shadow-2{ + -webkit-box-shadow: 0 2px 4px 0 rgba(34,36,38,.3); + box-shadow: 0 2px 4px 0 rgba(34,36,38,.3); +} + + +.ui.secondary.hometop.segment{ + background: #DFE9F0; + padding-top: 0; + border: none; + margin-bottom: 90px; +} +.ui.secondary.hometop.segment #navbar{ + z-index: 10; +} + +.hometop .ui.secondary.menu .active.item{ + color: #000; + background:none; + border-bottom: 1px solid #000; +} +.hometop .following.bar #navbar .brand{ + padding-top: .78571429em; +} +.hometop .following.bar .brand .ui.mini.image { + height: 50px; +} + +.homebanner{ + position: relative; + padding: 100px 32px 80px; + z-index: 9; +} +.homebanner .ui.header .sub.header{ + color: #3291F8; +} +.bannerpic{ + position: absolute; + right: 50px; + bottom: -64px; + width: 560px; +} +.ui[class*="very padded"].segment.i-code{ + padding-left: 6.0rem; +} +.i-code > .ui.blue.header{ + color: #1678c2!important; +} +.i-code h2{ + position: relative; +} +.i-code h2::before { + content: ""; + position: absolute; + left: calc(-4.0rem + 6px); + top: 0.8rem; + width: 18px; + height: 18px; + border: 2px solid #505559; + border-radius: 50%; + background: #1b1c1d; + z-index: 9; +} +.i-code h2.am-bw::before{ + background: #FFF; +} +.i-code-pic{ + position: relative; +} +.i-code-pic > img{ + margin-bottom: -3.0rem; +} +.i-env .ui.cards>.card>.image{ + background: none; +} +.i-env .ui.cards>.card>.content{ + border-top: none; +} +.leftline01{ + position: absolute; + left: 3.0rem; + top: 0; + bottom: 0; + border-left: 2px solid #505559; + border-bottom: 2px solid #505559; + border-radius: 0 0 0 2.0rem; + width: 2.0rem; +} +.leftline02{ + position: absolute; + left: 5rem; + top: calc(-5.0rem - 2px); + border-top: 2px solid #505559; + border-right: 2px solid #505559; + border-radius: 0 2.0rem 0 0; + width: 17.5rem; + height: 6.0rem; +} + +@media only screen and (max-width: 767px) { + .am-mt-30{ margin-top: 1.5rem !important;} + .ui.secondary.hometop.segment{ + margin-bottom: 2.0rem; + } + .bannerpic, .i-code-pic{ + display: none; + } + .i-code h2::before { + left: calc(-5.0rem + 6px); + } + .i-code h2.am-bw::before{ + left: calc(-4.0rem + 6px); + } + .leftline01{ + width: calc(50% - 4.0rem); + } + .leftline02{ + left: calc(50% - 1.0rem); + top: calc(-3.5rem - 2px); + } +} + +@media only screen and (min-width: 768px) and (max-width: 991px) { + .bannerpic, .i-code-pic{ + display: none; + } + .i-code h2::before { + left: calc(-5.0rem + 6px); + } + .i-code h2.am-bw::before{ + left: calc(-4.0rem + 6px); + } +} + +@media only screen and (min-width: 992px) and (max-width: 1199px) { + +} + +@media only screen and (min-width: 1200px) and (max-width: 1919px) { + +} + +@media only screen and (min-width: 1920px) { + +} \ No newline at end of file diff --git a/custom/public/img/develop.svg b/custom/public/img/develop.svg new file mode 100644 index 000000000..fb8412dda --- /dev/null +++ b/custom/public/img/develop.svg @@ -0,0 +1,711 @@ + + + diff --git a/custom/public/img/gitopeni-index-01.svg b/custom/public/img/gitopeni-index-01.svg new file mode 100644 index 000000000..18401747f --- /dev/null +++ b/custom/public/img/gitopeni-index-01.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom/public/img/gitopeni-index-02.svg b/custom/public/img/gitopeni-index-02.svg new file mode 100644 index 000000000..4b47fe632 --- /dev/null +++ b/custom/public/img/gitopeni-index-02.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom/public/img/i-code-pic.jpg b/custom/public/img/i-code-pic.jpg new file mode 100644 index 000000000..cba627b73 Binary files /dev/null and b/custom/public/img/i-code-pic.jpg differ diff --git a/custom/public/img/i-data-pic.jpg b/custom/public/img/i-data-pic.jpg new file mode 100644 index 000000000..2e5dbfb1f Binary files /dev/null and b/custom/public/img/i-data-pic.jpg differ diff --git a/custom/public/img/i-pic-01.svg b/custom/public/img/i-pic-01.svg new file mode 100644 index 000000000..97d8e4165 --- /dev/null +++ b/custom/public/img/i-pic-01.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom/public/img/i-pic-02.svg b/custom/public/img/i-pic-02.svg new file mode 100644 index 000000000..ef8606b5e --- /dev/null +++ b/custom/public/img/i-pic-02.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom/public/img/i-pic-03.svg b/custom/public/img/i-pic-03.svg new file mode 100644 index 000000000..779a28d5f --- /dev/null +++ b/custom/public/img/i-pic-03.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom/public/img/i-pic-04.svg b/custom/public/img/i-pic-04.svg new file mode 100644 index 000000000..96bb3e455 --- /dev/null +++ b/custom/public/img/i-pic-04.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom/public/img/i-yunnao.svg b/custom/public/img/i-yunnao.svg new file mode 100644 index 000000000..aeb1e9435 --- /dev/null +++ b/custom/public/img/i-yunnao.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom/public/img/icon-403@2x.png b/custom/public/img/icon-403@2x.png new file mode 100644 index 000000000..65bc29cd8 Binary files /dev/null and b/custom/public/img/icon-403@2x.png differ diff --git a/custom/public/img/icon-404@2x.png b/custom/public/img/icon-404@2x.png new file mode 100644 index 000000000..d5e606cbb Binary files /dev/null and b/custom/public/img/icon-404@2x.png differ diff --git a/custom/public/img/icon-500@2x.png b/custom/public/img/icon-500@2x.png new file mode 100644 index 000000000..e493b71c7 Binary files /dev/null and b/custom/public/img/icon-500@2x.png differ diff --git a/custom/public/img/logo-w.svg b/custom/public/img/logo-w.svg new file mode 100644 index 000000000..867acc1e2 --- /dev/null +++ b/custom/public/img/logo-w.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom/public/img/logo.svg b/custom/public/img/logo.svg new file mode 100644 index 000000000..b2330f885 --- /dev/null +++ b/custom/public/img/logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/models/cloudbrain.go b/models/cloudbrain.go index c8000c5a6..f9c0fb4e0 100755 --- a/models/cloudbrain.go +++ b/models/cloudbrain.go @@ -2,7 +2,6 @@ package models import ( "encoding/json" - "errors" "fmt" "time" "xorm.io/xorm" @@ -300,7 +299,7 @@ type CommitImageResult struct { Payload map[string]interface{} `json:"payload"` } -type StopJobResult struct { +type CloudBrainResult struct { Code string `json:"code"` Msg string `json:"msg"` } @@ -569,7 +568,7 @@ func getRepoCloudBrain(cb *Cloudbrain) (*Cloudbrain, error) { if err != nil { return nil, err } else if !has { - return nil, errors.New("cloudbrain task is not found") + return nil, ErrJobNotExist{} } return cb, nil } @@ -609,3 +608,8 @@ func deleteJob(e Engine, job *Cloudbrain) error { _, err := e.ID(job.ID).Delete(job) return err } + +func GetCloudbrainByName(jobName string) (*Cloudbrain, error) { + cb := &Cloudbrain{JobName: jobName} + return getRepoCloudBrain(cb) +} diff --git a/models/error.go b/models/error.go index 66bb74de0..9d1c68658 100755 --- a/models/error.go +++ b/models/error.go @@ -1987,3 +1987,15 @@ func IsErrFileChunkNotExist(err error) bool { _, ok := err.(ErrFileChunkNotExist) return ok } + +type ErrJobNotExist struct { +} + +func IsErrJobNotExist(err error) bool { + _, ok := err.(ErrJobNotExist) + return ok +} + +func (err ErrJobNotExist) Error() string { + return fmt.Sprintf("the job does not exist") +} diff --git a/modules/cloudbrain/resty.go b/modules/cloudbrain/resty.go index ed6157776..fa9b25011 100755 --- a/modules/cloudbrain/resty.go +++ b/modules/cloudbrain/resty.go @@ -2,6 +2,7 @@ package cloudbrain import ( "code.gitea.io/gitea/modules/log" + "encoding/json" "fmt" "code.gitea.io/gitea/models" @@ -143,14 +144,26 @@ sendjob: return nil, fmt.Errorf("resty GetImages: %v", err) } - if getImagesResult.Code == "S401" && retry < 1 { + var response models.CloudBrainResult + err = json.Unmarshal(res.Body(), &response) + if err != nil { + log.Error("json.Unmarshal failed: %s", err.Error()) + return &getImagesResult, fmt.Errorf("json.Unmarshal failed: %s", err.Error()) + } + + if response.Code == "S401" && retry < 1 { retry++ _ = loginCloudbrain() goto sendjob } + if len(response.Code) != 0 { + log.Error("getImagesResult failed(%s): %s", response.Code, response.Msg) + return &getImagesResult, fmt.Errorf("getImagesResult failed(%s): %s", response.Code, response.Msg) + } + if getImagesResult.Code != Success { - return &getImagesResult, fmt.Errorf("getImgesResult err: %s", res.String()) + return &getImagesResult, fmt.Errorf("getImagesResult err: %s", res.String()) } return &getImagesResult, nil @@ -223,7 +236,7 @@ sendjob: func StopJob(jobID string) error { checkSetting() client := getRestyClient() - var result models.StopJobResult + var result models.CloudBrainResult retry := 0 diff --git a/modules/git/repo.go b/modules/git/repo.go index 644ff0928..a2a4d28af 100644 --- a/modules/git/repo.go +++ b/modules/git/repo.go @@ -434,3 +434,38 @@ func GetDivergingCommits(repoPath string, baseBranch string, targetBranch string return DivergeObject{ahead, behind}, nil } + +type Contributor struct { + CommitCnt int + Committer string + Email string +} + +func GetContributors(repoPath string) ([]Contributor, error){ + cmd := NewCommand("shortlog", "-sne", "--all") + stdout, err := cmd.RunInDir(repoPath) + if err != nil { + return nil, err + } + stdout = strings.Trim(stdout, "\n") + contributorRows := strings.Split(stdout, "\n") + if len(contributorRows) > 0 { + contributorsInfo := make([]Contributor, len(contributorRows)) + for i := 0; i < len(contributorRows); i++ { + var oneCount string = strings.Trim(contributorRows[i], " ") + if strings.Index(oneCount, "\t") < 0 { + continue + } + number := oneCount[0:strings.Index(oneCount, "\t")] + commitCnt, _ := strconv.Atoi(number) + committer := oneCount[strings.Index(oneCount, "\t")+1:strings.LastIndex(oneCount, " ")] + committer = strings.Trim(committer, " ") + email := oneCount[strings.Index(oneCount, "<")+1:strings.Index(oneCount, ">")] + contributorsInfo[i] = Contributor{ + commitCnt, committer, email, + } + } + return contributorsInfo, nil + } + return nil, nil +} diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index c4956c65f..b5ad101ef 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -1,4 +1,5 @@ home = Home +index = Home dashboard = Dashboard explore = Explore datasets = Datasets @@ -702,6 +703,7 @@ delete= delete owner = Owner repo_name = Repository Name repo_name_helper = Good repository names use short, memorable and unique keywords. +repo_owner_helper = Some organizations may not show up in the dropdown due to a maximum repository count limit. repo_size = Repository Size template = Template template_select = Select a template. @@ -1817,6 +1819,7 @@ org_full_name_holder = Organization Full Name org_name_helper = Organization names should be short and memorable. create_org = Create Organization repo_updated = Updated +home = Home people = People teams = Teams lower_members = members @@ -2482,9 +2485,9 @@ error.unit_not_allowed = You are not allowed to access this repository section. [custom] head.community = Community -head.project = Project +head.project = Repositories head.openi = OpenI -head.dataset = Dataset +head.dataset = Datasets foot.council = Council foot.technical_committee = Technical Committee foot.join = Join OpenI diff --git a/options/locale/locale_zh-CN.ini b/options/locale/locale_zh-CN.ini index 8c0509752..67fc9ef58 100755 --- a/options/locale/locale_zh-CN.ini +++ b/options/locale/locale_zh-CN.ini @@ -1,5 +1,5 @@ home=个人中心 -index=首页 +index=个人中心 dashboard=个人中心 explore=探索 datasets=数据集 @@ -287,7 +287,7 @@ email_domain_blacklisted=您不能使用您的电子邮件地址注册。 authorize_application=应用授权 authorize_redirect_notice=如果您授权此应用,您将会被重定向到 %s。 authorize_application_created_by=此应用由%s创建。 -authorize_application_description=如果您允许,它将能够读取和修改您的所有帐户信息,包括私人项目和组织。 +authorize_application_description=如果您允许,它将能够读取您的个人信息。 authorize_title=授权 %s 访问您的帐户? authorization_failed=授权失败 authorization_failed_desc=授权失败,这是一个无效的请求。请联系尝试授权应用的管理员。 @@ -704,6 +704,7 @@ delete=删除 owner=拥有者 repo_name=项目名称 repo_name_helper=好的存储库名称使用简短、深刻和独特的关键字。 +repo_owner_helper = 由于最大存储库数量限制,某些组织名称可能不会显示在下拉列表中。 repo_size=项目大小 template=模板 template_select=选择模板 @@ -1819,6 +1820,7 @@ org_full_name_holder=组织全名 org_name_helper=组织名字应该简单明了。 create_org=创建组织 repo_updated=最后更新于 +home=组织主页 people=组织成员 teams=组织团队 lower_members=名成员 @@ -2482,7 +2484,7 @@ error.unit_not_allowed=您没有权限访问此项目单元 [custom] head.community=启智社区 -head.project=所有项目 +head.project=项目 head.openi=启智项目 head.dataset=数据集 foot.council=理事会 diff --git a/routers/org/home.go b/routers/org/home.go old mode 100644 new mode 100755 index fa61218d3..b11c179c1 --- a/routers/org/home.go +++ b/routers/org/home.go @@ -20,6 +20,7 @@ const ( // Home show organization home page func Home(ctx *context.Context) { ctx.SetParams(":org", ctx.Params(":username")) + ctx.Data["PageIsOrgHome"] = true context.HandleOrgAssignment(ctx) if ctx.Written() { return diff --git a/routers/repo/cloudbrain.go b/routers/repo/cloudbrain.go index 27642d7bb..1088f47d3 100755 --- a/routers/repo/cloudbrain.go +++ b/routers/repo/cloudbrain.go @@ -168,11 +168,24 @@ func CloudBrainCreate(ctx *context.Context, form auth.CreateCloudBrainForm) { ctx.RenderWithErr("jobtype error", tplCloudBrainNew, &form) return } + + _, err := models.GetCloudbrainByName(jobName) + if err == nil { + log.Error("the job name did already exist", ctx.Data["MsgID"]) + ctx.RenderWithErr("the job name did already exist", tplCloudBrainNew, &form) + return + } else { + if !models.IsErrJobNotExist(err) { + log.Error("system error, %v", err, ctx.Data["MsgID"]) + ctx.RenderWithErr("system error", tplCloudBrainNew, &form) + return + } + } repo := ctx.Repo.Repository downloadCode(repo, codePath) modelPath := setting.JobPath + jobName + cloudbrain.ModelMountPath - err := os.MkdirAll(modelPath, os.ModePerm) + err = os.MkdirAll(modelPath, os.ModePerm) if err != nil { ctx.RenderWithErr(err.Error(), tplCloudBrainNew, &form) return diff --git a/routers/repo/view.go b/routers/repo/view.go index 9c9cdc06b..76593ecc7 100644 --- a/routers/repo/view.go +++ b/routers/repo/view.go @@ -7,6 +7,7 @@ package repo import ( "bytes" + "code.gitea.io/gitea/modules/options" "encoding/base64" "fmt" gotemplate "html/template" @@ -567,9 +568,32 @@ func safeURL(address string) string { return u.String() } +type ContributorInfo struct { + UserInfo *models.User + Email string // for contributor who is not a registered user +} + // Home render repository home page func Home(ctx *context.Context) { if len(ctx.Repo.Units) > 0 { + //get repo contributors info + contributors, err := git.GetContributors(ctx.Repo.Repository.RepoPath()) + if err == nil && contributors != nil { + var contributorInfos []*ContributorInfo + for _, c := range contributors { + user, err := models.GetUserByEmail(c.Email) + if err == nil { + contributorInfos = append(contributorInfos, &ContributorInfo{ + user, c.Email, + }) + } else { + contributorInfos = append(contributorInfos, &ContributorInfo{ + nil, c.Email, + }) + } + } + ctx.Data["ContributorInfo"] = contributorInfos + } if ctx.Repo.Repository.IsBeingCreated() { task, err := models.GetMigratingTask(ctx.Repo.Repository.ID) if err != nil { @@ -611,6 +635,39 @@ func Home(ctx *context.Context) { ctx.NotFound("Home", fmt.Errorf(ctx.Tr("units.error.no_unit_allowed_repo"))) } +func renderLicense(ctx *context.Context) { + entry, err := ctx.Repo.Commit.GetTreeEntryByPath("LICENSE") + if err != nil { + log.Error(err.Error()) + return + } + blob := entry.Blob() + dataRc, err := blob.DataAsync() + if err != nil { + log.Error("DataAsync", err) + return + } + defer dataRc.Close() + buf, err := ioutil.ReadAll(dataRc) + if err != nil { + log.Error("DataAsync", err) + return + } + for _, f := range models.Licenses { + license, err := options.License(f) + if err != nil { + log.Error("failed to get license content: %v, err:%v", f, err) + continue + } + if bytes.Compare(buf,license) == 0 { + log.Info("got matched license:%v",f) + ctx.Data["LICENSE"] = f + return + } + } + log.Info("not found matched license,repo:%v",ctx.Repo.Repository.Name) +} + func renderLanguageStats(ctx *context.Context) { langs, err := ctx.Repo.Repository.GetTopLanguageStats(5) if err != nil { @@ -657,6 +714,8 @@ func renderCode(ctx *context.Context) { // Get Topics of this repo renderRepoTopics(ctx) + // Get license of this repo + renderLicense(ctx) if ctx.Written() { return } diff --git a/routers/routes/routes.go b/routers/routes/routes.go index c59ecefca..100ff009f 100755 --- a/routers/routes/routes.go +++ b/routers/routes/routes.go @@ -307,7 +307,7 @@ func RegisterRoutes(m *macaron.Macaron) { m.Head("/", func() string { return "" }) - m.Get("/", routers.ExploreRepos) + m.Get("/", routers.Dashboard) m.Get("/dashboard", routers.Dashboard) m.Group("/explore", func() { m.Get("", func(ctx *context.Context) { diff --git a/routers/user/auth.go b/routers/user/auth.go index 421598347..fe49b7b12 100755 --- a/routers/user/auth.go +++ b/routers/user/auth.go @@ -535,7 +535,10 @@ func handleSignInFull(ctx *context.Context, u *models.User, remember bool, obeyR log.Error("Unable to store session: %v", err) } - // Language setting of the user overwrites the one previously set + // Language setting of the user use the one previously set + if len(ctx.GetCookie("lang")) != 0 { + u.Language = ctx.GetCookie("lang") + } // If the user does not have a locale set, we save the current one. if len(u.Language) == 0 { u.Language = ctx.Locale.Language() diff --git a/templates/base/footer_content.tmpl b/templates/base/footer_content.tmpl index 921fe7f8b..86ef0d98e 100755 --- a/templates/base/footer_content.tmpl +++ b/templates/base/footer_content.tmpl @@ -5,15 +5,15 @@