Unknwon лет назад: 8
Родитель
Сommit
e42fcb033d

+ 5 - 3
cmd/web.go

@@ -378,6 +378,7 @@ func runWeb(ctx *cli.Context) {
 	}
 
 	reqRepoAdmin := middleware.RequireRepoAdmin()
+	reqRepoPusher := middleware.RequireRepoPusher()
 
 	// ***** START: Organization *****
 	m.Group("/org", func() {
@@ -534,13 +535,14 @@ func runWeb(ctx *cli.Context) {
 
 		m.Group("/wiki", func() {
 			m.Get("/?:page", repo.Wiki)
-			m.Get("/_list", repo.WikiList)
+			m.Get("/_pages", repo.WikiPages)
 
 			m.Group("", func() {
 				m.Combo("/_new").Get(repo.NewWiki).
 					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())
 
 		m.Get("/archive/*", repo.Download)

+ 5 - 0
conf/locale/locale_en-US.ini

@@ -539,10 +539,15 @@ wiki = 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.create_first_page = Create the first page
+wiki.page = Page
+wiki.filter_page = Filter page
 wiki.new_page = Create New Page
 wiki.default_commit_message = Write a note about this update (optional).
 wiki.save_page = Save Page
 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.options = Options

+ 20 - 0
models/error.go

@@ -107,6 +107,26 @@ func (err ErrUserHasOrgs) Error() string {
 	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
models/pull.go

@@ -252,7 +252,7 @@ func (pr *PullRequest) testPatch() (err error) {
 
 	// Checkout base branch.
 	_, 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)
 	if err != nil {
 		return fmt.Errorf("git checkout: %s", stderr)

+ 22 - 3
models/wiki.go

@@ -7,6 +7,7 @@ package models
 import (
 	"fmt"
 	"io/ioutil"
+	"os"
 	"path"
 	"path/filepath"
 	"strings"
@@ -108,8 +109,8 @@ func (repo *Repository) UpdateLocalWiki() error {
 	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))
 	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)
 	}
 
-	title = strings.Replace(title, "/", " ", -1)
+	title = ToWikiPageName(strings.Replace(title, "/", " ", -1))
 	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 {
 		return fmt.Errorf("WriteFile: %v", err)
 	}
@@ -152,3 +163,11 @@ func (repo *Repository) AddWikiPage(doer *User, title, content, message string)
 
 	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
modules/auth/repo_form.go

@@ -246,9 +246,10 @@ func (f *EditReleaseForm) Validate(ctx *macaron.Context, errs binding.Errors) bi
 //        \/          \/
 
 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.

Разница между файлами не показана из-за своего большого размера
+ 2 - 2
modules/bindata/bindata.go


+ 9 - 4
modules/middleware/context.go

@@ -59,7 +59,7 @@ type Context struct {
 	IsSigned    bool
 	IsBasicAuth bool
 
-	Repo RepoContext
+	Repo *RepoContext
 
 	Org struct {
 		IsOwner      bool
@@ -73,17 +73,22 @@ type Context struct {
 }
 
 // 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
 }
 
 // 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
 }
 
+// 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
-func (r RepoContext) HasAccess() bool {
+func (r *RepoContext) HasAccess() bool {
 	return r.AccessMode >= models.ACCESS_MODE_READ
 }
 

+ 12 - 6
modules/middleware/repo.go

@@ -6,7 +6,6 @@ package middleware
 
 import (
 	"fmt"
-	"net/url"
 	"path"
 	"strings"
 
@@ -225,6 +224,8 @@ func RetrieveBaseRepo(ctx *Context, repo *models.Repository) {
 
 func RepoAssignment(args ...bool) macaron.Handler {
 	return func(ctx *Context) {
+		ctx.Repo = &RepoContext{}
+
 		var (
 			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["IsRepositoryOwner"] = ctx.Repo.IsOwner()
 		ctx.Data["IsRepositoryAdmin"] = ctx.Repo.IsAdmin()
+		ctx.Data["IsRepositoryPusher"] = ctx.Repo.IsPusher()
 
 		ctx.Data["DisableSSH"] = setting.DisableSSH
 		ctx.Repo.CloneLink, err = repo.CloneLink()
@@ -397,11 +399,15 @@ func RepoAssignment(args ...bool) macaron.Handler {
 func RequireRepoAdmin() macaron.Handler {
 	return func(ctx *Context) {
 		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)
 			return
 		}

+ 24 - 19
public/js/gogs.js

@@ -231,6 +231,11 @@ function initRepository() {
         });
     }
 
+    // Wiki
+    if ($('.repository.wiki.view').length > 0) {
+        initFilterSearchDropdown('.choose.page .dropdown');
+    }
+
     // Options
     if ($('.repository.settings.options').length > 0) {
         $('#repo_name').keyup(function () {
@@ -314,23 +319,23 @@ function initRepository() {
         $('#edit-title').click(editTitleToggle);
         $('#cancel-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-content').click(function () {
@@ -729,9 +734,9 @@ $(document).ready(function () {
     // Show exact time
     $('.time-since').each(function () {
         $(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.

+ 102 - 23
routers/repo/wiki.go

@@ -6,6 +6,7 @@ package repo
 
 import (
 	"io/ioutil"
+	"strings"
 
 	"github.com/gogits/git-shell"
 
@@ -21,56 +22,97 @@ const (
 	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())
 	if err != nil {
 		ctx.Handle(500, "OpenRepository", err)
-		return
+		return nil, ""
 	}
 	commit, err := wikiRepo.GetCommitOfBranch("master")
 	if err != nil {
 		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
 
-	blob, err := commit.GetBlobByPath(page + ".md")
+	blob, err := commit.GetBlobByPath(pageName + ".md")
 	if err != nil {
 		if git.IsErrNotExist(err) {
-			ctx.Redirect(ctx.Repo.RepoLink + "/wiki/_list")
+			ctx.Redirect(ctx.Repo.RepoLink + "/wiki/_pages")
 		} else {
 			ctx.Handle(500, "GetBlobByPath", err)
 		}
-		return
+		return nil, ""
 	}
 	r, err := blob.Data()
 	if err != nil {
 		ctx.Handle(500, "Data", err)
-		return
+		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) {
+	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
 	}
-	ctx.Data["Content"] = string(base.RenderMarkdown(data, ctx.Repo.RepoLink))
 
 	// Get last change information.
-	lastCommit, err := wikiRepo.GetCommitByPath(page + ".md")
+	lastCommit, err := wikiRepo.GetCommitByPath(pageName + ".md")
 	if err != nil {
 		ctx.Handle(500, "GetCommitByPath", err)
 		return
@@ -80,7 +122,7 @@ func Wiki(ctx *middleware.Context) {
 	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 {
-		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
 	}
 
@@ -115,5 +162,37 @@ func NewWikiPost(ctx *middleware.Context, form auth.NewWikiForm) {
 }
 
 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))
 }

+ 0 - 67
templates/repo/nav.tmpl

@@ -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
templates/repo/wiki/new.tmpl

@@ -3,16 +3,23 @@
 	{{template "repo/header" .}}
   <div class="ui container">
     {{template "repo/sidebar" .}}
+    {{template "base/alert" .}}
     <div class="ui header">
       {{.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>
     <form class="ui form" action="{{.Link}}" method="post">
       {{.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>
       </div>
       <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 class="field">
         <input name="message" placeholder="{{.i18n.Tr "repo.wiki.default_commit_message"}}">

+ 30 - 2
templates/repo/wiki/view.tmpl

@@ -3,15 +3,43 @@
 	{{template "repo/header" .}}
   <div class="ui container">
     {{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">
-      {{.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">
       	{{$timeSince := TimeSince .Author.When $.Lang}}
       	{{.i18n.Tr "repo.wiki.last_commit_info" .Author.Name $timeSince | Safe}}
       </div>
     </div>
 		<div class="ui segment markdown">
-			{{.Content | Str2html}}
+			{{.content | Str2html}}
 		</div>
 	</div>
 </div>