wiki - page revisions list (#7369)
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>
This commit is contained in:
		
							parent
							
								
									d7211c5b5d
								
							
						
					
					
						commit
						e5b247ea8e
					
				
					 7 changed files with 341 additions and 71 deletions
				
			
		|  | @ -1034,6 +1034,9 @@ 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.edit_page_button = Edit | ||||||
| wiki.new_page_button = New Page | 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_button = Delete Page | ||||||
| wiki.delete_page_notice_1 = Deleting the wiki page '%s' cannot be undone. Continue? | 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. | wiki.page_already_exists = A wiki page with the same name already exists. | ||||||
|  |  | ||||||
|  | @ -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 tr{border-top:0} | ||||||
| .markdown:not(code) .csv-data th{font-weight:700;background:#f8f8f8;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} | .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} | .home .logo{max-width:220px} | ||||||
| @media only screen and (max-width:767px){.home .hero h1{font-size:3.5em} | @media only screen and (max-width:767px){.home .hero h1{font-size:3.5em} | ||||||
| .home .hero h2{font-size:2em} | .home .hero h2{font-size:2em} | ||||||
|  |  | ||||||
|  | @ -494,3 +494,35 @@ | ||||||
|         padding-left: 2em; |         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; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -23,10 +23,11 @@ import ( | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| const ( | const ( | ||||||
| 	tplWikiStart base.TplName = "repo/wiki/start" | 	tplWikiStart    base.TplName = "repo/wiki/start" | ||||||
| 	tplWikiView  base.TplName = "repo/wiki/view" | 	tplWikiView     base.TplName = "repo/wiki/view" | ||||||
| 	tplWikiNew   base.TplName = "repo/wiki/new" | 	tplWikiRevision base.TplName = "repo/wiki/revision" | ||||||
| 	tplWikiPages base.TplName = "repo/wiki/pages" | 	tplWikiNew      base.TplName = "repo/wiki/new" | ||||||
|  | 	tplWikiPages    base.TplName = "repo/wiki/pages" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // MustEnableWiki check if wiki is enabled, if external then redirect
 | // 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
 | // wikiContentsByName returns the contents of a wiki page, along with a boolean
 | ||||||
| // indicating whether the page exists. Writes to ctx if an error occurs.
 | // indicating whether the page exists. Writes to ctx if an error occurs.
 | ||||||
| func wikiContentsByName(ctx *context.Context, commit *git.Commit, wikiName string) ([]byte, bool) { | func wikiContentsByName(ctx *context.Context, commit *git.Commit, wikiName string) ([]byte, *git.TreeEntry, string, bool) { | ||||||
| 	entry, err := findEntryForFile(commit, models.WikiNameToFilename(wikiName)) | 	var entry *git.TreeEntry | ||||||
| 	if err != nil { | 	var err error | ||||||
|  | 	pageFilename := models.WikiNameToFilename(wikiName) | ||||||
|  | 	if entry, err = findEntryForFile(commit, pageFilename); err != nil { | ||||||
| 		ctx.ServerError("findEntryForFile", err) | 		ctx.ServerError("findEntryForFile", err) | ||||||
| 		return nil, false | 		return nil, nil, "", false | ||||||
| 	} else if entry == nil { | 	} 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) | 	wikiRepo, commit, err := findWikiRepoCommit(ctx) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		if !git.IsErrNotExist(err) { | 		if !git.IsErrNotExist(err) { | ||||||
|  | @ -128,88 +131,176 @@ func renderWikiPage(ctx *context.Context, isViewPage bool) (*git.Repository, *gi | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// Get page list.
 | 	// Get page list.
 | ||||||
| 	if isViewPage { | 	entries, err := commit.ListEntries() | ||||||
| 		entries, err := commit.ListEntries() | 	if err != nil { | ||||||
| 		if err != nil { | 		ctx.ServerError("ListEntries", err) | ||||||
| 			ctx.ServerError("ListEntries", err) | 		return nil, nil | ||||||
| 			return nil, nil |  | ||||||
| 		} |  | ||||||
| 		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" { |  | ||||||
| 				continue |  | ||||||
| 			} |  | ||||||
| 			pages = append(pages, PageMeta{ |  | ||||||
| 				Name:   wikiName, |  | ||||||
| 				SubURL: models.WikiNameToSubURL(wikiName), |  | ||||||
| 			}) |  | ||||||
| 		} |  | ||||||
| 		ctx.Data["Pages"] = pages |  | ||||||
| 	} | 	} | ||||||
|  | 	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" { | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
|  | 		pages = append(pages, PageMeta{ | ||||||
|  | 			Name:   wikiName, | ||||||
|  | 			SubURL: models.WikiNameToSubURL(wikiName), | ||||||
|  | 		}) | ||||||
|  | 	} | ||||||
|  | 	ctx.Data["Pages"] = pages | ||||||
| 
 | 
 | ||||||
|  | 	// get requested pagename
 | ||||||
| 	pageName := models.NormalizeWikiName(ctx.Params(":page")) | 	pageName := models.NormalizeWikiName(ctx.Params(":page")) | ||||||
| 	if len(pageName) == 0 { | 	if len(pageName) == 0 { | ||||||
| 		pageName = "Home" | 		pageName = "Home" | ||||||
| 	} | 	} | ||||||
| 	ctx.Data["PageURL"] = models.WikiNameToSubURL(pageName) | 	ctx.Data["PageURL"] = models.WikiNameToSubURL(pageName) | ||||||
| 
 |  | ||||||
| 	ctx.Data["old_title"] = pageName | 	ctx.Data["old_title"] = pageName | ||||||
| 	ctx.Data["Title"] = pageName | 	ctx.Data["Title"] = pageName | ||||||
| 	ctx.Data["title"] = pageName | 	ctx.Data["title"] = pageName | ||||||
| 	ctx.Data["RequireHighlightJS"] = true | 	ctx.Data["RequireHighlightJS"] = true | ||||||
| 
 | 
 | ||||||
| 	pageFilename := models.WikiNameToFilename(pageName) | 	//lookup filename in wiki - get filecontent, gitTree entry , real filename
 | ||||||
| 	var entry *git.TreeEntry | 	data, entry, pageFilename, noEntry := wikiContentsByName(ctx, commit, pageName) | ||||||
| 	if entry, err = findEntryForFile(commit, pageFilename); err != nil { | 	if noEntry { | ||||||
| 		ctx.ServerError("findEntryForFile", err) |  | ||||||
| 		return nil, nil |  | ||||||
| 	} else if entry == nil { |  | ||||||
| 		ctx.Redirect(ctx.Repo.RepoLink + "/wiki/_pages") | 		ctx.Redirect(ctx.Repo.RepoLink + "/wiki/_pages") | ||||||
|  | 	} | ||||||
|  | 	if entry == nil || ctx.Written() { | ||||||
| 		return nil, nil | 		return nil, nil | ||||||
| 	} | 	} | ||||||
| 	data := wikiContentsByEntry(ctx, entry) | 
 | ||||||
|  | 	sidebarContent, _, _, _ := wikiContentsByName(ctx, commit, "_Sidebar") | ||||||
| 	if ctx.Written() { | 	if ctx.Written() { | ||||||
| 		return nil, nil | 		return nil, nil | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if isViewPage { | 	footerContent, _, _, _ := wikiContentsByName(ctx, commit, "_Footer") | ||||||
| 		sidebarContent, sidebarPresent := wikiContentsByName(ctx, commit, "_Sidebar") | 	if ctx.Written() { | ||||||
| 		if ctx.Written() { | 		return nil, nil | ||||||
| 			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"] = 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"] = "" |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	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 | 	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 | ||||||
|  | 
 | ||||||
|  | 	//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
 | // Wiki renders single wiki page
 | ||||||
| func Wiki(ctx *context.Context) { | func Wiki(ctx *context.Context) { | ||||||
| 	ctx.Data["PageIsWiki"] = true | 	ctx.Data["PageIsWiki"] = true | ||||||
|  | @ -221,7 +312,7 @@ func Wiki(ctx *context.Context) { | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	wikiRepo, entry := renderWikiPage(ctx, true) | 	wikiRepo, entry := renderViewPage(ctx) | ||||||
| 	if ctx.Written() { | 	if ctx.Written() { | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|  | @ -247,6 +338,39 @@ func Wiki(ctx *context.Context) { | ||||||
| 	ctx.HTML(200, tplWikiView) | 	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
 | // WikiPages render wiki pages list page
 | ||||||
| func WikiPages(ctx *context.Context) { | func WikiPages(ctx *context.Context) { | ||||||
| 	if !ctx.Repo.Repository.HasWiki() { | 	if !ctx.Repo.Repository.HasWiki() { | ||||||
|  | @ -399,7 +523,7 @@ func EditWiki(ctx *context.Context) { | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	renderWikiPage(ctx, false) | 	renderEditPage(ctx) | ||||||
| 	if ctx.Written() { | 	if ctx.Written() { | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -804,6 +804,7 @@ func RegisterRoutes(m *macaron.Macaron) { | ||||||
| 		m.Group("/wiki", func() { | 		m.Group("/wiki", func() { | ||||||
| 			m.Get("/?:page", repo.Wiki) | 			m.Get("/?:page", repo.Wiki) | ||||||
| 			m.Get("/_pages", repo.WikiPages) | 			m.Get("/_pages", repo.WikiPages) | ||||||
|  | 			m.Get("/:page/_revision", repo.WikiRevision) | ||||||
| 
 | 
 | ||||||
| 			m.Group("", func() { | 			m.Group("", func() { | ||||||
| 				m.Combo("/_new").Get(repo.NewWiki). | 				m.Combo("/_new").Get(repo.NewWiki). | ||||||
|  |  | ||||||
							
								
								
									
										104
									
								
								templates/repo/wiki/revision.tmpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								templates/repo/wiki/revision.tmpl
									
									
									
									
									
										Normal file
									
								
							|  | @ -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=""/>  <a href="{{AppSubUrl}}/{{.User.Name}}">{{.User.FullName}}</a> | ||||||
|  | 										  {{else}} | ||||||
|  | 											<img class="ui avatar image" src="{{.User.RelAvatarLink}}" alt=""/>  <a href="{{AppSubUrl}}/{{.User.Name}}">{{.Author.Name}}</a> | ||||||
|  | 										  {{end}} | ||||||
|  | 										{{else}} | ||||||
|  | 											<img class="ui avatar image" src="{{AvatarLink .Author.Email}}" alt=""/>  {{.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" .}} | ||||||
|  | @ -56,6 +56,7 @@ | ||||||
| 		<div class="ui dividing header"> | 		<div class="ui dividing header"> | ||||||
| 			<div class="ui stackable grid"> | 			<div class="ui stackable grid"> | ||||||
| 				<div class="eight wide column"> | 				<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}} | 					{{$title}} | ||||||
| 					<div class="ui sub header"> | 					<div class="ui sub header"> | ||||||
| 						{{$timeSince := TimeSince .Author.When $.Lang}} | 						{{$timeSince := TimeSince .Author.When $.Lang}} | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue