wiki: finish edit

This commit is contained in:
Unknwon committed 2015-11-27 01:50:38 -05:00
1 parent 392f3ee210
commit e42fcb033d
14 files changed
+262 -152

No files matched your search

+5 -3
View File
@@ -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) m.Combo("/:page/_edit").Get(repo.EditWiki).
}, reqSignIn) Post(bindIgnErr(auth.NewWikiForm{}), repo.EditWikiPost)
}, reqSignIn, reqRepoPusher)
}, middleware.RepoRef()) }, middleware.RepoRef())
m.Get("/archive/*", repo.Download) m.Get("/archive/*", repo.Download)
+5
View File
@@ -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
+20
View File
@@ -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)
}
// __________ ___. .__ .__ ____ __. // __________ ___. .__ .__ ____ __.
// \______ \__ _\_ |__ | | |__| ____ | |/ _|____ ___.__. // \______ \__ _\_ |__ | | |__| ____ | |/ _|____ ___.__.
// | ___/ | \ __ \| | | |/ ___\ | <_/ __ < | | // | ___/ | \ __ \| | | |/ ___\ | <_/ __ < | |
+1 -1
View File
@@ -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)
+22 -3
View File
@@ -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. // updateWikiPage adds new page to repository wiki.
func (repo *Repository) AddWikiPage(doer *User, title, content, message string) (err error) { 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)
}
+4 -3
View File
@@ -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"` OldTitle string
Content string `binding:"Required"` Title string `binding:"Required"`
Message string Content string `binding:"Required"`
Message string
} }
// FIXME: use code generation to generate this method. // FIXME: use code generation to generate this method.
+2 -2
View File
@@ -4364,7 +4364,7 @@ func confLocaleLocale_deDeIni() (*asset, error) {
return a, nil return a, nil
} }
var _confLocaleLocale_enUsIni = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\xbc\xbd\xeb\x72\xdc\x48\xae\x27\xfe\x9d\x4f\xc1\xf6\x84\xc3\x76\x84\x5c\x8e\xee\x3e\xff\xff\x6e\x74\xb4\xdd\x2b\x4b\xed\xcb\x39\x96\xa5\xb1\xd4\xd3\x3b\xeb\x70\xb0\x59\x45\xaa\x8a\xe3\x2a\xb2\x9a\x64\xb9\xac\x39\x71\x22\xf6\x01\xf6\x01\x76\x5f\xef\x3c\xc9\x02\x3f\x00\x79\x21\x59\x92\xdd\x33\xb1\xfe\x60\xb1\x32\x91\x37\x24\x12\x89\x44\x02\xc8\x7c\xbb\xcd\x8a\xb2\x5b\xa4\x4f\xd3\xe3\x74\x9b\x57\xf5\xba\xec\xba\xb4\x2b\xd7\xd7\x8f\x57\x4d\xd7\x97\x45\xfa\xb2\xea\xe9\x77\xfb\xa9\x5a\x94\x49\xb2\x6a\x36\x25\x81\xbe\xa2\x3f\x49\x91\x77\xab\x79\x93\xb7\x05\x25\x9c\xda\x77\x52\x7e\xde\xae\x9b\x96\x81\x7e\x96\xaf\x64\x55\xae\xb7\x5c\x86\xfe\x24\x5d\xb5\xac\xb3\xaa\xa6\x9f\x97\xf4\x95\xbe\xae\x25\xa5\xd9\xf5\x96\x74\xbe\xeb\x25\x6d\xb7\xb5\xa4\x5f\xb6\x49\x5b\x2e\x2b\xea\x4d\x4b\x49\xef\xf4\x33\xd9\x97\xf3\xae\xea\xb9\xa5\x5f\xe5\x2b\xf9\x54\xb6\x5d\xd5\x70\xed\x7f\x91\xaf\x64\x9b\x2f\x19\xe0\x82\xfe\x24\x7d\xb9\xd9\xae\x73\x14\xb8\xd2\xcf\x64\x9d\xd7\xcb\x9d\xc0\xbc\xd1\xcf\x64\xd1\x96\x94\x95\xd5\xe5\x9e\x52\x4f\xf0\x63\x36\x9b\x25\x3b\x42\x42\xb6\x6d\x9b\xeb\x6a\x5d\x66\x79\x5d\x64\x1b\x19\xe6\x2f\x94\x9e\x6a\x7a\x4a\xe9\x29\xa7\x63\x08\x65\x41\x43\xcd\xf2\x4e\xc7\x41\xb8\xa4\x91\xe7\x5d\x82\xaa\xea\x7c\x63\xa5\xf9\x33\x29\x37\x79\xb5\x66\xac\x3d\xe6\x0f\xea\x78\xd7\xed\x1b\xe0\xf6\x42\x3f\x09\x09\x59\x7f\xb3\x2d\x81\x83\xc7\x57\xf4\x95\x2c\xf2\x6d\xbf\x58\xe5\xdc\x4f\xf9\x4a\x08\x68\xdb\x10\x32\x9a\xf6\x06\x70\xf6\x23\x69\xda\x65\x5e\x57\x7f\xcf\x7b\x41\xd0\x79\xf0\x33\xd9\x54\x6d\xdb\x30\x6e\xcf\xf0\x91\xd0\xd0\x33\xae\x87\x52\xde\x12\x16\x82\x5a\x38\x67\x53\x2d\x5b\x41\x23\x67\x9e\xe1\x17\xd7\xc2\x79\xd7\x4d\xfb\x51\x33\x5e\xf0\xe7\xa0\x28\x75\x42\x73\xe3\xf6\xf3\x9a\x10\xaf\xb9\x67\xf8\x11\x01\x74\x49\x5e\x6c\x08\x95\xdb\xbc\x2e\x19\x47\xc7\xfc\x8b\xf0\x42\xbf\x92\x7c\xb1\x68\x76\x75\x9f\x75\x65\xdf\x57\xf5\x92\x91\x7d\x2c\x49\xe9\xa5\x26\x25\x41\x9e\x4b\xbb\x69\x76\x6e\x3a\x29\xfd\xaf\xf4\x33\xbd\x90\x9f\x92\x17\x14\x42\xa6\x2b\xc9\x23\xe9\xb2\xeb\xb2\x2c\x64\x2c\x5d\xfa\x82\xbe\x93\xed\x6e\xbd\x26\xac\xfd\xbe\x2b\xbb\x9e\x0b\x5d\xd0\x6f\x1a\xbf\xfc\x4e\xaa\xae\xa3\x0f\x4a\x7e\x8d\x8f\x84\xa6\xae\x5e\x60\x30\x27\xf8\x48\x92\xf7\x5d\x99\xb7\x8b\xd5\x87\x44\xfe\xa2\xaf\xfc\xc1\xb4\x77\x68\x52\x99\x90\x94\x88\xa4\x05\x6b\x20\x59\x34\x05\xff\x38\xa1\x3f\x54\x75\x55\x77\x7d\xbe\x5e\x7f\x48\xf4\x83\xc1\xe4\x4b\x26\xa0\xaf\x7a\x60\x41\x13\xd3\xcb\xbe\xdc\x76\x3c\x83\xe9\x8b\xaa\xed\xfa\xc7\x7d\x45\xc4\xfa\x6e\x57\x27\x45\xb3\xf8\x48\xcb\x80\x97\x34\x5a\x7e\x7d\x9d\x12\xb2\x1e\xd0\x42\x68\x77\x75\x4d\xe8\x49\x5f\x36\x84\x32\x6a\xa6\xa2\xf6\x4f\x01\x7d\x94\x6e\xd7\x65\xde\x11\x48\x99\x17\xe9\x8f\x79\xda\xe7\xed\xb2\xec\x9f\xde\xcb\xe6\xb4\xfc\x3e\xde\x4b\x57\x6d\x79\xfd\xf4\xde\xfd\xee\xde\xb3\x97\x3b\x2a\xb6\xae\xea\xb2\xfb\xf1\x49\xfe\x2c\x5d\xe4\x94\x43\x68\xbc\x49\xe7\xe5\x35\xaf\x36\x6a\x2b\x25\x2a\xaf\x97\xbc\xd2\x6e\xfa\x15\x37\x48\x94\x40\x1f\x5d\xca\x4b\xfd\x9b\x84\x27\x80\x58\x41\x56\xcc\x8d\xad\xa1\x43\x48\x6e\x69\x02\xce\x6e\x2e\xff\xfc\xe6\x28\xbd\x20\xde\xb6\x6c\x4b\x7c\xd3\x7f\x54\xe2\xfb\x94\x46\x7b\x55\x9d\x3e\x9f\x25\x54\xd6\x10\x72\x9a\xf7\xf9\x9c\xfb\xee\x66\x9f\x33\x65\x11\xba\x3c\x2c\x45\xe6\x96\xe0\x8c\x5d\x1f\x4d\xcb\xd4\x42\xa6\x3a\x74\xf9\xbb\x3a\xde\x32\x0f\xa0\x74\x87\xd9\x0b\xc1\x19\x55\x95\xbe\x7e\xfb\xf6\xfc\xf4\x79\x5a\xd6\x4b\xc2\x4c\xba\xaf\xfa\x55\xba\xeb\xaf\xff\x6b\xb6\x2c\xeb\xb2\xcd\xd7\xd9\xa2\x62\xa4\xb4\x44\xb0\x29\x61\x49\x86\x38\x4b\xba\x6e\x4d\x2c\x0a\x54\x70\x79\xf9\x26\x3d\x63\x4a\xd8\xe6\xfd\x0a\x1d\xe9\x57\x49\xf7\xfb\x9a\x11\xe5\x1a\xbc\x5a\x95\x29\x16\x03\x80\x9a\xeb\x21\x5e\xd2\x42\xfb\x3a\x4b\xca\xb6\xcd\x88\x83\xf6\x37\x8c\x66\xad\xf3\x10\xb4\x54\x47\xd4\x5e\x37\x3d\x4d\x63\x8a\x72\x52\x45\x55\x7f\xca\xd7\x55\x41\xc8\xf6\x08\x89\xcb\x22\xb1\x68\x68\xde\xb8\x34\x51\x66\xb3\xc7\x50\xf3\x05\x6d\x00\x5d\x7a\x6f\x76\x0f\x1c\xf7\xde\xe3\x7b\xb3\xa4\x6e\x32\xe1\x12\xcc\x9b\x8b\xaa\xcb\xe7\xc4\xa7\x65\xdf\x68\x8d\xeb\xfd\x95\xe9\x47\xba\xa2\x10\x69\x04\xc1\xb8\xe5\xbd\x08\x5b\x00\x13\x57\x4e\x0c\x1b\xcc\x46\xd9\x4c\x38\x76\xe3\x49\x6e\x7e\x85\x2d\xb9\x84\xd1\x98\x13\x9b\x30\xa3\xae\xe3\xed\x76\x5d\x2d\xa4\xe9\x97\x92\xe7\x09\x8d\x77\x66\x45\x4a\x08\x07\x42\xb1\xbc\x80\x5c\xa8\xd7\xcc\xb6\xd2\x88\xcf\xa3\xfc\xaa\xa4\x95\xb3\xda\x2d\x65\x77\x5a\x37\xbb\xe2\x1b\x30\x14\x9b\x39\xcf\x4f\xd2\x77\x0d\x75\x18\xd4\xe1\x00\x7c\x13\xc7\xc4\x18\x58\x18\x68\xcb\x4d\xd3\x33\xe2\xb4\x58\x45\xd3\xb3\xaf\x28\x93\x46\xda\xe5\x9f\x88\x2d\xf6\x8d\x2c\xc9\x82\x96\xdc\x82\x2b\x26\x0e\xb6\xa3\x1d\x5d\x96\x05\xf1\x11\x59\x1a\x96\x16\xd3\x20\xa0\x36\x3b\x5a\x4d\x2b\xaa\x8c\x11\xcf\x12\x09\x55\x39\xd5\x4f\x0c\x89\xea\xc1\x2a\xa7\x95\xdb\xd0\xe6\xc9\x13\x7d\x8a\x0f\xfd\x1d\xd6\x4f\xbd\xca\xaf\xaf\xa9\x57\x1d\xad\x8a\x57\xe9\x62\xdd\xd0\x92\xfa\xe5\xdd\x9b\x8e\x17\xcc\x2a\xdb\x36\x2d\x24\x11\xca\xba\xa0\x4f\x97\x16\x20\x9a\x21\xea\xdd\x66\x4e\xbf\xf6\xab\x8a\x18\x35\xd0\xce\x25\x58\x4a\xa2\x54\x6a\x62\xd7\xd1\x14\x1e\xaLine truncated var _confLocaleLocale_enUsIni = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\xbc\xbd\xeb\x72\xdc\x48\xae\x27\xfe\x9d\x4f\xc1\xf6\x84\xc3\x76\x84\x5c\x8e\xee\x3e\xff\xff\x6e\x74\xb4\xdd\x2b\x4b\xed\xcb\x39\x96\xa5\xb1\xd4\xd3\x3b\xeb\x70\xb0\x59\x45\xaa\x8a\xe3\x2a\xb2\x9a\x64\xb9\xac\x39\x71\x22\xf6\x01\xf6\x01\x76\x5f\xef\x3c\xc9\x02\x3f\x00\x79\x21\x59\x92\xdd\x33\xb1\xfe\x60\xb1\x32\x91\x37\x24\x12\x89\x44\x02\xc8\x7c\xbb\xcd\x8a\xb2\x5b\xa4\x4f\xd3\xe3\x74\x9b\x57\xf5\xba\xec\xba\xb4\x2b\xd7\xd7\x8f\x57\x4d\xd7\x97\x45\xfa\xb2\xea\xe9\x77\xfb\xa9\x5a\x94\x49\xb2\x6a\x36\x25\x81\xbe\xa2\x3f\x49\x91\x77\xab\x79\x93\xb7\x05\x25\x9c\xda\x77\x52\x7e\xde\xae\x9b\x96\x81\x7e\x96\xaf\x64\x55\xae\xb7\x5c\x86\xfe\x24\x5d\xb5\xac\xb3\xaa\xa6\x9f\x97\xf4\x95\xbe\xae\x25\xa5\xd9\xf5\x96\x74\xbe\xeb\x25\x6d\xb7\xb5\xa4\x5f\xb6\x49\x5b\x2e\x2b\xea\x4d\x4b\x49\xef\xf4\x33\xd9\x97\xf3\xae\xea\xb9\xa5\x5f\xe5\x2b\xf9\x54\xb6\x5d\xd5\x70\xed\x7f\x91\xaf\x64\x9b\x2f\x19\xe0\x82\xfe\x24\x7d\xb9\xd9\xae\x73\x14\xb8\xd2\xcf\x64\x9d\xd7\xcb\x9d\xc0\xbc\xd1\xcf\x64\xd1\x96\x94\x95\xd5\xe5\x9e\x52\x4f\xf0\x63\x36\x9b\x25\x3b\x42\x42\xb6\x6d\x9b\xeb\x6a\x5d\x66\x79\x5d\x64\x1b\x19\xe6\x2f\x94\x9e\x6a\x7a\x4a\xe9\x29\xa7\x63\x08\x65\x41\x43\xcd\xf2\x4e\xc7\x41\xb8\xa4\x91\xe7\x5d\x82\xaa\xea\x7c\x63\xa5\xf9\x33\x29\x37\x79\xb5\x66\xac\x3d\xe6\x0f\xea\x78\xd7\xed\x1b\xe0\xf6\x42\x3f\x09\x09\x59\x7f\xb3\x2d\x81\x83\xc7\x57\xf4\x95\x2c\xf2\x6d\xbf\x58\xe5\xdc\x4f\xf9\x4a\x08\x68\xdb\x10\x32\x9a\xf6\x06\x70\xf6\x23\x69\xda\x65\x5e\x57\x7f\xcf\x7b\x41\xd0\x79\xf0\x33\xd9\x54\x6d\xdb\x30\x6e\xcf\xf0\x91\xd0\xd0\x33\xae\x87\x52\xde\x12\x16\x82\x5a\x38\x67\x53\x2d\x5b\x41\x23\x67\x9e\xe1\x17\xd7\xc2\x79\xd7\x4d\xfb\x51\x33\x5e\xf0\xe7\xa0\x28\x75\x42\x73\xe3\xf6\xf3\x9a\x10\xaf\xb9\x67\xf8\x11\x01\x74\x49\x5e\x6c\x08\x95\xdb\xbc\x2e\x19\x47\xc7\xfc\x8b\xf0\x42\xbf\x92\x7c\xb1\x68\x76\x75\x9f\x75\x65\xdf\x57\xf5\x92\x91\x7d\x2c\x49\xe9\xa5\x26\x25\x41\x9e\x4b\xbb\x69\x76\x6e\x3a\x29\xfd\xaf\xf4\x33\xbd\x90\x9f\x92\x17\x14\x42\xa6\x2b\xc9\x23\xe9\xb2\xeb\xb2\x2c\x64\x2c\x5d\xfa\x82\xbe\x93\xed\x6e\xbd\x26\xac\xfd\xbe\x2b\xbb\x9e\x0b\x5d\xd0\x6f\x1a\xbf\xfc\x4e\xaa\xae\xa3\x0f\x4a\x7e\x8d\x8f\x84\xa6\xae\x5e\x60\x30\x27\xf8\x48\x92\xf7\x5d\x99\xb7\x8b\xd5\x87\x44\xfe\xa2\xaf\xfc\xc1\xb4\x77\x68\x52\x99\x90\x94\x88\xa4\x05\x6b\x20\x59\x34\x05\xff\x38\xa1\x3f\x54\x75\x55\x77\x7d\xbe\x5e\x7f\x48\xf4\x83\xc1\xe4\x4b\x26\xa0\xaf\x7a\x60\x41\x13\xd3\xcb\xbe\xdc\x76\x3c\x83\xe9\x8b\xaa\xed\xfa\xc7\x7d\x45\xc4\xfa\x6e\x57\x27\x45\xb3\xf8\x48\xcb\x80\x97\x34\x5a\x7e\x7d\x9d\x12\xb2\x1e\xd0\x42\x68\x77\x75\x4d\xe8\x49\x5f\x36\x84\x32\x6a\xa6\xa2\xf6\x4f\x01\x7d\x94\x6e\xd7\x65\xde\x11\x48\x99\x17\xe9\x8f\x79\xda\xe7\xed\xb2\xec\x9f\xde\xcb\xe6\xb4\xfc\x3e\xde\x4b\x57\x6d\x79\xfd\xf4\xde\xfd\xee\xde\xb3\x97\x3b\x2a\xb6\xae\xea\xb2\xfb\xf1\x49\xfe\x2c\x5d\xe4\x94\x43\x68\xbc\x49\xe7\xe5\x35\xaf\x36\x6a\x2b\x25\x2a\xaf\x97\xbc\xd2\x6e\xfa\x15\x37\x48\x94\x40\x1f\x5d\xca\x4b\xfd\x9b\x84\x27\x80\x58\x41\x56\xcc\x8d\xad\xa1\x43\x48\x6e\x69\x02\xce\x6e\x2e\xff\xfc\xe6\x28\xbd\x20\xde\xb6\x6c\x4b\x7c\xd3\x7f\x54\xe2\xfb\x94\x46\x7b\x55\x9d\x3e\x9f\x25\x54\xd6\x10\x72\x9a\xf7\xf9\x9c\xfb\xee\x66\x9f\x33\x65\x11\xba\x3c\x2c\x45\xe6\x96\xe0\x8c\x5d\x1f\x4d\xcb\xd4\x42\xa6\x3a\x74\xf9\xbb\x3a\xde\x32\x0f\xa0\x74\x87\xd9\x0b\xc1\x19\x55\x95\xbe\x7e\xfb\xf6\xfc\xf4\x79\x5a\xd6\x4b\xc2\x4c\xba\xaf\xfa\x55\xba\xeb\xaf\xff\x6b\xb6\x2c\xeb\xb2\xcd\xd7\xd9\xa2\x62\xa4\xb4\x44\xb0\x29\x61\x49\x86\x38\x4b\xba\x6e\x4d\x2c\x0a\x54\x70\x79\xf9\x26\x3d\x63\x4a\xd8\xe6\xfd\x0a\x1d\xe9\x57\x49\xf7\xfb\x9a\x11\xe5\x1a\xbc\x5a\x95\x29\x16\x03\x80\x9a\xeb\x21\x5e\xd2\x42\xfb\x3a\x4b\xca\xb6\xcd\x88\x83\xf6\x37\x8c\x66\xad\xf3\x10\xb4\x54\x47\xd4\x5e\x37\x3d\x4d\x63\x8a\x72\x52\x45\x55\x7f\xca\xd7\x55\x41\xc8\xf6\x08\x89\xcb\x22\xb1\x68\x68\xde\xb8\x34\x51\x66\xb3\xc7\x50\xf3\x05\x6d\x00\x5d\x7a\x6f\x76\x0f\x1c\xf7\xde\xe3\x7b\xb3\xa4\x6e\x32\xe1\x12\xcc\x9b\x8b\xaa\xcb\xe7\xc4\xa7\x65\xdf\x68\x8d\xeb\xfd\x95\xe9\x47\xba\xa2\x10\x69\x04\xc1\xb8\xe5\xbd\x08\x5b\x00\x13\x57\x4e\x0c\x1b\xcc\x46\xd9\x4c\x38\x76\xe3\x49\x6e\x7e\x85\x2d\xb9\x84\xd1\x98\x13\x9b\x30\xa3\xae\xe3\xed\x76\x5d\x2d\xa4\xe9\x97\x92\xe7\x09\x8d\x77\x66\x45\x4a\x08\x07\x42\xb1\xbc\x80\x5c\xa8\xd7\xcc\xb6\xd2\x88\xcf\xa3\xfc\xaa\xa4\x95\xb3\xda\x2d\x65\x77\x5a\x37\xbb\xe2\x1b\x30\x14\x9b\x39\xcf\x4f\xd2\x77\x0d\x75\x18\xd4\xe1\x00\x7c\x13\xc7\xc4\x18\x58\x18\x68\xcb\x4d\xd3\x33\xe2\xb4\x58\x45\xd3\xb3\xaf\x28\x93\x46\xda\xe5\x9f\x88\x2d\xf6\x8d\x2c\xc9\x82\x96\xdc\x82\x2b\x26\x0e\xb6\xa3\x1d\x5d\x96\x05\xf1\x11\x59\x1a\x96\x16\xd3\x20\xa0\x36\x3b\x5a\x4d\x2b\xaa\x8c\x11\xcf\x12\x09\x55\x39\xd5\x4f\x0c\x89\xea\xc1\x2a\xa7\x95\xdb\xd0\xe6\xc9\x13\x7d\x8a\x0f\xfd\x1d\xd6\x4f\xbd\xca\xaf\xaf\xa9\x57\x1d\xad\x8a\x57\xe9\x62\xdd\xd0\x92\xfa\xe5\xdd\x9b\x8e\x17\xcc\x2a\xdb\x36\x2d\x24\x11\xca\xba\xa0\x4f\x97\x16\x20\x9a\x21\xea\xdd\x66\x4e\xbf\xf6\xab\x8a\x18\x35\xd0\xce\x25\x58\x4a\xa2\x54\x6a\x62\xd7\xd1\x14\x1e\xaLine truncated
func confLocaleLocale_enUsIniBytes() ([]byte, error) { func confLocaleLocale_enUsIniBytes() ([]byte, error) {
return bindataRead( return bindataRead(
@@ -4379,7 +4379,7 @@ func confLocaleLocale_enUsIni() (*asset, error) {
return nil, err return nil, err
} }
info := bindataFileInfo{name: "conf/locale/locale_en-US.ini", size: 45999, mode: os.FileMode(420), modTime: time.Unix(1448600194, 0)} info := bindataFileInfo{name: "conf/locale/locale_en-US.ini", size: 46176, mode: os.FileMode(420), modTime: time.Unix(1448605845, 0)}
a := &asset{bytes: bytes, info: info} a := &asset{bytes: bytes, info: info}
return a, nil return a, nil
} }
+9 -4
View File
@@ -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
} }
+12 -6
View File
@@ -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.Handle(404, ctx.Req.RequestURI, nil)
ctx.SetCookie("redirect_to", "/"+url.QueryEscape(setting.AppSubUrl+ctx.Req.RequestURI), 0, setting.AppSubUrl) return
ctx.Redirect(setting.AppSubUrl + "/user/login") }
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
} }
+24 -19
View File
@@ -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 () { click(function () {
if ($edit_input.val().length == 0 || if ($edit_input.val().length == 0 ||
$edit_input.val() == $issue_title.text()) { $edit_input.val() == $issue_title.text()) {
$edit_input.val($issue_title.text()); $edit_input.val($issue_title.text());
return false; return false;
} }
$.post($(this).data('update-url'), { $.post($(this).data('update-url'), {
"_csrf": csrf, "_csrf": csrf,
"title": $edit_input.val() "title": $edit_input.val()
}, },
function (data) { function (data) {
$edit_input.val(data.title); $edit_input.val(data.title);
$issue_title.text(data.title); $issue_title.text(data.title);
}); });
return false; 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-content', $(this).attr('title')).
attr('data-variation', 'inverted tiny'). attr('data-variation', 'inverted tiny').
attr('title', ''); attr('title', '');
}); });
// Semantic UI modules. // Semantic UI modules.
+119 -40
View File
@@ -6,6 +6,7 @@ package repo
import ( import (
"io/ioutil" "io/ioutil"
"strings"
"github.com/gogits/git-shell" "github.com/gogits/git-shell"
@@ -21,6 +22,81 @@ const (
WIKI_NEW base.TplName = "repo/wiki/new" WIKI_NEW base.TplName = "repo/wiki/new"
) )
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())
if err != nil {
ctx.Handle(500, "OpenRepository", err)
return nil, ""
}
commit, err := wikiRepo.GetCommitOfBranch("master")
if err != nil {
ctx.Handle(500, "GetCommitOfBranch", err)
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
}
pageURL := ctx.Params(":page")
if len(pageURL) == 0 {
pageURL = "Home"
}
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
blob, err := commit.GetBlobByPath(pageName + ".md")
if err != nil {
if git.IsErrNotExist(err) {
ctx.Redirect(ctx.Repo.RepoLink + "/wiki/_pages")
} else {
ctx.Handle(500, "GetBlobByPath", err)
}
return nil, ""
}
r, err := blob.Data()
if err != nil {
ctx.Handle(500, "Data", err)
return nil, ""
}
data, err := ioutil.ReadAll(r)
if err != nil {
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) { func Wiki(ctx *middleware.Context) {
ctx.Data["PageIsWiki"] = true ctx.Data["PageIsWiki"] = true
@@ -30,47 +106,13 @@ func Wiki(ctx *middleware.Context) {
return return
} }
wikiRepo, err := git.OpenRepository(ctx.Repo.Repository.WikiPath()) wikiRepo, pageName := renderWikiPage(ctx, true)
if err != nil { if ctx.Written() {
ctx.Handle(500, "OpenRepository", err)
return return
} }
commit, err := wikiRepo.GetCommitOfBranch("master")
if err != nil {
ctx.Handle(500, "GetCommitOfBranch", err)
return
}
page := models.ToWikiPageName(ctx.Params(":page"))
if len(page) == 0 {
page = "Home"
}
ctx.Data["Title"] = page
ctx.Data["RequireHighlightJS"] = true
blob, err := commit.GetBlobByPath(page + ".md")
if err != nil {
if git.IsErrNotExist(err) {
ctx.Redirect(ctx.Repo.RepoLink + "/wiki/_list")
} else {
ctx.Handle(500, "GetBlobByPath", err)
}
return
}
r, err := blob.Data()
if err != nil {
ctx.Handle(500, "Data", err)
return
}
data, err := ioutil.ReadAll(r)
if err != nil {
ctx.Handle(500, "ReadAll", err)
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))
} }
-67
View File
@@ -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>&nbsp;{{.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>&nbsp;{{.Repository.NumForks}}</a>
</div> -->
</div>
</div>
</div>
</div>
+9 -2
View File
@@ -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"}}">
+30 -2
View File
@@ -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>