]> source.dussan.org Git - gitea.git/commitdiff
wiki - page revisions list (#7369)
authorCherrg <michael@gnehr.de>
Mon, 8 Jul 2019 08:20:22 +0000 (10:20 +0200)
committerLauris BH <lauris@nix.lv>
Mon, 8 Jul 2019 08:20:22 +0000 (11:20 +0300)
fix #7

* add wiki page revision list

* mobile improvements

* css improvements for long usernames

* split renderWikiPage into 3 functions

Signed-off-by: Michael Gnehr <michael@gnehr.de>
options/locale/locale_en-US.ini
public/css/index.css
public/less/_markdown.less
routers/repo/wiki.go
routers/routes/routes.go
templates/repo/wiki/revision.tmpl [new file with mode: 0644]
templates/repo/wiki/view.tmpl

index 0c83a7aef17835d5e07f64f1142cb13b28496b0c..6ef1277c6254323956ff755e2ddd0362336c2bdf 100644 (file)
@@ -1034,6 +1034,9 @@ 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.file_revision = Page Revision
+wiki.wiki_page_revisions = Wiki Page Revisions
+wiki.back_to_wiki = Back to wiki page
 wiki.delete_page_button = Delete Page
 wiki.delete_page_notice_1 = Deleting the wiki page '%s' cannot be undone. Continue?
 wiki.page_already_exists = A wiki page with the same name already exists.
index 9039409f146837ff23dae4a337a792c341f252d1..b948766b416b1bade68f106a955498d915a8714a 100644 (file)
@@ -290,6 +290,11 @@ footer .ui.left,footer .ui.right{line-height:40px}
 .markdown:not(code) .csv-data tr{border-top:0}
 .markdown:not(code) .csv-data th{font-weight:700;background:#f8f8f8;border-top:0}
 .markdown:not(code) .ui.list .list,.markdown:not(code) ol.ui.list ol,.markdown:not(code) ul.ui.list ul{padding-left:2em}
+.repository.wiki.revisions .ui.container>.ui.stackable.grid{flex-direction:row-reverse}
+.repository.wiki.revisions .ui.container>.ui.stackable.grid>.header{margin-top:0}
+.repository.wiki.revisions .ui.container>.ui.stackable.grid>.header .sub.header{padding-left:52px}
+.file-revisions-btn{display:block;float:left;margin-bottom:2px!important;padding:11px!important;margin-right:10px!important}
+.file-revisions-btn i{-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
 .home .logo{max-width:220px}
 @media only screen and (max-width:767px){.home .hero h1{font-size:3.5em}
 .home .hero h2{font-size:2em}
index e971248f6ffca9a63eff0430e858e2ca69b1b883..1dcc2caf94356f981fc124827dbbc4a016201f90 100644 (file)
         padding-left: 2em;
     }
 }
+
+.repository.wiki.revisions {
+    .ui.container > .ui.stackable.grid {
+        -ms-flex-direction: row-reverse;
+        flex-direction: row-reverse;
+
+        > .header {
+            margin-top: 0;
+
+            .sub.header {
+                padding-left: 52px;
+            }
+        }
+    }
+}
+
+.file-revisions-btn {
+    display: block;
+    float: left;
+    margin-bottom: 2px !important;
+    padding: 11px !important;
+    margin-right: 10px !important;
+
+    i {
+        -webkit-touch-callout: none;
+        -webkit-user-select: none;
+        -khtml-user-select: none;
+        -moz-user-select: none;
+        -ms-user-select: none;
+        user-select: none;
+    }
+}
index 43149c034061b8c5c2e16b7c3456de23aa77c39f..0fdf8536307e739c687502f32f5bc5a06b7897bd 100644 (file)
@@ -23,10 +23,11 @@ import (
 )
 
 const (
-       tplWikiStart base.TplName = "repo/wiki/start"
-       tplWikiView  base.TplName = "repo/wiki/view"
-       tplWikiNew   base.TplName = "repo/wiki/new"
-       tplWikiPages base.TplName = "repo/wiki/pages"
+       tplWikiStart    base.TplName = "repo/wiki/start"
+       tplWikiView     base.TplName = "repo/wiki/view"
+       tplWikiRevision base.TplName = "repo/wiki/revision"
+       tplWikiNew      base.TplName = "repo/wiki/new"
+       tplWikiPages    base.TplName = "repo/wiki/pages"
 )
 
 // MustEnableWiki check if wiki is enabled, if external then redirect
@@ -107,18 +108,20 @@ func wikiContentsByEntry(ctx *context.Context, entry *git.TreeEntry) []byte {
 
 // wikiContentsByName returns the contents of a wiki page, along with a boolean
 // indicating whether the page exists. Writes to ctx if an error occurs.
-func wikiContentsByName(ctx *context.Context, commit *git.Commit, wikiName string) ([]byte, bool) {
-       entry, err := findEntryForFile(commit, models.WikiNameToFilename(wikiName))
-       if err != nil {
+func wikiContentsByName(ctx *context.Context, commit *git.Commit, wikiName string) ([]byte, *git.TreeEntry, string, bool) {
+       var entry *git.TreeEntry
+       var err error
+       pageFilename := models.WikiNameToFilename(wikiName)
+       if entry, err = findEntryForFile(commit, pageFilename); err != nil {
                ctx.ServerError("findEntryForFile", err)
-               return nil, false
+               return nil, nil, "", false
        } else if entry == nil {
-               return nil, false
+               return nil, nil, "", true
        }
-       return wikiContentsByEntry(ctx, entry), true
+       return wikiContentsByEntry(ctx, entry), entry, pageFilename, false
 }
 
-func renderWikiPage(ctx *context.Context, isViewPage bool) (*git.Repository, *git.TreeEntry) {
+func renderViewPage(ctx *context.Context) (*git.Repository, *git.TreeEntry) {
        wikiRepo, commit, err := findWikiRepoCommit(ctx)
        if err != nil {
                if !git.IsErrNotExist(err) {
@@ -128,88 +131,176 @@ func renderWikiPage(ctx *context.Context, isViewPage bool) (*git.Repository, *gi
        }
 
        // Get page list.
-       if isViewPage {
-               entries, err := commit.ListEntries()
-               if err != nil {
-                       ctx.ServerError("ListEntries", err)
-                       return nil, nil
+       entries, err := commit.ListEntries()
+       if err != nil {
+               ctx.ServerError("ListEntries", err)
+               return nil, nil
+       }
+       pages := make([]PageMeta, 0, len(entries))
+       for _, entry := range entries {
+               if !entry.IsRegular() {
+                       continue
                }
-               pages := make([]PageMeta, 0, len(entries))
-               for _, entry := range entries {
-                       if !entry.IsRegular() {
-                               continue
-                       }
-                       wikiName, err := models.WikiFilenameToName(entry.Name())
-                       if err != nil {
-                               if models.IsErrWikiInvalidFileName(err) {
-                                       continue
-                               }
-                               ctx.ServerError("WikiFilenameToName", err)
-                               return nil, nil
-                       } else if wikiName == "_Sidebar" || wikiName == "_Footer" {
+               wikiName, err := models.WikiFilenameToName(entry.Name())
+               if err != nil {
+                       if models.IsErrWikiInvalidFileName(err) {
                                continue
                        }
-                       pages = append(pages, PageMeta{
-                               Name:   wikiName,
-                               SubURL: models.WikiNameToSubURL(wikiName),
-                       })
+                       ctx.ServerError("WikiFilenameToName", err)
+                       return nil, nil
+               } else if wikiName == "_Sidebar" || wikiName == "_Footer" {
+                       continue
                }
-               ctx.Data["Pages"] = pages
+               pages = append(pages, PageMeta{
+                       Name:   wikiName,
+                       SubURL: models.WikiNameToSubURL(wikiName),
+               })
        }
+       ctx.Data["Pages"] = pages
 
+       // get requested pagename
        pageName := models.NormalizeWikiName(ctx.Params(":page"))
        if len(pageName) == 0 {
                pageName = "Home"
        }
        ctx.Data["PageURL"] = models.WikiNameToSubURL(pageName)
-
        ctx.Data["old_title"] = pageName
        ctx.Data["Title"] = pageName
        ctx.Data["title"] = pageName
        ctx.Data["RequireHighlightJS"] = true
 
-       pageFilename := models.WikiNameToFilename(pageName)
-       var entry *git.TreeEntry
-       if entry, err = findEntryForFile(commit, pageFilename); err != nil {
-               ctx.ServerError("findEntryForFile", err)
-               return nil, nil
-       } else if entry == nil {
+       //lookup filename in wiki - get filecontent, gitTree entry , real filename
+       data, entry, pageFilename, noEntry := wikiContentsByName(ctx, commit, pageName)
+       if noEntry {
                ctx.Redirect(ctx.Repo.RepoLink + "/wiki/_pages")
+       }
+       if entry == nil || ctx.Written() {
                return nil, nil
        }
-       data := wikiContentsByEntry(ctx, entry)
+
+       sidebarContent, _, _, _ := wikiContentsByName(ctx, commit, "_Sidebar")
        if ctx.Written() {
                return nil, nil
        }
 
-       if isViewPage {
-               sidebarContent, sidebarPresent := wikiContentsByName(ctx, commit, "_Sidebar")
-               if ctx.Written() {
-                       return nil, nil
-               }
+       footerContent, _, _, _ := wikiContentsByName(ctx, commit, "_Footer")
+       if ctx.Written() {
+               return nil, nil
+       }
 
-               footerContent, footerPresent := wikiContentsByName(ctx, commit, "_Footer")
-               if ctx.Written() {
-                       return nil, nil
+       metas := ctx.Repo.Repository.ComposeMetas()
+       ctx.Data["content"] = markdown.RenderWiki(data, ctx.Repo.RepoLink, metas)
+       ctx.Data["sidebarPresent"] = sidebarContent != nil
+       ctx.Data["sidebarContent"] = markdown.RenderWiki(sidebarContent, ctx.Repo.RepoLink, metas)
+       ctx.Data["footerPresent"] = footerContent != nil
+       ctx.Data["footerContent"] = markdown.RenderWiki(footerContent, ctx.Repo.RepoLink, metas)
+
+       // get commit count - wiki revisions
+       commitsCount, _ := wikiRepo.FileCommitsCount("master", pageFilename)
+       ctx.Data["CommitCount"] = commitsCount
+
+       return wikiRepo, entry
+}
+
+func renderRevisionPage(ctx *context.Context) (*git.Repository, *git.TreeEntry) {
+       wikiRepo, commit, err := findWikiRepoCommit(ctx)
+       if err != nil {
+               if !git.IsErrNotExist(err) {
+                       ctx.ServerError("GetBranchCommit", err)
                }
+               return nil, nil
+       }
+
+       // get requested pagename
+       pageName := models.NormalizeWikiName(ctx.Params(":page"))
+       if len(pageName) == 0 {
+               pageName = "Home"
+       }
+       ctx.Data["PageURL"] = models.WikiNameToSubURL(pageName)
+       ctx.Data["old_title"] = pageName
+       ctx.Data["Title"] = pageName
+       ctx.Data["title"] = pageName
+       ctx.Data["RequireHighlightJS"] = true
 
-               metas := ctx.Repo.Repository.ComposeMetas()
-               ctx.Data["content"] = markdown.RenderWiki(data, ctx.Repo.RepoLink, metas)
-               ctx.Data["sidebarPresent"] = sidebarPresent
-               ctx.Data["sidebarContent"] = markdown.RenderWiki(sidebarContent, ctx.Repo.RepoLink, metas)
-               ctx.Data["footerPresent"] = footerPresent
-               ctx.Data["footerContent"] = markdown.RenderWiki(footerContent, ctx.Repo.RepoLink, metas)
-       } else {
-               ctx.Data["content"] = string(data)
-               ctx.Data["sidebarPresent"] = false
-               ctx.Data["sidebarContent"] = ""
-               ctx.Data["footerPresent"] = false
-               ctx.Data["footerContent"] = ""
+       //lookup filename in wiki - get filecontent, gitTree entry , real filename
+       data, entry, pageFilename, noEntry := wikiContentsByName(ctx, commit, pageName)
+       if noEntry {
+               ctx.Redirect(ctx.Repo.RepoLink + "/wiki/_pages")
+       }
+       if entry == nil || ctx.Written() {
+               return nil, nil
        }
 
+       ctx.Data["content"] = string(data)
+       ctx.Data["sidebarPresent"] = false
+       ctx.Data["sidebarContent"] = ""
+       ctx.Data["footerPresent"] = false
+       ctx.Data["footerContent"] = ""
+
+       // get commit count - wiki revisions
+       commitsCount, _ := wikiRepo.FileCommitsCount("master", pageFilename)
+       ctx.Data["CommitCount"] = commitsCount
+
+       // get page
+       page := ctx.QueryInt("page")
+       if page <= 1 {
+               page = 1
+       }
+
+       // get Commit Count
+       commitsHistory, err := wikiRepo.CommitsByFileAndRange("master", pageFilename, page)
+       if err != nil {
+               ctx.ServerError("CommitsByFileAndRange", err)
+               return nil, nil
+       }
+       commitsHistory = models.ValidateCommitsWithEmails(commitsHistory)
+       commitsHistory = models.ParseCommitsWithSignature(commitsHistory)
+
+       ctx.Data["Commits"] = commitsHistory
+
+       pager := context.NewPagination(int(commitsCount), git.CommitsRangeSize, page, 5)
+       pager.SetDefaultParams(ctx)
+       ctx.Data["Page"] = pager
+
        return wikiRepo, entry
 }
 
+func renderEditPage(ctx *context.Context) {
+       _, commit, err := findWikiRepoCommit(ctx)
+       if err != nil {
+               if !git.IsErrNotExist(err) {
+                       ctx.ServerError("GetBranchCommit", err)
+               }
+               return
+       }
+
+       // get requested pagename
+       pageName := models.NormalizeWikiName(ctx.Params(":page"))
+       if len(pageName) == 0 {
+               pageName = "Home"
+       }
+       ctx.Data["PageURL"] = models.WikiNameToSubURL(pageName)
+       ctx.Data["old_title"] = pageName
+       ctx.Data["Title"] = pageName
+       ctx.Data["title"] = pageName
+       ctx.Data["RequireHighlightJS"] = true
+
+       //lookup filename in wiki - get filecontent, gitTree entry , real filename
+       data, entry, _, noEntry := wikiContentsByName(ctx, commit, pageName)
+       if noEntry {
+               ctx.Redirect(ctx.Repo.RepoLink + "/wiki/_pages")
+       }
+       if entry == nil || ctx.Written() {
+               return
+       }
+
+       ctx.Data["content"] = string(data)
+       ctx.Data["sidebarPresent"] = false
+       ctx.Data["sidebarContent"] = ""
+       ctx.Data["footerPresent"] = false
+       ctx.Data["footerContent"] = ""
+}
+
 // Wiki renders single wiki page
 func Wiki(ctx *context.Context) {
        ctx.Data["PageIsWiki"] = true
@@ -221,7 +312,7 @@ func Wiki(ctx *context.Context) {
                return
        }
 
-       wikiRepo, entry := renderWikiPage(ctx, true)
+       wikiRepo, entry := renderViewPage(ctx)
        if ctx.Written() {
                return
        }
@@ -247,6 +338,39 @@ func Wiki(ctx *context.Context) {
        ctx.HTML(200, tplWikiView)
 }
 
+// WikiRevision renders file revision list of wiki page
+func WikiRevision(ctx *context.Context) {
+       ctx.Data["PageIsWiki"] = true
+       ctx.Data["CanWriteWiki"] = ctx.Repo.CanWrite(models.UnitTypeWiki) && !ctx.Repo.Repository.IsArchived
+
+       if !ctx.Repo.Repository.HasWiki() {
+               ctx.Data["Title"] = ctx.Tr("repo.wiki")
+               ctx.HTML(200, tplWikiStart)
+               return
+       }
+
+       wikiRepo, entry := renderRevisionPage(ctx)
+       if ctx.Written() {
+               return
+       }
+       if entry == nil {
+               ctx.Data["Title"] = ctx.Tr("repo.wiki")
+               ctx.HTML(200, tplWikiStart)
+               return
+       }
+
+       // Get last change information.
+       wikiPath := entry.Name()
+       lastCommit, err := wikiRepo.GetCommitByPath(wikiPath)
+       if err != nil {
+               ctx.ServerError("GetCommitByPath", err)
+               return
+       }
+       ctx.Data["Author"] = lastCommit.Author
+
+       ctx.HTML(200, tplWikiRevision)
+}
+
 // WikiPages render wiki pages list page
 func WikiPages(ctx *context.Context) {
        if !ctx.Repo.Repository.HasWiki() {
@@ -399,7 +523,7 @@ func EditWiki(ctx *context.Context) {
                return
        }
 
-       renderWikiPage(ctx, false)
+       renderEditPage(ctx)
        if ctx.Written() {
                return
        }
index 744088a9d7b1e27e03f598ca445c89f5b6443ba2..ec57e8f5fdac7b9c8a65162e4fd5bf3b514cf0fd 100644 (file)
@@ -804,6 +804,7 @@ func RegisterRoutes(m *macaron.Macaron) {
                m.Group("/wiki", func() {
                        m.Get("/?:page", repo.Wiki)
                        m.Get("/_pages", repo.WikiPages)
+                       m.Get("/:page/_revision", repo.WikiRevision)
 
                        m.Group("", func() {
                                m.Combo("/_new").Get(repo.NewWiki).
diff --git a/templates/repo/wiki/revision.tmpl b/templates/repo/wiki/revision.tmpl
new file mode 100644 (file)
index 0000000..a64c386
--- /dev/null
@@ -0,0 +1,104 @@
+{{template "base/head" .}}
+<div class="repository wiki revisions">
+       {{template "repo/header" .}}
+       {{ $title := .title}}
+       <div class="ui container">
+               <div class="ui stackable grid">
+                       <div class="ui eight wide column text right">
+                               <div class="ui action small input" id="clone-panel">
+                                       {{if not $.DisableHTTP}}
+                                               <button class="ui basic clone button" id="repo-clone-https" data-link="{{.WikiCloneLink.HTTPS}}">
+                                                       {{if UseHTTPS}}HTTPS{{else}}HTTP{{end}}
+                                               </button>
+                                       {{end}}
+                                       {{if and (not $.DisableSSH) (or $.IsSigned $.ExposeAnonSSH)}}
+                                               <button class="ui basic clone button" id="repo-clone-ssh" data-link="{{.WikiCloneLink.SSH}}">
+                                                       SSH
+                                               </button>
+                                       {{end}}
+                                       {{if not $.DisableHTTP}}
+                                               <input id="repo-clone-url" value="{{$.WikiCloneLink.HTTPS}}" readonly>
+                                       {{else if and (not $.DisableSSH) (or $.IsSigned $.ExposeAnonSSH)}}
+                                               <input id="repo-clone-url" value="{{$.WikiCloneLink.SSH}}" readonly>
+                                       {{end}}
+                                       {{if or ((not $.DisableHTTP) (and (not $.DisableSSH) (or $.IsSigned $.ExposeAnonSSH)))}}
+                                               <button class="ui basic icon button poping up clipboard" id="clipboard-btn" data-original="{{.i18n.Tr "repo.copy_link"}}" data-success="{{.i18n.Tr "repo.copy_link_success"}}" data-error="{{.i18n.Tr "repo.copy_link_error"}}" data-content="{{.i18n.Tr "repo.copy_link"}}" data-variation="inverted tiny" data-clipboard-target="#repo-clone-url">
+                                                       <i class="octicon octicon-clippy"></i>
+                                               </button>
+                                       {{end}}
+                               </div>
+                       </div>
+                       <div class="ui header eight wide column">
+                               <a class="file-revisions-btn ui basic button" title="{{.i18n.Tr "repo.wiki.back_to_wiki"}}" href="{{.RepoLink}}/wiki/{{.PageURL}}" ><span>{{.revision}}</span> <i class="fa fa-fw fa-file-text-o"></i></a>
+                               {{$title}}
+                               <div class="ui sub header">
+                                       {{$timeSince := TimeSince .Author.When $.Lang}}
+                                       {{.i18n.Tr "repo.wiki.last_commit_info" .Author.Name $timeSince | Safe}}
+                               </div>
+                       </div>
+               </div>
+               <h2 class="ui top header">{{.i18n.Tr "repo.wiki.wiki_page_revisions"}}</h2>
+               <div class="ui" style="margin-top: 1rem;">
+                       <h4 class="ui top attached header">
+                               <div class="ui stackable grid">
+                                       <div class="sixteen wide column">
+                                               {{.CommitCount}} {{.i18n.Tr "repo.commits.commits"}}
+                                       </div>
+                               </div>
+                       </h4>
+
+                       {{if and .Commits (gt .CommitCount 0)}}
+                               <div class="ui attached table segment">
+                                       <table class="ui very basic striped fixed table single line" id="commits-table">
+                                               <thead>
+                                                       <tr>
+                                                               <th class="eight wide">{{.i18n.Tr "repo.commits.author"}}</th>
+                                                               <th class="four wide sha">SHA1</th>
+                                                               <th class="four wide">{{.i18n.Tr "repo.commits.date"}}</th>
+                                                       </tr>
+                                               </thead>
+                                               <tbody class="commit-list">
+                                                       {{ $r:= List .Commits}}
+                                                       {{range $r}}
+                                                               <tr>
+                                                                       <td class="author">
+                                                                               {{if .User}}
+                                                                                 {{if .User.FullName}}
+                                                                                       <img class="ui avatar image" src="{{.User.RelAvatarLink}}" alt=""/>&nbsp;&nbsp;<a href="{{AppSubUrl}}/{{.User.Name}}">{{.User.FullName}}</a>
+                                                                                 {{else}}
+                                                                                       <img class="ui avatar image" src="{{.User.RelAvatarLink}}" alt=""/>&nbsp;&nbsp;<a href="{{AppSubUrl}}/{{.User.Name}}">{{.Author.Name}}</a>
+                                                                                 {{end}}
+                                                                               {{else}}
+                                                                                       <img class="ui avatar image" src="{{AvatarLink .Author.Email}}" alt=""/>&nbsp;&nbsp;{{.Author.Name}}
+                                                                               {{end}}
+                                                                       </td>
+                                                                       <td class="sha">
+                                                                               <label rel="nofollow" class="ui sha label {{if .Signature}} isSigned {{if .Verification.Verified }} isVerified {{end}}{{end}}">
+                                                                                       {{ShortSha .ID.String}}
+                                                                                       {{if .Signature}}
+                                                                                               <div class="ui detail icon button">
+                                                                                                       {{if .Verification.Verified}}
+                                                                                                               <i title="{{.Verification.Reason}}" class="lock green icon"></i>
+                                                                                                       {{else}}
+                                                                                                               <i title="{{$.i18n.Tr .Verification.Reason}}" class="unlock icon"></i>
+                                                                                                       {{end}}
+                                                                                               </div>
+                                                                                       {{end}}
+                                                                               </label>
+                                                                       </td>
+                                                                       <td class="grey text">{{TimeSince .Author.When $.Lang}}</td>
+                                                               </tr>
+                                                       {{end}}
+                                               </tbody>
+                                       </table>
+                               </div>
+                       {{end}}
+
+                       {{template "base/paginate" .}}
+
+               </div>
+       </div>
+</div>
+
+
+{{template "base/footer" .}}
index dd2de2a041380256e2d03d897d16fb914c6d9934..f775ac9429200bbbd74b990cd8be5f3845b274b3 100644 (file)
@@ -56,6 +56,7 @@
                <div class="ui dividing header">
                        <div class="ui stackable grid">
                                <div class="eight wide column">
+                                       <a class="file-revisions-btn ui basic button" title="{{.i18n.Tr "repo.wiki.file_revision"}}" href="{{.RepoLink}}/wiki/{{.PageURL}}/_revision" ><span>{{.CommitCount}}</span> <i class="fa fa-fw fa-history"></i></a>
                                        {{$title}}
                                        <div class="ui sub header">
                                                {{$timeSince := TimeSince .Author.When $.Lang}}