Parcourir la source

Merge pull request #81 from achilleas-k/doi-badge-button-redesign

Repository page header redesign II: The reredesign
Michael Sonntag il y a 5 ans
Parent
commit
6958842319

+ 76 - 42
internal/context/context_gin.go

@@ -1,61 +1,95 @@
 package context
 package context
 
 
 import (
 import (
-	"os"
-	"path"
 	"strings"
 	"strings"
 
 
+	"github.com/G-Node/git-module"
+	"github.com/G-Node/gogs/internal/db"
 	"github.com/G-Node/gogs/internal/setting"
 	"github.com/G-Node/gogs/internal/setting"
-	"github.com/G-Node/gogs/internal/tool"
-	"github.com/unknwon/com"
+	"github.com/G-Node/libgin/libgin"
 	log "gopkg.in/clog.v1"
 	log "gopkg.in/clog.v1"
 )
 )
 
 
-// readNotice checks if a notice file exists and loads the message to display
-// on all pages.
-func readNotice(c *Context) {
-
-	fileloc := path.Join(setting.CustomPath, "notice")
-	var maxlen int64 = 1024
-
-	if !com.IsExist(fileloc) {
-		return
+// getRepoDOI returns the DOI for the repository based on the following rules:
+// - if the repository belongs to the DOI user and has a tag that matches the
+// DOI prefix, returns the tag.
+// - if the repo is forked by the DOI user, check the DOI fork for the tag as above.
+// - if the repo is forked by the DOI user and the fork doesn't have a tag,
+// returns the (old-style) calculated DOI, based on the hash of the repository
+// path.
+// - An empty string is returned if it is not not forked by the DOI user.
+// If an error occurs at any point, returns an empty string (the error is logged).
+// Tag retrieval is allowed to fail and falls back on the hashed DOI method.
+func getRepoDOI(c *Context) string {
+	repo := c.Repo.Repository
+	var doiFork *db.Repository
+	if repo.Owner.Name == "doi" {
+		doiFork = repo
+	} else {
+		if forks, err := repo.GetForks(); err == nil {
+			for _, fork := range forks {
+				if fork.MustOwner().Name == "doi" {
+					doiFork = fork
+					break
+				}
+			}
+		} else {
+			log.Error(2, "failed to get forks for repository %q (%d): %v", repo.FullName(), repo.ID, err)
+			return ""
+		}
 	}
 	}
 
 
-	log.Trace("Found notice file")
-	fp, err := os.Open(fileloc)
-	if err != nil {
-		log.Error(2, "Failed to open notice file %s: %v", fileloc, err)
-		return
+	if doiFork == nil {
+		// not owned or forked by DOI, so not registered
+		return ""
 	}
 	}
-	defer fp.Close()
 
 
-	finfo, err := fp.Stat()
-	if err != nil {
-		log.Error(2, "Failed to stat notice file %s: %v", fileloc, err)
-		return
-	}
+	// check the DOI fork for a tag that matches our DOI prefix
+	// if multiple exit, get the latest one
+	doiBase := setting.DOI.Base
 
 
-	if finfo.Size() > maxlen { // Refuse to print very long messages
-		log.Error(2, "Notice file %s size too large [%d > %d]: refusing to render", fileloc, finfo.Size(), maxlen)
-		return
-	}
-
-	buf := make([]byte, maxlen)
-	n, err := fp.Read(buf)
+	doiForkGit, err := git.OpenRepository(doiFork.RepoPath())
 	if err != nil {
 	if err != nil {
-		log.Error(2, "Failed to read notice file: %v", err)
-		return
+		log.Error(2, "failed to open git repository at %q (%d): %v", doiFork.RepoPath(), doiFork.ID, err)
+		return ""
 	}
 	}
-	buf = buf[:n]
-
-	if !tool.IsTextFile(buf) {
-		log.Error(2, "Notice file %s does not appear to be a text file: aborting", fileloc)
-		return
+	if tags, err := doiForkGit.GetTags(); err == nil {
+		var latestTime int64
+		latestTag := ""
+		for _, tagName := range tags {
+			if strings.Contains(tagName, doiBase) {
+				tag, err := doiForkGit.GetTag(tagName)
+				if err != nil {
+					// log the error and continue to the next tag
+					log.Error(2, "failed to get information for tag %q for repository at %q: %v", tagName, doiForkGit.Path, err)
+					continue
+				}
+				commit, err := tag.Commit()
+				if err != nil {
+					// log the error and continue to the next tag
+					log.Error(2, "failed to get commit for tag %q for repository at %q: %v", tagName, doiForkGit.Path, err)
+					continue
+				}
+				commitTime := commit.Committer.When.Unix()
+				if commitTime > latestTime {
+					latestTag = tagName
+					latestTime = commitTime
+				}
+				return latestTag
+			}
+		}
+	} else {
+		// this shouldn't happen even if there are no tags
+		// log the error, but fall back to the old method anyway
+		log.Error(2, "failed to get tags for repository at %q: %v", doiForkGit.Path, err)
 	}
 	}
 
 
-	noticetext := strings.SplitN(string(buf), "\n", 2)
-	c.Data["HasNotice"] = true
-	c.Data["NoticeTitle"] = noticetext[0]
-	c.Data["NoticeMessage"] = noticetext[1]
+	// Has DOI fork but isn't tagged: return old style has-based DOI
+	repoPath := repo.FullName()
+	// get base repo name if it's a DOI fork
+	if c.Repo.Repository.IsFork && c.Repo.Owner.Name == "doi" {
+		repoPath = c.Repo.Repository.BaseRepo.FullName()
+	}
+	uuid := libgin.RepoPathToUUID(repoPath)
+	return doiBase + uuid[:6]
 }
 }

