Browse Source

repo: allow private repository to have public wiki or issues

Relates to #649 and #2157
pull/4343/head
Unknwon 8 years ago
parent
commit
8196430f47
No known key found for this signature in database
GPG Key ID: 25B575AE3213B2B3
  1. 34
      cmd/web.go
  2. 2
      conf/locale/locale_en-US.ini
  3. 2
      gogs.go
  4. 21
      models/repo.go
  5. 4
      modules/bindata/bindata.go
  6. 74
      modules/context/repo.go
  7. 2
      modules/form/repo.go
  8. 3
      public/css/gogs.css
  9. 9
      public/js/gogs.js
  10. 6
      public/less/_repository.less
  11. 46
      routers/repo/issue.go
  12. 2
      routers/repo/setting.go
  13. 2
      templates/.VERSION
  14. 60
      templates/repo/header.tmpl
  15. 39
      templates/repo/settings/options.tmpl

34
cmd/web.go

@ -493,18 +493,15 @@ func runWeb(ctx *cli.Context) error {
m.Get("/:username/:reponame/action/:action", reqSignIn, context.RepoAssignment(), repo.Action) m.Get("/:username/:reponame/action/:action", reqSignIn, context.RepoAssignment(), repo.Action)
m.Group("/:username/:reponame", func() { m.Group("/:username/:reponame", func() {
m.Get("/issues", repo.RetrieveLabels, repo.Issues)
m.Get("/issues/:index", repo.ViewIssue)
// FIXME: should use different URLs but mostly same logic for comments of issue and pull reuqest. // FIXME: should use different URLs but mostly same logic for comments of issue and pull reuqest.
// So they can apply their own enable/disable logic on routers. // So they can apply their own enable/disable logic on routers.
m.Group("/issues", func() { m.Group("/issues", func() {
m.Combo("/new", repo.MustEnableIssues).Get(context.RepoRef(), repo.NewIssue). m.Combo("/new", repo.MustEnableIssues).Get(context.RepoRef(), repo.NewIssue).
Post(bindIgnErr(form.NewIssue{}), repo.NewIssuePost) Post(bindIgnErr(form.NewIssue{}), repo.NewIssuePost)
m.Group("/:index", func() {
m.Post("/label", repo.UpdateIssueLabel)
m.Post("/milestone", repo.UpdateIssueMilestone)
m.Post("/assignee", repo.UpdateIssueAssignee)
}, reqRepoWriter)
m.Group("/:index", func() { m.Group("/:index", func() {
m.Post("/title", repo.UpdateIssueTitle) m.Post("/title", repo.UpdateIssueTitle)
m.Post("/content", repo.UpdateIssueContent) m.Post("/content", repo.UpdateIssueContent)
@ -515,6 +512,24 @@ func runWeb(ctx *cli.Context) error {
m.Post("", repo.UpdateCommentContent) m.Post("", repo.UpdateCommentContent)
m.Post("/delete", repo.DeleteComment) m.Post("/delete", repo.DeleteComment)
}) })
}, ignSignIn, context.RepoAssignment(true))
m.Group("/:username/:reponame", func() {
m.Group("/wiki", func() {
m.Get("/?:page", repo.Wiki)
m.Get("/_pages", repo.WikiPages)
}, repo.MustEnableWiki, context.RepoRef())
}, ignSignIn, context.RepoAssignment(false, true))
m.Group("/:username/:reponame", func() {
// FIXME: should use different URLs but mostly same logic for comments of issue and pull reuqest.
// So they can apply their own enable/disable logic on routers.
m.Group("/issues", func() {
m.Group("/:index", func() {
m.Post("/label", repo.UpdateIssueLabel)
m.Post("/milestone", repo.UpdateIssueMilestone)
m.Post("/assignee", repo.UpdateIssueAssignee)
}, reqRepoWriter)
})
m.Group("/labels", func() { m.Group("/labels", func() {
m.Post("/new", bindIgnErr(form.CreateLabel{}), repo.NewLabel) m.Post("/new", bindIgnErr(form.CreateLabel{}), repo.NewLabel)
m.Post("/edit", bindIgnErr(form.CreateLabel{}), repo.UpdateLabel) m.Post("/edit", bindIgnErr(form.CreateLabel{}), repo.UpdateLabel)
@ -580,8 +595,8 @@ func runWeb(ctx *cli.Context) error {
m.Group("/:username/:reponame", func() { m.Group("/:username/:reponame", func() {
m.Group("", func() { m.Group("", func() {
m.Get("/releases", repo.MustBeNotBare, repo.Releases) m.Get("/releases", repo.MustBeNotBare, repo.Releases)
m.Get("/^:type(issues|pulls)$", repo.RetrieveLabels, repo.Issues) m.Get("/pulls", repo.RetrieveLabels, repo.Pulls)
m.Get("/^:type(issues|pulls)$/:index", repo.ViewIssue) m.Get("/pulls/:index", repo.ViewPull)
m.Get("/labels/", repo.RetrieveLabels, repo.Labels) m.Get("/labels/", repo.RetrieveLabels, repo.Labels)
m.Get("/milestones", repo.Milestones) m.Get("/milestones", repo.Milestones)
}, context.RepoRef()) }, context.RepoRef())
@ -595,9 +610,6 @@ func runWeb(ctx *cli.Context) error {
}) })
m.Group("/wiki", func() { m.Group("/wiki", func() {
m.Get("/?:page", repo.Wiki)
m.Get("/_pages", repo.WikiPages)
m.Group("", func() { m.Group("", func() {
m.Combo("/_new").Get(repo.NewWiki). m.Combo("/_new").Get(repo.NewWiki).
Post(bindIgnErr(form.NewWiki{}), repo.NewWikiPost) Post(bindIgnErr(form.NewWiki{}), repo.NewWikiPost)

2
conf/locale/locale_en-US.ini

@ -690,11 +690,13 @@ settings.change_reponame_prompt = This change will affect how links relate to th
settings.advanced_settings = Advanced Settings settings.advanced_settings = Advanced Settings
settings.wiki_desc = Enable wiki system settings.wiki_desc = Enable wiki system
settings.use_internal_wiki = Use builtin wiki settings.use_internal_wiki = Use builtin wiki
settings.allow_public_wiki_desc = Allow public access to wiki when repository is private
settings.use_external_wiki = Use external wiki settings.use_external_wiki = Use external wiki
settings.external_wiki_url = External Wiki URL settings.external_wiki_url = External Wiki URL
settings.external_wiki_url_desc = Visitors will be redirected to URL when they click on the tab. settings.external_wiki_url_desc = Visitors will be redirected to URL when they click on the tab.
settings.issues_desc = Enable issue tracker settings.issues_desc = Enable issue tracker
settings.use_internal_issue_tracker = Use builtin lightweight issue tracker settings.use_internal_issue_tracker = Use builtin lightweight issue tracker
settings.allow_public_issues_desc = Allow public access to issues when repository is private
settings.use_external_issue_tracker = Use external issue tracker settings.use_external_issue_tracker = Use external issue tracker
settings.external_tracker_url = External Issue Tracker URL settings.external_tracker_url = External Issue Tracker URL
settings.external_tracker_url_desc = Visitors will be redirected to URL when they click on the tab. settings.external_tracker_url_desc = Visitors will be redirected to URL when they click on the tab.

2
gogs.go

@ -16,7 +16,7 @@ import (
"github.com/gogits/gogs/modules/setting" "github.com/gogits/gogs/modules/setting"
) )
const APP_VER = "0.10.29.0324" const APP_VER = "0.10.30.0324"
func init() { func init() {
setting.AppVer = APP_VER setting.AppVer = APP_VER

21
models/repo.go

@ -173,9 +173,11 @@ type Repository struct {
// Advanced settings // Advanced settings
EnableWiki bool `xorm:"NOT NULL DEFAULT true"` EnableWiki bool `xorm:"NOT NULL DEFAULT true"`
AllowPublicWiki bool
EnableExternalWiki bool EnableExternalWiki bool
ExternalWikiURL string ExternalWikiURL string
EnableIssues bool `xorm:"NOT NULL DEFAULT true"` EnableIssues bool `xorm:"NOT NULL DEFAULT true"`
AllowPublicIssues bool
EnableExternalTracker bool EnableExternalTracker bool
ExternalTrackerURL string ExternalTrackerURL string
ExternalTrackerFormat string ExternalTrackerFormat string
@ -253,10 +255,21 @@ func (repo *Repository) LoadAttributes() error {
return repo.loadAttributes(x) return repo.loadAttributes(x)
} }
// MustOwner always returns a valid *User object to avoid // IsPartialPublic returns true if repository is public or allow public access to wiki or issues.
// conceptually impossible error handling. func (repo *Repository) IsPartialPublic() bool {
// It creates a fake object that contains error deftail return !repo.IsPrivate || repo.AllowPublicWiki || repo.AllowPublicIssues
// when error occurs. }
func (repo *Repository) CanGuestViewWiki() bool {
return repo.IsPartialPublic() && repo.EnableWiki && !repo.EnableExternalWiki && repo.AllowPublicWiki
}
func (repo *Repository) CanGuestViewIssues() bool {
return repo.IsPartialPublic() && repo.EnableIssues && !repo.EnableExternalTracker && repo.AllowPublicIssues
}
// MustOwner always returns a valid *User object to avoid conceptually impossible error handling.
// It creates a fake object that contains error deftail when error occurs.
func (repo *Repository) MustOwner() *User { func (repo *Repository) MustOwner() *User {
return repo.mustOwner(x) return repo.mustOwner(x)
} }

4
modules/bindata/bindata.go

File diff suppressed because one or more lines are too long

74
modules/context/repo.go

@ -126,13 +126,24 @@ func earlyResponseForGoGetMeta(ctx *Context) {
}))) })))
} }
func RepoAssignment() macaron.Handler { // [0]: issues, [1]: wiki
func RepoAssignment(pages ...bool) macaron.Handler {
return func(ctx *Context) { return func(ctx *Context) {
var ( var (
owner *models.User owner *models.User
err error err error
isIssuesPage bool
isWikiPage bool
) )
if len(pages) > 0 {
isIssuesPage = pages[0]
}
if len(pages) > 1 {
isWikiPage = pages[1]
}
_, _ = isIssuesPage, isWikiPage
ownerName := ctx.Params(":username") ownerName := ctx.Params(":username")
repoName := strings.TrimSuffix(ctx.Params(":reponame"), ".git") repoName := strings.TrimSuffix(ctx.Params(":reponame"), ".git")
refName := ctx.Params(":branchname") refName := ctx.Params(":branchname")
@ -174,20 +185,20 @@ func RepoAssignment() macaron.Handler {
ctx.Handle(500, "GetRepositoryByName", err) ctx.Handle(500, "GetRepositoryByName", err)
} }
return return
} else if err = repo.GetOwner(); err != nil {
ctx.Handle(500, "GetOwner", err)
return
} }
ctx.Repo.Repository = repo
ctx.Data["RepoName"] = ctx.Repo.Repository.Name
ctx.Data["IsBareRepo"] = ctx.Repo.Repository.IsBare
ctx.Repo.RepoLink = repo.Link()
ctx.Data["RepoLink"] = ctx.Repo.RepoLink
ctx.Data["RepoRelPath"] = ctx.Repo.Owner.Name + "/" + ctx.Repo.Repository.Name
// Admin has super access. // Admin has super access.
if ctx.IsSigned && ctx.User.IsAdmin { if ctx.IsSigned && ctx.User.IsAdmin {
ctx.Repo.AccessMode = models.ACCESS_MODE_OWNER ctx.Repo.AccessMode = models.ACCESS_MODE_OWNER
} else { } else {
var userID int64 mode, err := models.AccessLevel(ctx.UserID(), repo)
if ctx.IsSigned {
userID = ctx.User.ID
}
mode, err := models.AccessLevel(userID, repo)
if err != nil { if err != nil {
ctx.Handle(500, "AccessLevel", err) ctx.Handle(500, "AccessLevel", err)
return return
@ -195,16 +206,40 @@ func RepoAssignment() macaron.Handler {
ctx.Repo.AccessMode = mode ctx.Repo.AccessMode = mode
} }
// Check access. // Check access
if ctx.Repo.AccessMode == models.ACCESS_MODE_NONE { if ctx.Repo.AccessMode == models.ACCESS_MODE_NONE {
if ctx.Query("go-get") == "1" { if ctx.Query("go-get") == "1" {
earlyResponseForGoGetMeta(ctx) earlyResponseForGoGetMeta(ctx)
return return
} }
ctx.NotFound()
return // Redirect to any accessible page if not yet on it
if repo.IsPartialPublic() &&
(!(isIssuesPage || isWikiPage) ||
(isIssuesPage && !repo.CanGuestViewIssues()) ||
(isWikiPage && !repo.CanGuestViewWiki())) {
switch {
case repo.CanGuestViewIssues():
ctx.Redirect(repo.Link() + "/issues")
case repo.CanGuestViewWiki():
ctx.Redirect(repo.Link() + "/wiki")
default:
ctx.NotFound()
}
return
}
// Response 404 if user is on completely private repository or possible accessible page but owner doesn't enabled
if !repo.IsPartialPublic() ||
(isIssuesPage && !repo.CanGuestViewIssues()) ||
(isWikiPage && !repo.CanGuestViewWiki()) {
ctx.NotFound()
return
}
ctx.Repo.Repository.EnableIssues = repo.CanGuestViewIssues()
ctx.Repo.Repository.EnableWiki = repo.CanGuestViewWiki()
} }
ctx.Data["HasAccess"] = true
if repo.IsMirror { if repo.IsMirror {
ctx.Repo.Mirror, err = models.GetMirrorByRepoID(repo.ID) ctx.Repo.Mirror, err = models.GetMirrorByRepoID(repo.ID)
@ -217,19 +252,12 @@ func RepoAssignment() macaron.Handler {
ctx.Data["Mirror"] = ctx.Repo.Mirror ctx.Data["Mirror"] = ctx.Repo.Mirror
} }
ctx.Repo.Repository = repo
ctx.Data["RepoName"] = ctx.Repo.Repository.Name
ctx.Data["IsBareRepo"] = ctx.Repo.Repository.IsBare
gitRepo, err := git.OpenRepository(models.RepoPath(ownerName, repoName)) gitRepo, err := git.OpenRepository(models.RepoPath(ownerName, repoName))
if err != nil { if err != nil {
ctx.Handle(500, "RepoAssignment Invalid repo "+models.RepoPath(ownerName, repoName), err) ctx.Handle(500, "RepoAssignment Invalid repo "+models.RepoPath(ownerName, repoName), err)
return return
} }
ctx.Repo.GitRepo = gitRepo ctx.Repo.GitRepo = gitRepo
ctx.Repo.RepoLink = repo.Link()
ctx.Data["RepoLink"] = ctx.Repo.RepoLink
ctx.Data["RepoRelPath"] = ctx.Repo.Owner.Name + "/" + ctx.Repo.Repository.Name
tags, err := ctx.Repo.GitRepo.GetTags() tags, err := ctx.Repo.GitRepo.GetTags()
if err != nil { if err != nil {
@ -288,6 +316,8 @@ func RepoAssignment() macaron.Handler {
ctx.Data["GoDocDirectory"] = prefix + "{/dir}" ctx.Data["GoDocDirectory"] = prefix + "{/dir}"
ctx.Data["GoDocFile"] = prefix + "{/dir}/{file}#L{line}" ctx.Data["GoDocFile"] = prefix + "{/dir}/{file}#L{line}"
} }
ctx.Data["IsGuest"] = !ctx.Repo.HasAccess()
} }
} }

2
modules/form/repo.go

@ -92,9 +92,11 @@ type RepoSetting struct {
// Advanced settings // Advanced settings
EnableWiki bool EnableWiki bool
AllowPublicWiki bool
EnableExternalWiki bool EnableExternalWiki bool
ExternalWikiURL string ExternalWikiURL string
EnableIssues bool EnableIssues bool
AllowPublicIssues bool
EnableExternalTracker bool EnableExternalTracker bool
ExternalTrackerURL string ExternalTrackerURL string
TrackerURLFormat string TrackerURLFormat string

3
public/css/gogs.css

@ -2321,6 +2321,9 @@ footer .ui.language .menu {
.repository.wiki.view > .markdown h6:first-of-type { .repository.wiki.view > .markdown h6:first-of-type {
margin-top: 0; margin-top: 0;
} }
.repository.settings.options .box.field {
padding-left: 27px;
}
.repository.settings.collaboration .collaborator.list { .repository.settings.collaboration .collaborator.list {
padding: 0; padding: 0;
} }

9
public/js/gogs.js

@ -265,11 +265,8 @@ function initRepository() {
} }
}); });
$('.enable-system-radio').change(function () { $('.enable-system-radio').change(function () {
if (this.value == 'false') { $($(this).data('enable')).removeClass('disabled');
$($(this).data('target')).addClass('disabled'); $($(this).data('disable')).addClass('disabled');
} else if (this.value == 'true') {
$($(this).data('target')).removeClass('disabled');
}
}); });
} }
@ -1289,7 +1286,7 @@ $(document).ready(function () {
$this.data('url', url); $this.data('url', url);
$this.removeClass('disabled'); $this.removeClass('disabled');
} else { } else {
$this.remove(); $this.remove();
} }
}); });
}); });

6
public/less/_repository.less

@ -1325,6 +1325,12 @@
} }
&.settings { &.settings {
&.options {
.box.field {
padding-left: 27px;
}
}
&.collaboration { &.collaboration {
.collaborator.list { .collaborator.list {
padding: 0; padding: 0;

46
routers/repo/issue.go

@ -89,8 +89,7 @@ func RetrieveLabels(ctx *context.Context) {
ctx.Data["NumLabels"] = len(labels) ctx.Data["NumLabels"] = len(labels)
} }
func Issues(ctx *context.Context) { func issues(ctx *context.Context, isPullList bool) {
isPullList := ctx.Params(":type") == "pulls"
if isPullList { if isPullList {
MustAllowPulls(ctx) MustAllowPulls(ctx)
if ctx.Written() { if ctx.Written() {
@ -247,6 +246,14 @@ func Issues(ctx *context.Context) {
ctx.HTML(200, ISSUES) ctx.HTML(200, ISSUES)
} }
func Issues(ctx *context.Context) {
issues(ctx, false)
}
func Pulls(ctx *context.Context) {
issues(ctx, true)
}
func renderAttachmentSettings(ctx *context.Context) { func renderAttachmentSettings(ctx *context.Context) {
ctx.Data["RequireDropzone"] = true ctx.Data["RequireDropzone"] = true
ctx.Data["IsAttachmentEnabled"] = setting.AttachmentEnabled ctx.Data["IsAttachmentEnabled"] = setting.AttachmentEnabled
@ -492,7 +499,7 @@ func UploadIssueAttachment(ctx *context.Context) {
uploadAttachment(ctx, strings.Split(setting.AttachmentAllowedTypes, ",")) uploadAttachment(ctx, strings.Split(setting.AttachmentAllowedTypes, ","))
} }
func ViewIssue(ctx *context.Context) { func viewIssue(ctx *context.Context, isPullList bool) {
ctx.Data["RequireHighlightJS"] = true ctx.Data["RequireHighlightJS"] = true
ctx.Data["RequireDropzone"] = true ctx.Data["RequireDropzone"] = true
renderAttachmentSettings(ctx) renderAttachmentSettings(ctx)
@ -511,10 +518,10 @@ func ViewIssue(ctx *context.Context) {
ctx.Data["Title"] = issue.Title ctx.Data["Title"] = issue.Title
// Make sure type and URL matches. // Make sure type and URL matches.
if ctx.Params(":type") == "issues" && issue.IsPull { if !isPullList && issue.IsPull {
ctx.Redirect(ctx.Repo.RepoLink + "/pulls/" + com.ToStr(issue.Index)) ctx.Redirect(ctx.Repo.RepoLink + "/pulls/" + com.ToStr(issue.Index))
return return
} else if ctx.Params(":type") == "pulls" && !issue.IsPull { } else if isPullList && !issue.IsPull {
ctx.Redirect(ctx.Repo.RepoLink + "/issues/" + com.ToStr(issue.Index)) ctx.Redirect(ctx.Repo.RepoLink + "/issues/" + com.ToStr(issue.Index))
return return
} }
@ -652,12 +659,27 @@ func ViewIssue(ctx *context.Context) {
ctx.HTML(200, ISSUE_VIEW) ctx.HTML(200, ISSUE_VIEW)
} }
func ViewIssue(ctx *context.Context) {
viewIssue(ctx, false)
}
func ViewPull(ctx *context.Context) {
viewIssue(ctx, true)
}
func getActionIssue(ctx *context.Context) *models.Issue { func getActionIssue(ctx *context.Context) *models.Issue {
issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index"))
if err != nil { if err != nil {
ctx.NotFoundOrServerError("GetIssueByIndex", errors.IsIssueNotExist, err) ctx.NotFoundOrServerError("GetIssueByIndex", errors.IsIssueNotExist, err)
return nil return nil
} }
// Prevent guests accessing pull requests
if !ctx.Repo.HasAccess() && issue.IsPull {
ctx.NotFound()
return nil
}
return issue return issue
} }
@ -803,9 +825,8 @@ func UpdateIssueAssignee(ctx *context.Context) {
} }
func NewComment(ctx *context.Context, f form.CreateComment) { func NewComment(ctx *context.Context, f form.CreateComment) {
issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) issue := getActionIssue(ctx)
if err != nil { if ctx.Written() {
ctx.NotFoundOrServerError("GetIssueByIndex", errors.IsIssueNotExist, err)
return return
} }
@ -820,6 +841,7 @@ func NewComment(ctx *context.Context, f form.CreateComment) {
return return
} }
var err error
var comment *models.Comment var comment *models.Comment
defer func() { defer func() {
// Check if issue admin/poster changes the status of issue. // Check if issue admin/poster changes the status of issue.
@ -895,8 +917,8 @@ func UpdateCommentContent(ctx *context.Context) {
return return
} }
if !ctx.IsSigned || (ctx.User.ID != comment.PosterID && !ctx.Repo.IsAdmin()) { if ctx.UserID() != comment.PosterID && !ctx.Repo.IsAdmin() {
ctx.Error(403) ctx.Error(404)
return return
} else if comment.Type != models.COMMENT_TYPE_COMMENT { } else if comment.Type != models.COMMENT_TYPE_COMMENT {
ctx.Error(204) ctx.Error(204)
@ -928,8 +950,8 @@ func DeleteComment(ctx *context.Context) {
return return
} }
if !ctx.IsSigned || (ctx.User.ID != comment.PosterID && !ctx.Repo.IsAdmin()) { if ctx.UserID() != comment.PosterID && !ctx.Repo.IsAdmin() {
ctx.Error(403) ctx.Error(404)
return return
} else if comment.Type != models.COMMENT_TYPE_COMMENT { } else if comment.Type != models.COMMENT_TYPE_COMMENT {
ctx.Error(204) ctx.Error(204)

2
routers/repo/setting.go

@ -138,9 +138,11 @@ func SettingsPost(ctx *context.Context, f form.RepoSetting) {
case "advanced": case "advanced":
repo.EnableWiki = f.EnableWiki repo.EnableWiki = f.EnableWiki
repo.AllowPublicWiki = f.AllowPublicWiki
repo.EnableExternalWiki = f.EnableExternalWiki repo.EnableExternalWiki = f.EnableExternalWiki
repo.ExternalWikiURL = f.ExternalWikiURL repo.ExternalWikiURL = f.ExternalWikiURL
repo.EnableIssues = f.EnableIssues repo.EnableIssues = f.EnableIssues
repo.AllowPublicIssues = f.AllowPublicIssues
repo.EnableExternalTracker = f.EnableExternalTracker repo.EnableExternalTracker = f.EnableExternalTracker
repo.ExternalTrackerURL = f.ExternalTrackerURL repo.ExternalTrackerURL = f.ExternalTrackerURL
repo.ExternalTrackerFormat = f.TrackerURLFormat repo.ExternalTrackerFormat = f.TrackerURLFormat

2
templates/.VERSION

@ -1 +1 @@
0.10.29.0324 0.10.30.0324

60
templates/repo/header.tmpl

@ -13,34 +13,36 @@
{{if .IsFork}}<div class="fork-flag">{{$.i18n.Tr "repo.forked_from"}} <a href="{{.BaseRepo.Link}}">{{SubStr .BaseRepo.RelLink 1 -1}}</a></div>{{end}} {{if .IsFork}}<div class="fork-flag">{{$.i18n.Tr "repo.forked_from"}} <a href="{{.BaseRepo.Link}}">{{SubStr .BaseRepo.RelLink 1 -1}}</a></div>{{end}}
</div> </div>
<div class="ui right"> {{if not $.IsGuest}}
<div class="ui labeled button" tabindex="0"> <div class="ui right">
<a class="ui basic button" href="{{$.RepoLink}}/action/{{if $.IsWatchingRepo}}un{{end}}watch?redirect_to={{$.Link}}">
<i class="icon fa-eye{{if not $.IsWatchingRepo}}-slash{{end}}"></i>{{if $.IsWatchingRepo}}{{$.i18n.Tr "repo.unwatch"}}{{else}}{{$.i18n.Tr "repo.watch"}}{{end}}
</a>
<a class="ui basic label" href="{{.Link}}/watchers">
{{.NumWatches}}
</a>
</div>
<div class="ui labeled button" tabindex="0">
<a class="ui basic button" href="{{$.RepoLink}}/action/{{if $.IsStaringRepo}}un{{end}}star?redirect_to={{$.Link}}">
<i class="icon fa-star{{if not $.IsStaringRepo}}-o{{end}}"></i>{{if $.IsStaringRepo}}{{$.i18n.Tr "repo.unstar"}}{{else}}{{$.i18n.Tr "repo.star"}}{{end}}
</a>
<a class="ui basic label" href="{{.Link}}/stars">
{{.NumStars}}
</a>
</div>
{{if .CanBeForked}}
<div class="ui labeled button" tabindex="0"> <div class="ui labeled button" tabindex="0">
<a class="ui basic button {{if eq .OwnerID $.SignedUserID}}poping up{{end}}" href="{{AppSubUrl}}/repo/fork/{{.ID}}"> <a class="ui basic button" href="{{$.RepoLink}}/action/{{if $.IsWatchingRepo}}un{{end}}watch?redirect_to={{$.Link}}">
<i class="octicon octicon-repo-forked"></i>{{$.i18n.Tr "repo.fork"}} <i class="icon fa-eye{{if not $.IsWatchingRepo}}-slash{{end}}"></i>{{if $.IsWatchingRepo}}{{$.i18n.Tr "repo.unwatch"}}{{else}}{{$.i18n.Tr "repo.watch"}}{{end}}
</a> </a>
<a class="ui basic label" href="{{.Link}}/forks"> <a class="ui basic label" href="{{.Link}}/watchers">
{{.NumForks}} {{.NumWatches}}
</a> </a>
</div> </div>
{{end}} <div class="ui labeled button" tabindex="0">
</div> <a class="ui basic button" href="{{$.RepoLink}}/action/{{if $.IsStaringRepo}}un{{end}}star?redirect_to={{$.Link}}">
<i class="icon fa-star{{if not $.IsStaringRepo}}-o{{end}}"></i>{{if $.IsStaringRepo}}{{$.i18n.Tr "repo.unstar"}}{{else}}{{$.i18n.Tr "repo.star"}}{{end}}
</a>
<a class="ui basic label" href="{{.Link}}/stars">
{{.NumStars}}
</a>
</div>
{{if .CanBeForked}}
<div class="ui labeled button" tabindex="0">
<a class="ui basic button {{if eq .OwnerID $.SignedUserID}}poping up{{end}}" href="{{AppSubUrl}}/repo/fork/{{.ID}}">
<i class="octicon octicon-repo-forked"></i>{{$.i18n.Tr "repo.fork"}}
</a>
<a class="ui basic label" href="{{.Link}}/forks">
{{.NumForks}}
</a>
</div>
{{end}}
</div>
{{end}}
</div> </div>
</div><!-- end column --> </div><!-- end column -->
</div><!-- end grid --> </div><!-- end grid -->
@ -49,15 +51,17 @@
{{if not .IsDiffCompare}} {{if not .IsDiffCompare}}
<div class="ui tabs container"> <div class="ui tabs container">
<div class="ui tabular menu navbar"> <div class="ui tabular menu navbar">
<a class="{{if .PageIsViewFiles}}active{{end}} item" href="{{.RepoLink}}"> {{if not $.IsGuest}}
<i class="octicon octicon-file-text"></i> {{.i18n.Tr "repo.files"}} <a class="{{if .PageIsViewFiles}}active{{end}} item" href="{{.RepoLink}}">
</a> <i class="octicon octicon-file-text"></i> {{.i18n.Tr "repo.files"}}
</a>
{{end}}
{{if .Repository.EnableIssues}} {{if .Repository.EnableIssues}}
<a class="{{if .PageIsIssueList}}active{{end}} item" href="{{.RepoLink}}/issues"> <a class="{{if .PageIsIssueList}}active{{end}} item" href="{{.RepoLink}}/issues">
<i class="octicon octicon-issue-opened"></i> {{.i18n.Tr "repo.issues"}} {{if not .Repository.EnableExternalTracker}}<span class="ui {{if not .Repository.NumOpenIssues}}gray{{else}}blue{{end}} small label">{{.Repository.NumOpenIssues}}{{end}}</span> <i class="octicon octicon-issue-opened"></i> {{.i18n.Tr "repo.issues"}} {{if not .Repository.EnableExternalTracker}}<span class="ui {{if not .Repository.NumOpenIssues}}gray{{else}}blue{{end}} small label">{{.Repository.NumOpenIssues}}{{end}}</span>
</a> </a>
{{end}} {{end}}
{{if .Repository.AllowsPulls}} {{if and .Repository.AllowsPulls (not .IsGuest)}}
<a class="{{if .PageIsPullList}}active{{end}} item" href="{{.RepoLink}}/pulls"> <a class="{{if .PageIsPullList}}active{{end}} item" href="{{.RepoLink}}/pulls">
<i class="octicon octicon-git-pull-request"></i> {{.i18n.Tr "repo.pulls"}} <span class="ui {{if not .Repository.NumOpenPulls}}gray{{else}}blue{{end}} small label">{{.Repository.NumOpenPulls}}</span> <i class="octicon octicon-git-pull-request"></i> {{.i18n.Tr "repo.pulls"}} <span class="ui {{if not .Repository.NumOpenPulls}}gray{{else}}blue{{end}} small label">{{.Repository.NumOpenPulls}}</span>
</a> </a>

39
templates/repo/settings/options.tmpl

@ -15,7 +15,7 @@
<input type="hidden" name="action" value="update"> <input type="hidden" name="action" value="update">
<div class="required field {{if .Err_RepoName}}error{{end}}"> <div class="required field {{if .Err_RepoName}}error{{end}}">
<label for="repo_name">{{.i18n.Tr "repo.repo_name"}}<span class="text red hide" id="repo-name-change-prompt"> {{.i18n.Tr "repo.settings.change_reponame_prompt"}}</span></label> <label for="repo_name">{{.i18n.Tr "repo.repo_name"}}<span class="text red hide" id="repo-name-change-prompt"> {{.i18n.Tr "repo.settings.change_reponame_prompt"}}</span></label>
<input id="repo_name" name="repo_name" value="{{.Repository.Name}}" data-repo-name="{{.Repository.Name}}" autofocus required> <input id="repo_name" name="repo_name" value="{{.Repository.Name}}" data-repo-name="{{.Repository.Name}}" required>
</div> </div>
<div class="field {{if .Err_Description}}error{{end}}"> <div class="field {{if .Err_Description}}error{{end}}">
<label for="description">{{$.i18n.Tr "repo.repo_desc"}}</label> <label for="description">{{$.i18n.Tr "repo.repo_desc"}}</label>
@ -96,6 +96,7 @@
{{.CsrfTokenHtml}} {{.CsrfTokenHtml}}
<input type="hidden" name="action" value="advanced"> <input type="hidden" name="action" value="advanced">
<!-- Wiki -->
<div class="inline field"> <div class="inline field">
<label>{{.i18n.Tr "repo.wiki"}}</label> <label>{{.i18n.Tr "repo.wiki"}}</label>
<div class="ui checkbox"> <div class="ui checkbox">
@ -103,28 +104,34 @@
<label>{{.i18n.Tr "repo.settings.wiki_desc"}}</label> <label>{{.i18n.Tr "repo.settings.wiki_desc"}}</label>
</div> </div>
</div> </div>
<div class="field {{if not .Repository.EnableWiki}}disabled{{end}}" id="wiki_box"> <div class="ui segment field {{if not .Repository.EnableWiki}}disabled{{end}}" id="wiki_box">
<div class="field"> <div class="field">
<div class="ui radio checkbox"> <div class="ui radio checkbox">
<input class="hidden enable-system-radio" tabindex="0" name="enable_external_wiki" type="radio" value="false" data-target="#external_wiki_box" {{if not .Repository.EnableExternalWiki}}checked{{end}}/> <input class="hidden enable-system-radio" tabindex="0" name="enable_external_wiki" type="radio" value="false" data-enable="#internal_wiki_box" data-disable="#external_wiki_box" {{if not .Repository.EnableExternalWiki}}checked{{end}}/>
<label>{{.i18n.Tr "repo.settings.use_internal_wiki"}}</label> <label>{{.i18n.Tr "repo.settings.use_internal_wiki"}}</label>
</div> </div>
</div> </div>
<div class="box field {{if .Repository.EnableExternalWiki}}disabled{{end}}" id="internal_wiki_box">
<div class="ui checkbox">
<input name="allow_public_wiki" type="checkbox" {{if .Repository.AllowPublicWiki}}checked{{end}}>
<label>{{.i18n.Tr "repo.settings.allow_public_wiki_desc"}}</label>
</div>
</div>
<div class="field"> <div class="field">
<div class="ui radio checkbox"> <div class="ui radio checkbox">
<input class="hidden enable-system-radio" tabindex="0" name="enable_external_wiki" type="radio" value="true" data-target="#external_wiki_box" {{if .Repository.EnableExternalWiki}}checked{{end}}/> <input class="hidden enable-system-radio" tabindex="0" name="enable_external_wiki" type="radio" value="true" data-enable="#external_wiki_box" data-disable="#internal_wiki_box" {{if .Repository.EnableExternalWiki}}checked{{end}}/>
<label>{{.i18n.Tr "repo.settings.use_external_wiki"}}</label> <label>{{.i18n.Tr "repo.settings.use_external_wiki"}}</label>
</div> </div>
</div> </div>
<div class="field {{if not .Repository.EnableExternalWiki}}disabled{{end}}" id="external_wiki_box"> <div class="box field {{if not .Repository.EnableExternalWiki}}disabled{{end}}" id="external_wiki_box">
<label for="external_wiki_url">{{.i18n.Tr "repo.settings.external_wiki_url"}}</label> <label for="external_wiki_url">{{.i18n.Tr "repo.settings.external_wiki_url"}}</label>
<input id="external_wiki_url" name="external_wiki_url" type="url" value="{{.Repository.ExternalWikiURL}}"> <input id="external_wiki_url" name="external_wiki_url" type="url" value="{{.Repository.ExternalWikiURL}}">
<p class="help">{{.i18n.Tr "repo.settings.external_wiki_url_desc"}}</p> <p class="help">{{.i18n.Tr "repo.settings.external_wiki_url_desc"}}</p>
</div> </div>
</div> </div>
<div class="ui divider"></div> <!-- Issues -->
<div class="inline field"> <div class="inline field">
<label>{{.i18n.Tr "repo.issues"}}</label> <label>{{.i18n.Tr "repo.issues"}}</label>
<div class="ui checkbox"> <div class="ui checkbox">
@ -132,20 +139,27 @@
<label>{{.i18n.Tr "repo.settings.issues_desc"}}</label> <label>{{.i18n.Tr "repo.settings.issues_desc"}}</label>
</div> </div>
</div> </div>
<div class="field {{if not .Repository.EnableIssues}}disabled{{end}}" id="issue_box"> <div class="ui segment field {{if not .Repository.EnableIssues}}disabled{{end}}" id="issue_box">
<div class="field"> <div class="field">
<div class="ui radio checkbox"> <div class="ui radio checkbox">
<input class="hidden enable-system-radio" tabindex="0" name="enable_external_tracker" type="radio" value="false" data-target="#external_issue_box" {{if not .Repository.EnableExternalTracker}}checked{{end}}/> <input class="hidden enable-system-radio" tabindex="0" name="enable_external_tracker" type="radio" value="false" data-enable="#internal_issue_box" data-disable="#external_issue_box" {{if not .Repository.EnableExternalTracker}}checked{{end}}/>
<label>{{.i18n.Tr "repo.settings.use_internal_issue_tracker"}}</label> <label>{{.i18n.Tr "repo.settings.use_internal_issue_tracker"}}</label>
</div> </div>
</div> </div>
<div class="box field {{if .Repository.EnableExternalTracker}}disabled{{end}}" id="internal_issue_box">
<div class="ui checkbox">
<input name="allow_public_issues" type="checkbox" {{if .Repository.AllowPublicIssues}}checked{{end}}>
<label>{{.i18n.Tr "repo.settings.allow_public_issues_desc"}}</label>
</div>
</div>
<div class="field"> <div class="field">
<div class="ui radio checkbox"> <div class="ui radio checkbox">
<input class="hidden enable-system-radio" tabindex="0" name="enable_external_tracker" type="radio" value="true" data-target="#external_issue_box" {{if .Repository.EnableExternalTracker}}checked{{end}}/> <input class="hidden enable-system-radio" tabindex="0" name="enable_external_tracker" type="radio" value="true" data-enable="#external_issue_box" data-disable="#internal_issue_box" {{if .Repository.EnableExternalTracker}}checked{{end}}/>
<label>{{.i18n.Tr "repo.settings.use_external_issue_tracker"}}</label> <label>{{.i18n.Tr "repo.settings.use_external_issue_tracker"}}</label>
</div> </div>
</div> </div>
<div class="field {{if not .Repository.EnableExternalTracker}}disabled{{end}}" id="external_issue_box"> <div class="box field {{if not .Repository.EnableExternalTracker}}disabled{{end}}" id="external_issue_box">
<div class="field"> <div class="field">
<label for="external_tracker_url">{{.i18n.Tr "repo.settings.external_tracker_url"}}</label> <label for="external_tracker_url">{{.i18n.Tr "repo.settings.external_tracker_url"}}</label>
<input id="external_tracker_url" name="external_tracker_url" type="url" value="{{.Repository.ExternalTrackerURL}}"> <input id="external_tracker_url" name="external_tracker_url" type="url" value="{{.Repository.ExternalTrackerURL}}">
@ -174,9 +188,8 @@
</div> </div>
</div> </div>
<!-- Pull Requests -->
{{if .Repository.CanEnablePulls}} {{if .Repository.CanEnablePulls}}
<div class="ui divider"></div>
<div class="inline field"> <div class="inline field">
<label>{{.i18n.Tr "repo.pulls"}}</label> <label>{{.i18n.Tr "repo.pulls"}}</label>
<div class="ui checkbox"> <div class="ui checkbox">

Loading…
Cancel
Save