@@ -378,6 +378,7 @@ func runWeb(ctx *cli.Context) { | |||||
} | } | ||||
reqRepoAdmin := middleware.RequireRepoAdmin() | reqRepoAdmin := middleware.RequireRepoAdmin() | ||||
reqRepoPusher := middleware.RequireRepoPusher() | |||||
// ***** START: Organization ***** | // ***** START: Organization ***** | ||||
m.Group("/org", func() { | m.Group("/org", func() { | ||||
@@ -534,13 +535,14 @@ func runWeb(ctx *cli.Context) { | |||||
m.Group("/wiki", func() { | m.Group("/wiki", func() { | ||||
m.Get("/?:page", repo.Wiki) | m.Get("/?:page", repo.Wiki) | ||||
m.Get("/_list", repo.WikiList) | |||||
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(auth.NewWikiForm{}), repo.NewWikiPost) | Post(bindIgnErr(auth.NewWikiForm{}), repo.NewWikiPost) | ||||
m.Get("/:page/_edit", repo.EditWiki) | |||||
}, reqSignIn) | |||||
m.Combo("/:page/_edit").Get(repo.EditWiki). | |||||
Post(bindIgnErr(auth.NewWikiForm{}), repo.EditWikiPost) | |||||
}, reqSignIn, reqRepoPusher) | |||||
}, middleware.RepoRef()) | }, middleware.RepoRef()) | ||||
m.Get("/archive/*", repo.Download) | m.Get("/archive/*", repo.Download) | ||||
@@ -539,10 +539,15 @@ wiki = Wiki | |||||
wiki.welcome = Welcome to Wiki! | wiki.welcome = Welcome to Wiki! | ||||
wiki.welcome_desc = Wiki is the place where you would like to document your project together and make it better. | wiki.welcome_desc = Wiki is the place where you would like to document your project together and make it better. | ||||
wiki.create_first_page = Create the first page | wiki.create_first_page = Create the first page | ||||
wiki.page = Page | |||||
wiki.filter_page = Filter page | |||||
wiki.new_page = Create New Page | wiki.new_page = Create New Page | ||||
wiki.default_commit_message = Write a note about this update (optional). | wiki.default_commit_message = Write a note about this update (optional). | ||||
wiki.save_page = Save Page | wiki.save_page = Save Page | ||||
wiki.last_commit_info = %s edited this page %s | wiki.last_commit_info = %s edited this page %s | ||||
wiki.edit_page_button = Edit | |||||
wiki.new_page_button = New Page | |||||
wiki.page_already_exists = Wiki page with same name already exists. | |||||
settings = Settings | settings = Settings | ||||
settings.options = Options | settings.options = Options | ||||
@@ -107,6 +107,26 @@ func (err ErrUserHasOrgs) Error() string { | |||||
return fmt.Sprintf("user still has membership of organizations [uid: %d]", err.UID) | return fmt.Sprintf("user still has membership of organizations [uid: %d]", err.UID) | ||||
} | } | ||||
// __ __.__ __ .__ | |||||
// / \ / \__| | _|__| | |||||
// \ \/\/ / | |/ / | | |||||
// \ /| | <| | | |||||
// \__/\ / |__|__|_ \__| | |||||
// \/ \/ | |||||
type ErrWikiAlreadyExist struct { | |||||
Title string | |||||
} | |||||
func IsErrWikiAlreadyExist(err error) bool { | |||||
_, ok := err.(ErrWikiAlreadyExist) | |||||
return ok | |||||
} | |||||
func (err ErrWikiAlreadyExist) Error() string { | |||||
return fmt.Sprintf("wiki page already exists [title: %s]", err.Title) | |||||
} | |||||
// __________ ___. .__ .__ ____ __. | // __________ ___. .__ .__ ____ __. | ||||
// \______ \__ _\_ |__ | | |__| ____ | |/ _|____ ___.__. | // \______ \__ _\_ |__ | | |__| ____ | |/ _|____ ___.__. | ||||
// | ___/ | \ __ \| | | |/ ___\ | <_/ __ < | | | // | ___/ | \ __ \| | | |/ ___\ | <_/ __ < | | | ||||
@@ -252,7 +252,7 @@ func (pr *PullRequest) testPatch() (err error) { | |||||
// Checkout base branch. | // Checkout base branch. | ||||
_, stderr, err := process.ExecDir(-1, pr.BaseRepo.LocalCopyPath(), | _, stderr, err := process.ExecDir(-1, pr.BaseRepo.LocalCopyPath(), | ||||
fmt.Sprintf("PullRequest.Merge(git checkout): %s", pr.BaseRepo.ID), | |||||
fmt.Sprintf("PullRequest.Merge(git checkout): %v", pr.BaseRepo.ID), | |||||
"git", "checkout", pr.BaseBranch) | "git", "checkout", pr.BaseBranch) | ||||
if err != nil { | if err != nil { | ||||
return fmt.Errorf("git checkout: %s", stderr) | return fmt.Errorf("git checkout: %s", stderr) | ||||
@@ -7,6 +7,7 @@ package models | |||||
import ( | import ( | ||||
"fmt" | "fmt" | ||||
"io/ioutil" | "io/ioutil" | ||||
"os" | |||||
"path" | "path" | ||||
"path/filepath" | "path/filepath" | ||||
"strings" | "strings" | ||||
@@ -108,8 +109,8 @@ func (repo *Repository) UpdateLocalWiki() error { | |||||
return updateLocalCopy(repo.WikiPath(), repo.LocalWikiPath()) | return updateLocalCopy(repo.WikiPath(), repo.LocalWikiPath()) | ||||
} | } | ||||
// AddWikiPage adds new page to repository wiki. | |||||
func (repo *Repository) AddWikiPage(doer *User, title, content, message string) (err error) { | |||||
// updateWikiPage adds new page to repository wiki. | |||||
func (repo *Repository) updateWikiPage(doer *User, oldTitle, title, content, message string, isNew bool) (err error) { | |||||
wikiWorkingPool.CheckIn(com.ToStr(repo.ID)) | wikiWorkingPool.CheckIn(com.ToStr(repo.ID)) | ||||
defer wikiWorkingPool.CheckOut(com.ToStr(repo.ID)) | defer wikiWorkingPool.CheckOut(com.ToStr(repo.ID)) | ||||
@@ -133,8 +134,18 @@ func (repo *Repository) AddWikiPage(doer *User, title, content, message string) | |||||
return fmt.Errorf("UpdateLocalWiki: %v", err) | return fmt.Errorf("UpdateLocalWiki: %v", err) | ||||
} | } | ||||
title = strings.Replace(title, "/", " ", -1) | |||||
title = ToWikiPageName(strings.Replace(title, "/", " ", -1)) | |||||
filename := path.Join(localPath, title+".md") | filename := path.Join(localPath, title+".md") | ||||
// If not a new file, show perform update not create. | |||||
if isNew { | |||||
if com.IsExist(filename) { | |||||
return ErrWikiAlreadyExist{filename} | |||||
} | |||||
} else { | |||||
os.Remove(path.Join(localPath, oldTitle+".md")) | |||||
} | |||||
if err = ioutil.WriteFile(filename, []byte(content), 0666); err != nil { | if err = ioutil.WriteFile(filename, []byte(content), 0666); err != nil { | ||||
return fmt.Errorf("WriteFile: %v", err) | return fmt.Errorf("WriteFile: %v", err) | ||||
} | } | ||||
@@ -152,3 +163,11 @@ func (repo *Repository) AddWikiPage(doer *User, title, content, message string) | |||||
return nil | return nil | ||||
} | } | ||||
func (repo *Repository) AddWikiPage(doer *User, title, content, message string) error { | |||||
return repo.updateWikiPage(doer, "", title, content, message, true) | |||||
} | |||||
func (repo *Repository) EditWikiPage(doer *User, oldTitle, title, content, message string) error { | |||||
return repo.updateWikiPage(doer, oldTitle, title, content, message, false) | |||||
} |
@@ -246,9 +246,10 @@ func (f *EditReleaseForm) Validate(ctx *macaron.Context, errs binding.Errors) bi | |||||
// \/ \/ | // \/ \/ | ||||
type NewWikiForm struct { | type NewWikiForm struct { | ||||
Title string `binding:"Required"` | |||||
Content string `binding:"Required"` | |||||
Message string | |||||
OldTitle string | |||||
Title string `binding:"Required"` | |||||
Content string `binding:"Required"` | |||||
Message string | |||||
} | } | ||||
// FIXME: use code generation to generate this method. | // FIXME: use code generation to generate this method. | ||||
@@ -59,7 +59,7 @@ type Context struct { | |||||
IsSigned bool | IsSigned bool | ||||
IsBasicAuth bool | IsBasicAuth bool | ||||
Repo RepoContext | |||||
Repo *RepoContext | |||||
Org struct { | Org struct { | ||||
IsOwner bool | IsOwner bool | ||||
@@ -73,17 +73,22 @@ type Context struct { | |||||
} | } | ||||
// IsOwner returns true if current user is the owner of repository. | // IsOwner returns true if current user is the owner of repository. | ||||
func (r RepoContext) IsOwner() bool { | |||||
func (r *RepoContext) IsOwner() bool { | |||||
return r.AccessMode >= models.ACCESS_MODE_OWNER | return r.AccessMode >= models.ACCESS_MODE_OWNER | ||||
} | } | ||||
// IsAdmin returns true if current user has admin or higher access of repository. | // IsAdmin returns true if current user has admin or higher access of repository. | ||||
func (r RepoContext) IsAdmin() bool { | |||||
func (r *RepoContext) IsAdmin() bool { | |||||
return r.AccessMode >= models.ACCESS_MODE_ADMIN | return r.AccessMode >= models.ACCESS_MODE_ADMIN | ||||
} | } | ||||
// IsPusher returns true if current user has write or higher access of repository. | |||||
func (r *RepoContext) IsPusher() bool { | |||||
return r.AccessMode >= models.ACCESS_MODE_WRITE | |||||
} | |||||
// Return if the current user has read access for this repository | // Return if the current user has read access for this repository | ||||
func (r RepoContext) HasAccess() bool { | |||||
func (r *RepoContext) HasAccess() bool { | |||||
return r.AccessMode >= models.ACCESS_MODE_READ | return r.AccessMode >= models.ACCESS_MODE_READ | ||||
} | } | ||||
@@ -6,7 +6,6 @@ package middleware | |||||
import ( | import ( | ||||
"fmt" | "fmt" | ||||
"net/url" | |||||
"path" | "path" | ||||
"strings" | "strings" | ||||
@@ -225,6 +224,8 @@ func RetrieveBaseRepo(ctx *Context, repo *models.Repository) { | |||||
func RepoAssignment(args ...bool) macaron.Handler { | func RepoAssignment(args ...bool) macaron.Handler { | ||||
return func(ctx *Context) { | return func(ctx *Context) { | ||||
ctx.Repo = &RepoContext{} | |||||
var ( | var ( | ||||
displayBare bool // To display bare page if it is a bare repo. | displayBare bool // To display bare page if it is a bare repo. | ||||
) | ) | ||||
@@ -335,6 +336,7 @@ func RepoAssignment(args ...bool) macaron.Handler { | |||||
ctx.Data["Owner"] = ctx.Repo.Repository.Owner | ctx.Data["Owner"] = ctx.Repo.Repository.Owner | ||||
ctx.Data["IsRepositoryOwner"] = ctx.Repo.IsOwner() | ctx.Data["IsRepositoryOwner"] = ctx.Repo.IsOwner() | ||||
ctx.Data["IsRepositoryAdmin"] = ctx.Repo.IsAdmin() | ctx.Data["IsRepositoryAdmin"] = ctx.Repo.IsAdmin() | ||||
ctx.Data["IsRepositoryPusher"] = ctx.Repo.IsPusher() | |||||
ctx.Data["DisableSSH"] = setting.DisableSSH | ctx.Data["DisableSSH"] = setting.DisableSSH | ||||
ctx.Repo.CloneLink, err = repo.CloneLink() | ctx.Repo.CloneLink, err = repo.CloneLink() | ||||
@@ -397,11 +399,15 @@ func RepoAssignment(args ...bool) macaron.Handler { | |||||
func RequireRepoAdmin() macaron.Handler { | func RequireRepoAdmin() macaron.Handler { | ||||
return func(ctx *Context) { | return func(ctx *Context) { | ||||
if !ctx.Repo.IsAdmin() { | if !ctx.Repo.IsAdmin() { | ||||
if !ctx.IsSigned { | |||||
ctx.SetCookie("redirect_to", "/"+url.QueryEscape(setting.AppSubUrl+ctx.Req.RequestURI), 0, setting.AppSubUrl) | |||||
ctx.Redirect(setting.AppSubUrl + "/user/login") | |||||
return | |||||
} | |||||
ctx.Handle(404, ctx.Req.RequestURI, nil) | |||||
return | |||||
} | |||||
} | |||||
} | |||||
func RequireRepoPusher() macaron.Handler { | |||||
return func(ctx *Context) { | |||||
if !ctx.Repo.IsPusher() { | |||||
ctx.Handle(404, ctx.Req.RequestURI, nil) | ctx.Handle(404, ctx.Req.RequestURI, nil) | ||||
return | return | ||||
} | } | ||||
@@ -231,6 +231,11 @@ function initRepository() { | |||||
}); | }); | ||||
} | } | ||||
// Wiki | |||||
if ($('.repository.wiki.view').length > 0) { | |||||
initFilterSearchDropdown('.choose.page .dropdown'); | |||||
} | |||||
// Options | // Options | ||||
if ($('.repository.settings.options').length > 0) { | if ($('.repository.settings.options').length > 0) { | ||||
$('#repo_name').keyup(function () { | $('#repo_name').keyup(function () { | ||||
@@ -314,23 +319,23 @@ function initRepository() { | |||||
$('#edit-title').click(editTitleToggle); | $('#edit-title').click(editTitleToggle); | ||||
$('#cancel-edit-title').click(editTitleToggle); | $('#cancel-edit-title').click(editTitleToggle); | ||||
$('#save-edit-title').click(editTitleToggle). | $('#save-edit-title').click(editTitleToggle). | ||||
click(function () { | |||||
if ($edit_input.val().length == 0 || | |||||
$edit_input.val() == $issue_title.text()) { | |||||
$edit_input.val($issue_title.text()); | |||||
return false; | |||||
} | |||||
click(function () { | |||||
if ($edit_input.val().length == 0 || | |||||
$edit_input.val() == $issue_title.text()) { | |||||
$edit_input.val($issue_title.text()); | |||||
return false; | |||||
} | |||||
$.post($(this).data('update-url'), { | |||||
"_csrf": csrf, | |||||
"title": $edit_input.val() | |||||
}, | |||||
function (data) { | |||||
$edit_input.val(data.title); | |||||
$issue_title.text(data.title); | |||||
}); | |||||
return false; | |||||
}); | |||||
$.post($(this).data('update-url'), { | |||||
"_csrf": csrf, | |||||
"title": $edit_input.val() | |||||
}, | |||||
function (data) { | |||||
$edit_input.val(data.title); | |||||
$issue_title.text(data.title); | |||||
}); | |||||
return false; | |||||
}); | |||||
// Edit issue or comment content | // Edit issue or comment content | ||||
$('.edit-content').click(function () { | $('.edit-content').click(function () { | ||||
@@ -729,9 +734,9 @@ $(document).ready(function () { | |||||
// Show exact time | // Show exact time | ||||
$('.time-since').each(function () { | $('.time-since').each(function () { | ||||
$(this).addClass('poping up'). | $(this).addClass('poping up'). | ||||
attr('data-content', $(this).attr('title')). | |||||
attr('data-variation', 'inverted tiny'). | |||||
attr('title', ''); | |||||
attr('data-content', $(this).attr('title')). | |||||
attr('data-variation', 'inverted tiny'). | |||||
attr('title', ''); | |||||
}); | }); | ||||
// Semantic UI modules. | // Semantic UI modules. | ||||
@@ -6,6 +6,7 @@ package repo | |||||
import ( | import ( | ||||
"io/ioutil" | "io/ioutil" | ||||
"strings" | |||||
"github.com/gogits/git-shell" | "github.com/gogits/git-shell" | ||||
@@ -21,56 +22,97 @@ const ( | |||||
WIKI_NEW base.TplName = "repo/wiki/new" | WIKI_NEW base.TplName = "repo/wiki/new" | ||||
) | ) | ||||
func Wiki(ctx *middleware.Context) { | |||||
ctx.Data["PageIsWiki"] = true | |||||
if !ctx.Repo.Repository.HasWiki() { | |||||
ctx.Data["Title"] = ctx.Tr("repo.wiki") | |||||
ctx.HTML(200, WIKI_START) | |||||
return | |||||
} | |||||
type PageMeta struct { | |||||
Name string | |||||
URL string | |||||
} | |||||
func renderWikiPage(ctx *middleware.Context, isViewPage bool) (*git.Repository, string) { | |||||
wikiRepo, err := git.OpenRepository(ctx.Repo.Repository.WikiPath()) | wikiRepo, err := git.OpenRepository(ctx.Repo.Repository.WikiPath()) | ||||
if err != nil { | if err != nil { | ||||
ctx.Handle(500, "OpenRepository", err) | ctx.Handle(500, "OpenRepository", err) | ||||
return | |||||
return nil, "" | |||||
} | } | ||||
commit, err := wikiRepo.GetCommitOfBranch("master") | commit, err := wikiRepo.GetCommitOfBranch("master") | ||||
if err != nil { | if err != nil { | ||||
ctx.Handle(500, "GetCommitOfBranch", err) | ctx.Handle(500, "GetCommitOfBranch", err) | ||||
return | |||||
return nil, "" | |||||
} | |||||
// Get page list. | |||||
if isViewPage { | |||||
entries, err := commit.ListEntries() | |||||
if err != nil { | |||||
ctx.Handle(500, "ListEntries", err) | |||||
return nil, "" | |||||
} | |||||
pages := make([]PageMeta, len(entries)) | |||||
for i := range entries { | |||||
name := strings.TrimSuffix(entries[i].Name(), ".md") | |||||
pages[i] = PageMeta{ | |||||
Name: name, | |||||
URL: models.ToWikiPageURL(name), | |||||
} | |||||
} | |||||
ctx.Data["Pages"] = pages | |||||
} | } | ||||
page := models.ToWikiPageName(ctx.Params(":page")) | |||||
if len(page) == 0 { | |||||
page = "Home" | |||||
pageURL := ctx.Params(":page") | |||||
if len(pageURL) == 0 { | |||||
pageURL = "Home" | |||||
} | } | ||||
ctx.Data["Title"] = page | |||||
ctx.Data["PageURL"] = pageURL | |||||
pageName := models.ToWikiPageName(pageURL) | |||||
ctx.Data["old_title"] = pageName | |||||
ctx.Data["Title"] = pageName | |||||
ctx.Data["title"] = pageName | |||||
ctx.Data["RequireHighlightJS"] = true | ctx.Data["RequireHighlightJS"] = true | ||||
blob, err := commit.GetBlobByPath(page + ".md") | |||||
blob, err := commit.GetBlobByPath(pageName + ".md") | |||||
if err != nil { | if err != nil { | ||||
if git.IsErrNotExist(err) { | if git.IsErrNotExist(err) { | ||||
ctx.Redirect(ctx.Repo.RepoLink + "/wiki/_list") | |||||
ctx.Redirect(ctx.Repo.RepoLink + "/wiki/_pages") | |||||
} else { | } else { | ||||
ctx.Handle(500, "GetBlobByPath", err) | ctx.Handle(500, "GetBlobByPath", err) | ||||
} | } | ||||
return | |||||
return nil, "" | |||||
} | } | ||||
r, err := blob.Data() | r, err := blob.Data() | ||||
if err != nil { | if err != nil { | ||||
ctx.Handle(500, "Data", err) | ctx.Handle(500, "Data", err) | ||||
return | |||||
return nil, "" | |||||
} | } | ||||
data, err := ioutil.ReadAll(r) | data, err := ioutil.ReadAll(r) | ||||
if err != nil { | if err != nil { | ||||
ctx.Handle(500, "ReadAll", err) | ctx.Handle(500, "ReadAll", err) | ||||
return nil, "" | |||||
} | |||||
if isViewPage { | |||||
ctx.Data["content"] = string(base.RenderMarkdown(data, ctx.Repo.RepoLink)) | |||||
} else { | |||||
ctx.Data["content"] = string(data) | |||||
} | |||||
return wikiRepo, pageName | |||||
} | |||||
func Wiki(ctx *middleware.Context) { | |||||
ctx.Data["PageIsWiki"] = true | |||||
if !ctx.Repo.Repository.HasWiki() { | |||||
ctx.Data["Title"] = ctx.Tr("repo.wiki") | |||||
ctx.HTML(200, WIKI_START) | |||||
return | |||||
} | |||||
wikiRepo, pageName := renderWikiPage(ctx, true) | |||||
if ctx.Written() { | |||||
return | return | ||||
} | } | ||||
ctx.Data["Content"] = string(base.RenderMarkdown(data, ctx.Repo.RepoLink)) | |||||
// Get last change information. | // Get last change information. | ||||
lastCommit, err := wikiRepo.GetCommitByPath(page + ".md") | |||||
lastCommit, err := wikiRepo.GetCommitByPath(pageName + ".md") | |||||
if err != nil { | if err != nil { | ||||
ctx.Handle(500, "GetCommitByPath", err) | ctx.Handle(500, "GetCommitByPath", err) | ||||
return | return | ||||
@@ -80,7 +122,7 @@ func Wiki(ctx *middleware.Context) { | |||||
ctx.HTML(200, WIKI_VIEW) | ctx.HTML(200, WIKI_VIEW) | ||||
} | } | ||||
func WikiList(ctx *middleware.Context) { | |||||
func WikiPages(ctx *middleware.Context) { | |||||
} | } | ||||
@@ -107,7 +149,12 @@ func NewWikiPost(ctx *middleware.Context, form auth.NewWikiForm) { | |||||
} | } | ||||
if err := ctx.Repo.Repository.AddWikiPage(ctx.User, form.Title, form.Content, form.Message); err != nil { | if err := ctx.Repo.Repository.AddWikiPage(ctx.User, form.Title, form.Content, form.Message); err != nil { | ||||
ctx.Handle(500, "AddWikiPage", err) | |||||
if models.IsErrWikiAlreadyExist(err) { | |||||
ctx.Data["Err_Title"] = true | |||||
ctx.RenderWithErr(ctx.Tr("repo.wiki.page_already_exists"), WIKI_NEW, &form) | |||||
} else { | |||||
ctx.Handle(500, "AddWikiPage", err) | |||||
} | |||||
return | return | ||||
} | } | ||||
@@ -115,5 +162,37 @@ func NewWikiPost(ctx *middleware.Context, form auth.NewWikiForm) { | |||||
} | } | ||||
func EditWiki(ctx *middleware.Context) { | func EditWiki(ctx *middleware.Context) { | ||||
ctx.PlainText(200, []byte(ctx.Params(":page"))) | |||||
ctx.Data["PageIsWiki"] = true | |||||
ctx.Data["PageIsWikiEdit"] = true | |||||
ctx.Data["RequireSimpleMDE"] = true | |||||
if !ctx.Repo.Repository.HasWiki() { | |||||
ctx.Redirect(ctx.Repo.RepoLink + "/wiki") | |||||
return | |||||
} | |||||
renderWikiPage(ctx, false) | |||||
if ctx.Written() { | |||||
return | |||||
} | |||||
ctx.HTML(200, WIKI_NEW) | |||||
} | |||||
func EditWikiPost(ctx *middleware.Context, form auth.NewWikiForm) { | |||||
ctx.Data["Title"] = ctx.Tr("repo.wiki.new_page") | |||||
ctx.Data["PageIsWiki"] = true | |||||
ctx.Data["RequireSimpleMDE"] = true | |||||
if ctx.HasError() { | |||||
ctx.HTML(200, WIKI_NEW) | |||||
return | |||||
} | |||||
if err := ctx.Repo.Repository.EditWikiPage(ctx.User, form.OldTitle, form.Title, form.Content, form.Message); err != nil { | |||||
ctx.Handle(500, "EditWikiPage", err) | |||||
return | |||||
} | |||||
ctx.Redirect(ctx.Repo.RepoLink + "/wiki/" + models.ToWikiPageURL(form.Title)) | |||||
} | } |
@@ -1,67 +0,0 @@ | |||||
<div id="body-nav" class="repo-nav"> | |||||
<div class="container"> | |||||
<div class="row"> | |||||
<div class="col-md-7"> | |||||
<h3 class="name"><i class="fa fa-book fa-lg"></i><a href="{{.Owner.HomeLink}}">{{.Owner.Name}}</a> / <a href="{{AppSubUrl}}/{{.Owner.Name}}/{{.Repository.Name}}">{{.Repository.Name}}</a> {{if .Repository.IsPrivate}}<span class="label label-default">Private</span>{{else if .Repository.IsMirror}}<span class="label label-default">Mirror</span>{{end}}</h3> | |||||
<p class="desc">{{.Repository.DescriptionHtml}}{{if .Repository.Website}} <a href="{{.Repository.Website}}">{{.Repository.Website}}</a>{{end}}</p> | |||||
</div> | |||||
<div class="col-md-5 actions text-right clone-group-btn"> | |||||
{{if not .IsBareRepo}} | |||||
<div class="btn-group" id="repo-clone"> | |||||
<a class="btn btn-default" href="{{.RepoLink}}/archive/{{.BranchName}}/{{.Repository.Name}}.zip"><i class="fa fa-download fa-lg fa-m"></i></a> | |||||
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown"> | |||||
<span class="caret"></span> | |||||
</button> | |||||
<div class="dropdown-menu clone-group-btn dropdown-menu-right no-propagation"> | |||||
<div class="input-group"> | |||||
<span class="input-group-btn"> | |||||
<button class="btn btn-default" data-link="{{.CloneLink.SSH}}" type="button">SSH</button> | |||||
<button class="btn btn-default" data-link="{{.CloneLink.HTTPS}}" type="button">HTTPS</button> | |||||
</span> | |||||
<input type="text" class="form-control clone-group-url" value="" readonly id="repo-clone-ipt"/> | |||||
<span class="input-group-btn"> | |||||
<button class="btn btn-default" type="button" data-toggle="tooltip" title="copy to clipboard" data-placement="top" data-init="copy" data-copy-val="val" data-copy-from="#repo-clone-ipt"><i class="fa fa-copy"></i></button> | |||||
</span> | |||||
</div> | |||||
<p class="help-block text-center">Need help cloning? Visit <a target="_blank" href="https://help.github.com/articles/fork-a-repo">Help</a>!</p> | |||||
<hr/> | |||||
<div class="clone-zip text-center"> | |||||
<a class="btn btn-success btn-lg" href="{{.RepoLink}}/archive/{{.BranchName}}/{{.Repository.Name}}.zip" rel="nofollow"><i class="fa fa-suitcase"></i>Download ZIP</a> | |||||
<a class="btn btn-success btn-lg" href="{{.RepoLink}}/archive/{{.BranchName}}/{{.Repository.Name}}.tar.gz" rel="nofollow"><i class="fa fa-suitcase"></i>Download TAR.GZ</a> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
{{if .IsSigned}} | |||||
<div class="btn-group {{if .IsRepositoryWatching}}watching{{else}}no-watching{{end}}" id="repo-watching" data-watch="{{AppSubUrl}}/{{.Owner.Name}}/{{.Repository.Name}}/action/watch" data-unwatch="{{AppSubUrl}}/{{.Owner.Name}}/{{.Repository.Name}}/action/unwatch"> | |||||
{{if .IsRepositoryWatching}} | |||||
<button type="button" class="btn btn-default"><i class="fa fa-eye fa-lg fa-m"></i></button> | |||||
{{else}} | |||||
<button type="button" class="btn btn-default"><i class="fa fa-eye-slash fa-lg fa-m"></i></button> | |||||
{{end}} | |||||
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown"> | |||||
<span class="caret"></span> | |||||
</button> | |||||
<div class="dropdown-menu dropdown-menu-right"> | |||||
<div class="dropdown-item text-left to-unwatch"> | |||||
<h4 role="presentation" class="dropdown-header {{if not .IsRepositoryWatching}}text-primary{{end}}">Not Watching</h4> | |||||
<p class="description">You only receive notifications for conversations in which you participate or are @mentioned.</p> | |||||
<p class="divider"></p> | |||||
</div> | |||||
<div class="dropdown-item text-left to-watch"> | |||||
<h4 role="presentation" class="dropdown-header {{if .IsRepositoryWatching}}text-primary{{end}}">Watching</h4> | |||||
<p class="description">You receive notifications for all conversations in this repository.</p> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
{{end}} | |||||
<!-- <div class="btn-group"> | |||||
<button type="button" class="btn btn-default" data-toggle="tooltip" data-placement="top" title="Star"><i class="fa fa-star"></i> {{.Repository.NumStars}}</button> | |||||
</div> --> | |||||
{{end}} | |||||
<!-- <div class="btn-group"> | |||||
<a type="button" {{if not .IsRepositoryOwner}}href="{{AppSubUrl}}/{{.Username}}/{{.Reponame}}/fork"{{end}} class="btn btn-default" data-toggle="tooltip" data-placement="top" title="Fork"><i class="fa fa-code-fork fa-lg"></i> {{.Repository.NumForks}}</a> | |||||
</div> --> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</div> |
@@ -3,16 +3,23 @@ | |||||
{{template "repo/header" .}} | {{template "repo/header" .}} | ||||
<div class="ui container"> | <div class="ui container"> | ||||
{{template "repo/sidebar" .}} | {{template "repo/sidebar" .}} | ||||
{{template "base/alert" .}} | |||||
<div class="ui header"> | <div class="ui header"> | ||||
{{.i18n.Tr "repo.wiki.new_page"}} | {{.i18n.Tr "repo.wiki.new_page"}} | ||||
{{if .PageIsWikiEdit}} | |||||
<div class="ui right"> | |||||
<a class="ui green small button" href="{{.RepoLink}}/wiki/_new">{{.i18n.Tr "repo.wiki.new_page_button"}}</a> | |||||
</div> | |||||
{{end}} | |||||
</div> | </div> | ||||
<form class="ui form" action="{{.Link}}" method="post"> | <form class="ui form" action="{{.Link}}" method="post"> | ||||
{{.CsrfTokenHtml}} | {{.CsrfTokenHtml}} | ||||
<div class="field"> | |||||
<input type="hidden" name="old_title" value="{{.old_title}}"> | |||||
<div class="field {{if .Err_Title}}error{{end}}"> | |||||
<input name="title" value="{{.title}}" autofocus required> | <input name="title" value="{{.title}}" autofocus required> | ||||
</div> | </div> | ||||
<div class="field"> | <div class="field"> | ||||
<textarea id="edit-area" name="content" data-url="{{AppSubUrl}}/api/v1/markdown" data-context="{{.RepoLink}}">{{.i18n.Tr "repo.wiki.welcome"}}</textarea required> | |||||
<textarea id="edit-area" name="content" data-url="{{AppSubUrl}}/api/v1/markdown" data-context="{{.RepoLink}}">{{if .PageIsWikiEdit}}{{.content}}{{else}}{{.i18n.Tr "repo.wiki.welcome"}}{{end}}</textarea required> | |||||
</div> | </div> | ||||
<div class="field"> | <div class="field"> | ||||
<input name="message" placeholder="{{.i18n.Tr "repo.wiki.default_commit_message"}}"> | <input name="message" placeholder="{{.i18n.Tr "repo.wiki.default_commit_message"}}"> | ||||
@@ -3,15 +3,43 @@ | |||||
{{template "repo/header" .}} | {{template "repo/header" .}} | ||||
<div class="ui container"> | <div class="ui container"> | ||||
{{template "repo/sidebar" .}} | {{template "repo/sidebar" .}} | ||||
<div class="choose page"> | |||||
<div class="ui floating filter dropdown" data-no-results="{{.i18n.Tr "repo.pulls.no_results"}}"> | |||||
<div class="ui basic small button"> | |||||
<span class="text"> | |||||
{{.i18n.Tr "repo.wiki.page"}}: | |||||
<strong>{{.title}}</strong> | |||||
</span> | |||||
<i class="dropdown icon"></i> | |||||
</div> | |||||
<div class="menu"> | |||||
<div class="ui icon search input"> | |||||
<i class="filter icon"></i> | |||||
<input name="search" placeholder="{{.i18n.Tr "repo.wiki.filter_page"}}..."> | |||||
</div> | |||||
<div class="scrolling menu" {{if .IsTag}}style="display: none"{{end}}> | |||||
{{range .Pages}} | |||||
<div class="item {{if eq $.Title .Name}}selected{{end}}" data-url="{{$.RepoLink}}/wiki/{{.URL}}">{{.Name}}</div> | |||||
{{end}} | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
<div class="ui dividing header"> | <div class="ui dividing header"> | ||||
{{.Title}} | |||||
{{.title}} | |||||
{{if .IsRepositoryPusher}} | |||||
<div class="ui right"> | |||||
<a class="ui small button" href="{{.RepoLink}}/wiki/{{.PageURL}}/_edit">{{.i18n.Tr "repo.wiki.edit_page_button"}}</a> | |||||
<a class="ui green small button" href="{{.RepoLink}}/wiki/_new">{{.i18n.Tr "repo.wiki.new_page_button"}}</a> | |||||
</div> | |||||
{{end}} | |||||
<div class="ui sub header"> | <div class="ui sub header"> | ||||
{{$timeSince := TimeSince .Author.When $.Lang}} | {{$timeSince := TimeSince .Author.When $.Lang}} | ||||
{{.i18n.Tr "repo.wiki.last_commit_info" .Author.Name $timeSince | Safe}} | {{.i18n.Tr "repo.wiki.last_commit_info" .Author.Name $timeSince | Safe}} | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<div class="ui segment markdown"> | <div class="ui segment markdown"> | ||||
{{.Content | Str2html}} | |||||
{{.content | Str2html}} | |||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </div> |