+ 8 - 4
internal/context/repo.go

@@ -6,17 +6,16 @@ package context
 
 
 import (
 import (
 	"fmt"
 	"fmt"
-	"io/ioutil"
-	"strings"
-
 	"gopkg.in/editorconfig/editorconfig-core-go.v1"
 	"gopkg.in/editorconfig/editorconfig-core-go.v1"
 	"gopkg.in/macaron.v1"
 	"gopkg.in/macaron.v1"
+	"io/ioutil"
+	"strings"
 
 
 	"github.com/G-Node/git-module"
 	"github.com/G-Node/git-module"
-
 	"github.com/G-Node/gogs/internal/db"
 	"github.com/G-Node/gogs/internal/db"
 	"github.com/G-Node/gogs/internal/db/errors"
 	"github.com/G-Node/gogs/internal/db/errors"
 	"github.com/G-Node/gogs/internal/setting"
 	"github.com/G-Node/gogs/internal/setting"
+	"github.com/G-Node/libgin/libgin"
 )
 )
 
 
 type PullRequest struct {
 type PullRequest struct {
@@ -270,6 +269,11 @@ func RepoAssignment(pages ...bool) macaron.Handler {
 		c.Data["CommitID"] = c.Repo.CommitID
 		c.Data["CommitID"] = c.Repo.CommitID
 
 
 		c.Data["IsGuest"] = !c.Repo.HasAccess()
 		c.Data["IsGuest"] = !c.Repo.HasAccess()
+
+		if doi := getRepoDOI(c); doi != "" && libgin.IsRegisteredDOI(doi) {
+			c.Data["DOI"] = doi
+		}
+
 	}
 	}
 }
 }
 
 

+ 3 - 90
internal/route/repo/repo_gin.go

@@ -14,7 +14,6 @@ import (
 
 
 	"github.com/G-Node/git-module"
 	"github.com/G-Node/git-module"
 	"github.com/G-Node/gogs/internal/context"
 	"github.com/G-Node/gogs/internal/context"
-	"github.com/G-Node/gogs/internal/db"
 	"github.com/G-Node/gogs/internal/setting"
 	"github.com/G-Node/gogs/internal/setting"
 	"github.com/G-Node/gogs/internal/tool"
 	"github.com/G-Node/gogs/internal/tool"
 	"github.com/G-Node/libgin/libgin"
 	"github.com/G-Node/libgin/libgin"
@@ -94,17 +93,15 @@ func readDataciteFile(entry *git.TreeEntry, c *context.Context) {
 		return
 		return
 	}
 	}
 	c.Data["DOIInfo"] = &doiInfo
 	c.Data["DOIInfo"] = &doiInfo
-
-	if doi := getRepoDOI(c); doi != "" && libgin.IsRegisteredDOI(doi) {
-		c.Data["DOI"] = doi
-	}
-
 	c.Data["IsDOIReady"] = isDOIReady(c)
 	c.Data["IsDOIReady"] = isDOIReady(c)
 }
 }
 
 
 // True if repository is not Private, is not registered, or is registered and
 // True if repository is not Private, is not registered, or is registered and
 // has changes.
 // has changes.
 func isDOIReady(c *context.Context) bool {
 func isDOIReady(c *context.Context) bool {
+	if hasDC, ok := c.Data["HasDatacite"]; !ok || !hasDC.(bool) {
+		return false
+	}
 	dbrepo := c.Repo.Repository
 	dbrepo := c.Repo.Repository
 	gitrepo := c.Repo.GitRepo
 	gitrepo := c.Repo.GitRepo
 
 
@@ -139,90 +136,6 @@ func isDOIReady(c *context.Context) bool {
 	return !dbrepo.IsPrivate && !headIsRegistered
 	return !dbrepo.IsPrivate && !headIsRegistered
 }
 }
 
 
-// getRepoDOI returns the DOI for the repository based on the following rules:
-// - if the repository belongs to the DOI user and has a tag that matches the
-// DOI prefix, returns the tag.
-// - if the repo is forked by the DOI user, check the DOI fork for the tag as above.
-// - if the repo is forked by the DOI user and the fork doesn't have a tag,
-// returns the (old-style) calculated DOI, based on the hash of the repository
-// path.
-// - An empty string is returned if it is not not forked by the DOI user.
-// If an error occurs at any point, returns an empty string (the error is logged).
-// Tag retrieval is allowed to fail and falls back on the hashed DOI method.
-func getRepoDOI(c *context.Context) string {
-	repo := c.Repo.Repository
-	var doiFork *db.Repository
-	if repo.Owner.Name == "doi" {
-		doiFork = repo
-	} else {
-		if forks, err := repo.GetForks(); err == nil {
-			for _, fork := range forks {
-				if fork.MustOwner().Name == "doi" {
-					doiFork = fork
-					break
-				}
-			}
-		} else {
-			log.Error(2, "failed to get forks for repository %q (%d): %v", repo.FullName(), repo.ID, err)
-			return ""
-		}
-	}
-
-	if doiFork == nil {
-		// not owned or forked by DOI, so not registered
-		return ""
-	}
-
-	// check the DOI fork for a tag that matches our DOI prefix
-	// if multiple exit, get the latest one
-	doiBase := setting.DOI.Base
-
-	doiForkGit, err := git.OpenRepository(doiFork.RepoPath())
-	if err != nil {
-		log.Error(2, "failed to open git repository at %q (%d): %v", doiFork.RepoPath(), doiFork.ID, err)
-		return ""
-	}
-	if tags, err := doiForkGit.GetTags(); err == nil {
-		var latestTime int64
-		latestTag := ""
-		for _, tagName := range tags {
-			if strings.Contains(tagName, doiBase) {
-				tag, err := doiForkGit.GetTag(tagName)
-				if err != nil {
-					// log the error and continue to the next tag
-					log.Error(2, "failed to get information for tag %q for repository at %q: %v", tagName, doiForkGit.Path, err)
-					continue
-				}
-				commit, err := tag.Commit()
-				if err != nil {
-					// log the error and continue to the next tag
-					log.Error(2, "failed to get commit for tag %q for repository at %q: %v", tagName, doiForkGit.Path, err)
-					continue
-				}
-				commitTime := commit.Committer.When.Unix()
-				if commitTime > latestTime {
-					latestTag = tagName
-					latestTime = commitTime
-				}
-				return latestTag
-			}
-		}
-	} else {
-		// this shouldn't happen even if there are no tags
-		// log the error, but fall back to the old method anyway
-		log.Error(2, "failed to get tags for repository at %q: %v", doiForkGit.Path, err)
-	}
-
-	// Has DOI fork but isn't tagged: return old style has-based DOI
-	repoPath := repo.FullName()
-	// get base repo name if it's a DOI fork
-	if c.Repo.Repository.IsFork && c.Repo.Owner.Name == "doi" {
-		repoPath = c.Repo.Repository.BaseRepo.FullName()
-	}
-	uuid := libgin.RepoPathToUUID(repoPath)
-	return doiBase + uuid[:6]
-}
-
 // resolveAnnexedContent takes a buffer with the contents of a git-annex
 // resolveAnnexedContent takes a buffer with the contents of a git-annex
 // pointer file and an io.Reader for the underlying file and returns the
 // pointer file and an io.Reader for the underlying file and returns the
 // corresponding buffer and a bufio.Reader for the underlying content file.
 // corresponding buffer and a bufio.Reader for the underlying content file.

+ 7 - 2
public/css/custom.css

@@ -237,7 +237,7 @@ figure figcaption {
   color: white;
   color: white;
   border-top-left-radius: 0.28571429rem;
   border-top-left-radius: 0.28571429rem;
   border-bottom-left-radius: 0.28571429rem;
   border-bottom-left-radius: 0.28571429rem;
-  padding: 0.833em 1em;
+  padding: 0.5em 1.5em;
 }
 }
 .gin.doinr {
 .gin.doinr {
   background-color: #2185D0;
   background-color: #2185D0;
@@ -245,7 +245,7 @@ figure figcaption {
   color: white;
   color: white;
   border-top-right-radius: 0.28571429rem;
   border-top-right-radius: 0.28571429rem;
   border-bottom-right-radius: 0.28571429rem;
   border-bottom-right-radius: 0.28571429rem;
-  padding: 0.833em 1em;
+  padding: 0.5em 1.5em;
 }
 }
 .ui.image.label.nobg {
 .ui.image.label.nobg {
   background: none;
   background: none;
@@ -375,3 +375,8 @@ textarea#description {
   font-size: 1rem;
   font-size: 1rem;
   vertical-align: middle;
   vertical-align: middle;
 }
 }
+.ui.header .button {
+    height: 2em;
+    vertical-align: middle;
+    padding: 0.5em 1.5em;
+}

+ 1 - 1
templates/repo/header.tmpl

@@ -20,6 +20,7 @@
 
 
 					{{if not $.IsGuest}}
 					{{if not $.IsGuest}}
 						<div class="ui right">
 						<div class="ui right">
+							{{template "repo/header_gin" $}}
 							<form class="display inline" action="{{$.RepoLink}}/action/{{if $.IsWatchingRepo}}un{{end}}watch?redirect_to={{$.Link}}" method="POST">
 							<form class="display inline" action="{{$.RepoLink}}/action/{{if $.IsWatchingRepo}}un{{end}}watch?redirect_to={{$.Link}}" method="POST">
 								{{$.CSRFTokenHTML}}
 								{{$.CSRFTokenHTML}}
 								<div class="ui labeled button" tabindex="0">
 								<div class="ui labeled button" tabindex="0">
@@ -59,7 +60,6 @@
 		</div><!-- end grid -->
 		</div><!-- end grid -->
 	</div><!-- end container -->
 	</div><!-- end container -->
 {{end}}
 {{end}}
-{{template "repo/header_gin" .}}
 {{if not .IsDiffCompare}}
 {{if not .IsDiffCompare}}
 	<div class="ui tabs container">
 	<div class="ui tabs container">
 		<div class="ui tabular menu navbar">
 		<div class="ui tabular menu navbar">

+ 28 - 36
templates/repo/header_gin.tmpl

@@ -1,37 +1,29 @@
-<div class="ui container"><!-- start container -->
-	<div class="ui vertically padded grid head"><!-- start grid -->
-		<div class="column"><!-- start column -->
-			<div class="ui header">
-				{{if not $.IsGuest}}
-					<div class="ui right">
-						{{if and $.IsRepositoryAdmin .PageIsRepoHome}}
-							{{if $.IsDOIReady}} {{/* Ready to (re)register: Show button */}}
-							<div class="ui labeled button" tabindex="0">
-								<a class="ui basic button" href="/{{.Repository.Owner.Name}}/{{.Repository.Name}}/doi"><i class="octicon octicon-squirrel"></i> Request DOI</a>
-							</div>
-							{{else if not $.DOI}} {{/*Link to registration instructions*/}}
-								<div class="ui labeled button	" tabindex="0">
-									<a class="ui basic button" data-tooltip="Your repository does not fulfill all requirements for a DOI yet. Click to get instructions." data-position="bottom center" href="/G-Node/Info/wiki/DOI">
-										<i class="octicon octicon-squirrel"></i> How to publish
-									</a>
-									<a class="ui basic label" href="{{$.RepoLink}}/_add/{{EscapePound $.BranchName}}/datacite.yml" data-tooltip="Add datacite file" data-position="bottom center">
-										<i class="octicon octicon-file"></i>
-									</a>
-								</div>
-							{{end}} {{/* End registration button */}}
-						{{end}} {{/* Admin section */}}
-							
-						{{if $.DOI}} {{/* Registered repo: Show DOI badge */}}
-							<div class="nobg ui image label">
-								<a href="https://doi.org/{{$.DOI}}">
-									<div class="gin doi">DOI</div>
-								</a>
-								<div class="gin doinr">{{$.DOI}}</div>
-							</div>
-						{{end}} {{/* End DOI badge */}}
+{{if or $.DOI $.IsRepositoryAdmin}} {{/* Show DOI buttons or badge */}}
+					{{if $.IsRepositoryAdmin}}
+						{{if $.IsDOIReady}} {{/* Ready to (re)register: Show button */}}
+							<a class="ui basic button" href="/{{.Repository.Owner.Name}}/{{.Repository.Name}}/doi"><i class="octicon octicon-squirrel"></i> Request {{if $.DOI}}New{{end}} DOI</a>
+						{{else if not $.DOI}} {{/*Link to registration instructions*/}}
+							<a class="ui basic button" data-tooltip="Your repository does not fulfill all requirements for a DOI yet. Click to get instructions." data-position="bottom center" href="/G-Node/Info/wiki/DOI"><i class="octicon octicon-squirrel"></i> How to publish</a>
+							<a class="ui basic button" href="{{$.RepoLink}}/_add/{{EscapePound $.BranchName}}/datacite.yml" data-tooltip="Add datacite file" data-position="bottom center"><i class="octicon octicon-file">Add DataCite file</i></a>
+						{{end}} {{/* End registration button */}}
+					{{end}} {{/* Admin section */}}
+					{{if $.DOI}} {{/* Registered repo: Show DOI badge */}}
+						<div class="ui labeled button" tabindex="0">
+							<a href="https://doi.org/{{$.DOI}}">
+								<div class="gin doi">DOI</div>
+							</a>
+							<div class="gin doinr">{{$.DOI}}</div>
+						</div>
+					{{end}} {{/* End DOI badge */}}
+					{{/* Close original header divs and create second row below for original buttons */}}
 					</div>
 					</div>
-				{{end}}
-			</div>
-		</div>
-	</div>
-</div>
+				</div>
+			</div><!--- end column -->
+		</div><!--- end grid -->
+	</div><!--- end container -->
+	<div class="ui container"><!-- start container -->
+		<div class="ui vertically padded grid head"><!-- start grid -->
+			<div class="column"><!-- start column -->
+				<div class="ui header">
+					<div class="ui right">
+{{end}}