* Add the tag list page to the release page * Add the tags list view * Add the delete tag way on ui * Not delete tag and clear message when delete a release Signed-off-by: a1012112796 <1012112796@qq.com> * Apply suggestions from code review Co-authored-by: Cirno the Strongest <1447794+CirnoT@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: zeripath <art27@cantab.net> * fix ui * Add to header * ui * permission * ui * Update options/locale/locale_en-US.ini Co-authored-by: Lauris BH <lauris@nix.lv> * tweaks * monospace commit hashes * Add read permission check * fix permission * fix nit * Update web_src/less/_base.less Co-authored-by: silverwind <me@silverwind.io> * ui fixes * title tweaks * fix lint * fix test * fix test and some ui nits * Apply suggestions from code review Co-authored-by: silverwind <me@silverwind.io> Co-authored-by: Cirno the Strongest <1447794+CirnoT@users.noreply.github.com> Co-authored-by: zeripath <art27@cantab.net> Co-authored-by: Lauris BH <lauris@nix.lv> Co-authored-by: silverwind <me@silverwind.io>tags/v1.15.0-dev
@@ -52,7 +52,7 @@ func checkLatestReleaseAndCount(t *testing.T, session *TestSession, repoURL, ver | |||||
htmlDoc := NewHTMLParser(t, resp.Body) | htmlDoc := NewHTMLParser(t, resp.Body) | ||||
labelText := htmlDoc.doc.Find("#release-list > li .meta .label").First().Text() | labelText := htmlDoc.doc.Find("#release-list > li .meta .label").First().Text() | ||||
assert.EqualValues(t, label, labelText) | assert.EqualValues(t, label, labelText) | ||||
titleText := htmlDoc.doc.Find("#release-list > li .detail h3 a").First().Text() | |||||
titleText := htmlDoc.doc.Find("#release-list > li .detail h4 a").First().Text() | |||||
assert.EqualValues(t, version, titleText) | assert.EqualValues(t, version, titleText) | ||||
releaseList := htmlDoc.doc.Find("#release-list > li") | releaseList := htmlDoc.doc.Find("#release-list > li") | ||||
@@ -83,7 +83,7 @@ func TestCreateRelease(t *testing.T) { | |||||
session := loginUser(t, "user2") | session := loginUser(t, "user2") | ||||
createNewRelease(t, session, "/user2/repo1", "v0.0.1", "v0.0.1", false, false) | createNewRelease(t, session, "/user2/repo1", "v0.0.1", "v0.0.1", false, false) | ||||
checkLatestReleaseAndCount(t, session, "/user2/repo1", "v0.0.1", i18n.Tr("en", "repo.release.stable"), 3) | |||||
checkLatestReleaseAndCount(t, session, "/user2/repo1", "v0.0.1", i18n.Tr("en", "repo.release.stable"), 2) | |||||
} | } | ||||
func TestCreateReleasePreRelease(t *testing.T) { | func TestCreateReleasePreRelease(t *testing.T) { | ||||
@@ -92,7 +92,7 @@ func TestCreateReleasePreRelease(t *testing.T) { | |||||
session := loginUser(t, "user2") | session := loginUser(t, "user2") | ||||
createNewRelease(t, session, "/user2/repo1", "v0.0.1", "v0.0.1", true, false) | createNewRelease(t, session, "/user2/repo1", "v0.0.1", "v0.0.1", true, false) | ||||
checkLatestReleaseAndCount(t, session, "/user2/repo1", "v0.0.1", i18n.Tr("en", "repo.release.prerelease"), 3) | |||||
checkLatestReleaseAndCount(t, session, "/user2/repo1", "v0.0.1", i18n.Tr("en", "repo.release.prerelease"), 2) | |||||
} | } | ||||
func TestCreateReleaseDraft(t *testing.T) { | func TestCreateReleaseDraft(t *testing.T) { | ||||
@@ -101,7 +101,7 @@ func TestCreateReleaseDraft(t *testing.T) { | |||||
session := loginUser(t, "user2") | session := loginUser(t, "user2") | ||||
createNewRelease(t, session, "/user2/repo1", "v0.0.1", "v0.0.1", false, true) | createNewRelease(t, session, "/user2/repo1", "v0.0.1", "v0.0.1", false, true) | ||||
checkLatestReleaseAndCount(t, session, "/user2/repo1", "v0.0.1", i18n.Tr("en", "repo.release.draft"), 3) | |||||
checkLatestReleaseAndCount(t, session, "/user2/repo1", "v0.0.1", i18n.Tr("en", "repo.release.draft"), 2) | |||||
} | } | ||||
func TestCreateReleasePaging(t *testing.T) { | func TestCreateReleasePaging(t *testing.T) { | ||||
@@ -53,7 +53,11 @@ func (r *Release) loadAttributes(e Engine) error { | |||||
if r.Publisher == nil { | if r.Publisher == nil { | ||||
r.Publisher, err = getUserByID(e, r.PublisherID) | r.Publisher, err = getUserByID(e, r.PublisherID) | ||||
if err != nil { | if err != nil { | ||||
return err | |||||
if IsErrUserNotExist(err) { | |||||
r.Publisher = NewGhostUser() | |||||
} else { | |||||
return err | |||||
} | |||||
} | } | ||||
} | } | ||||
return getReleaseAttachments(e, r) | return getReleaseAttachments(e, r) | ||||
@@ -808,7 +808,9 @@ org_labels_desc_manage = manage | |||||
milestones = Milestones | milestones = Milestones | ||||
commits = Commits | commits = Commits | ||||
commit = Commit | commit = Commit | ||||
release = Release | |||||
releases = Releases | releases = Releases | ||||
released_this = released this | |||||
file_raw = Raw | file_raw = Raw | ||||
file_history = History | file_history = History | ||||
file_view_raw = View Raw | file_view_raw = View Raw | ||||
@@ -1796,6 +1798,8 @@ diff.protected = Protected | |||||
releases.desc = Track project versions and downloads. | releases.desc = Track project versions and downloads. | ||||
release.releases = Releases | release.releases = Releases | ||||
release.detail = Release details | |||||
release.tags = Tags | |||||
release.new_release = New Release | release.new_release = New Release | ||||
release.draft = Draft | release.draft = Draft | ||||
release.prerelease = Pre-Release | release.prerelease = Pre-Release | ||||
@@ -1818,11 +1822,15 @@ release.publish = Publish Release | |||||
release.save_draft = Save Draft | release.save_draft = Save Draft | ||||
release.edit_release = Update Release | release.edit_release = Update Release | ||||
release.delete_release = Delete Release | release.delete_release = Delete Release | ||||
release.delete_tag = Delete Tag | |||||
release.deletion = Delete Release | release.deletion = Delete Release | ||||
release.deletion_desc = Deleting a release removes its Git tag from the repository. Repository contents and history remain unchanged. Continue? | |||||
release.deletion_desc = Deleting a release only removes it from Gitea. Git tag, repository contents and history remain unchanged. Continue? | |||||
release.deletion_success = The release has been deleted. | release.deletion_success = The release has been deleted. | ||||
release.deletion_tag_desc = Will delete this tag from repository. Repository contents and history remain unchanged. Continue? | |||||
release.deletion_tag_success = The tag has been deleted. | |||||
release.tag_name_already_exist = A release with this tag name already exists. | release.tag_name_already_exist = A release with this tag name already exists. | ||||
release.tag_name_invalid = The tag name is not valid. | release.tag_name_invalid = The tag name is not valid. | ||||
release.tag_already_exist = This tag name already exists. | |||||
release.downloads = Downloads | release.downloads = Downloads | ||||
release.download_count = Downloads: %s | release.download_count = Downloads: %s | ||||
@@ -55,10 +55,26 @@ func calReleaseNumCommitsBehind(repoCtx *context.Repository, release *models.Rel | |||||
// Releases render releases list page | // Releases render releases list page | ||||
func Releases(ctx *context.Context) { | func Releases(ctx *context.Context) { | ||||
ctx.Data["Title"] = ctx.Tr("repo.release.releases") | |||||
releasesOrTags(ctx, false) | |||||
} | |||||
// TagsList render tags list page | |||||
func TagsList(ctx *context.Context) { | |||||
releasesOrTags(ctx, true) | |||||
} | |||||
func releasesOrTags(ctx *context.Context, isTagList bool) { | |||||
ctx.Data["PageIsReleaseList"] = true | ctx.Data["PageIsReleaseList"] = true | ||||
ctx.Data["DefaultBranch"] = ctx.Repo.Repository.DefaultBranch | ctx.Data["DefaultBranch"] = ctx.Repo.Repository.DefaultBranch | ||||
if isTagList { | |||||
ctx.Data["Title"] = ctx.Tr("repo.release.tags") | |||||
ctx.Data["PageIsTagList"] = true | |||||
} else { | |||||
ctx.Data["Title"] = ctx.Tr("repo.release.releases") | |||||
ctx.Data["PageIsTagList"] = false | |||||
} | |||||
writeAccess := ctx.Repo.CanWrite(models.UnitTypeReleases) | writeAccess := ctx.Repo.CanWrite(models.UnitTypeReleases) | ||||
ctx.Data["CanCreateRelease"] = writeAccess && !ctx.Repo.Repository.IsArchived | ctx.Data["CanCreateRelease"] = writeAccess && !ctx.Repo.Repository.IsArchived | ||||
@@ -68,7 +84,7 @@ func Releases(ctx *context.Context) { | |||||
PageSize: convert.ToCorrectPageSize(ctx.QueryInt("limit")), | PageSize: convert.ToCorrectPageSize(ctx.QueryInt("limit")), | ||||
}, | }, | ||||
IncludeDrafts: writeAccess, | IncludeDrafts: writeAccess, | ||||
IncludeTags: true, | |||||
IncludeTags: isTagList, | |||||
} | } | ||||
releases, err := models.GetReleasesByRepoID(ctx.Repo.Repository.ID, opts) | releases, err := models.GetReleasesByRepoID(ctx.Repo.Repository.ID, opts) | ||||
@@ -83,8 +99,7 @@ func Releases(ctx *context.Context) { | |||||
return | return | ||||
} | } | ||||
err = models.GetReleaseAttachments(releases...) | |||||
if err != nil { | |||||
if err = models.GetReleaseAttachments(releases...); err != nil { | |||||
ctx.ServerError("GetReleaseAttachments", err) | ctx.ServerError("GetReleaseAttachments", err) | ||||
return | return | ||||
} | } | ||||
@@ -118,6 +133,7 @@ func Releases(ctx *context.Context) { | |||||
} | } | ||||
ctx.Data["Releases"] = releases | ctx.Data["Releases"] = releases | ||||
ctx.Data["ReleasesNum"] = len(releases) | |||||
pager := context.NewPagination(int(count), opts.PageSize, opts.Page, 5) | pager := context.NewPagination(int(count), opts.PageSize, opts.Page, 5) | ||||
pager.SetDefaultParams(ctx) | pager.SetDefaultParams(ctx) | ||||
@@ -194,6 +210,20 @@ func NewRelease(ctx *context.Context) { | |||||
ctx.Data["Title"] = ctx.Tr("repo.release.new_release") | ctx.Data["Title"] = ctx.Tr("repo.release.new_release") | ||||
ctx.Data["PageIsReleaseList"] = true | ctx.Data["PageIsReleaseList"] = true | ||||
ctx.Data["tag_target"] = ctx.Repo.Repository.DefaultBranch | ctx.Data["tag_target"] = ctx.Repo.Repository.DefaultBranch | ||||
if tagName := ctx.Query("tag"); len(tagName) > 0 { | |||||
rel, err := models.GetRelease(ctx.Repo.Repository.ID, tagName) | |||||
if err != nil && !models.IsErrReleaseNotExist(err) { | |||||
ctx.ServerError("GetRelease", err) | |||||
return | |||||
} | |||||
if rel != nil { | |||||
ctx.Data["tag_name"] = rel.TagName | |||||
ctx.Data["tag_target"] = rel.Target | |||||
ctx.Data["title"] = rel.Title | |||||
ctx.Data["content"] = rel.Note | |||||
} | |||||
} | |||||
ctx.Data["IsAttachmentEnabled"] = setting.Attachment.Enabled | ctx.Data["IsAttachmentEnabled"] = setting.Attachment.Enabled | ||||
upload.AddUploadContext(ctx, "release") | upload.AddUploadContext(ctx, "release") | ||||
ctx.HTML(200, tplReleaseNew) | ctx.HTML(200, tplReleaseNew) | ||||
@@ -354,10 +384,30 @@ func EditReleasePost(ctx *context.Context, form auth.EditReleaseForm) { | |||||
// DeleteRelease delete a release | // DeleteRelease delete a release | ||||
func DeleteRelease(ctx *context.Context) { | func DeleteRelease(ctx *context.Context) { | ||||
if err := releaseservice.DeleteReleaseByID(ctx.QueryInt64("id"), ctx.User, true); err != nil { | |||||
deleteReleaseOrTag(ctx, false) | |||||
} | |||||
// DeleteTag delete a tag | |||||
func DeleteTag(ctx *context.Context) { | |||||
deleteReleaseOrTag(ctx, true) | |||||
} | |||||
func deleteReleaseOrTag(ctx *context.Context, isDelTag bool) { | |||||
if err := releaseservice.DeleteReleaseByID(ctx.QueryInt64("id"), ctx.User, isDelTag); err != nil { | |||||
ctx.Flash.Error("DeleteReleaseByID: " + err.Error()) | ctx.Flash.Error("DeleteReleaseByID: " + err.Error()) | ||||
} else { | } else { | ||||
ctx.Flash.Success(ctx.Tr("repo.release.deletion_success")) | |||||
if isDelTag { | |||||
ctx.Flash.Success(ctx.Tr("repo.release.deletion_tag_success")) | |||||
} else { | |||||
ctx.Flash.Success(ctx.Tr("repo.release.deletion_success")) | |||||
} | |||||
} | |||||
if isDelTag { | |||||
ctx.JSON(200, map[string]interface{}{ | |||||
"redirect": ctx.Repo.RepoLink + "/tags", | |||||
}) | |||||
return | |||||
} | } | ||||
ctx.JSON(200, map[string]interface{}{ | ctx.JSON(200, map[string]interface{}{ | ||||
@@ -896,12 +896,14 @@ func RegisterRoutes(m *macaron.Macaron) { | |||||
// Releases | // Releases | ||||
m.Group("/:username/:reponame", func() { | m.Group("/:username/:reponame", func() { | ||||
m.Get("/tags", repo.TagsList, repo.MustBeNotEmpty, | |||||
reqRepoCodeReader, context.RepoRefByType(context.RepoRefTag)) | |||||
m.Group("/releases", func() { | m.Group("/releases", func() { | ||||
m.Get("/", repo.Releases) | m.Get("/", repo.Releases) | ||||
m.Get("/tag/*", repo.SingleRelease) | m.Get("/tag/*", repo.SingleRelease) | ||||
m.Get("/latest", repo.LatestRelease) | m.Get("/latest", repo.LatestRelease) | ||||
m.Get("/attachments/:uuid", repo.GetAttachment) | m.Get("/attachments/:uuid", repo.GetAttachment) | ||||
}, repo.MustBeNotEmpty, context.RepoRefByType(context.RepoRefTag)) | |||||
}, repo.MustBeNotEmpty, reqRepoReleaseReader, context.RepoRefByType(context.RepoRefTag)) | |||||
m.Group("/releases", func() { | m.Group("/releases", func() { | ||||
m.Get("/new", repo.NewRelease) | m.Get("/new", repo.NewRelease) | ||||
m.Post("/new", bindIgnErr(auth.NewReleaseForm{}), repo.NewReleasePost) | m.Post("/new", bindIgnErr(auth.NewReleaseForm{}), repo.NewReleasePost) | ||||
@@ -909,6 +911,8 @@ func RegisterRoutes(m *macaron.Macaron) { | |||||
m.Post("/attachments", repo.UploadReleaseAttachment) | m.Post("/attachments", repo.UploadReleaseAttachment) | ||||
m.Post("/attachments/remove", repo.DeleteAttachment) | m.Post("/attachments/remove", repo.DeleteAttachment) | ||||
}, reqSignIn, repo.MustBeNotEmpty, context.RepoMustNotBeArchived(), reqRepoReleaseWriter, context.RepoRef()) | }, reqSignIn, repo.MustBeNotEmpty, context.RepoMustNotBeArchived(), reqRepoReleaseWriter, context.RepoRef()) | ||||
m.Post("/tags/delete", repo.DeleteTag, reqSignIn, | |||||
repo.MustBeNotEmpty, context.RepoMustNotBeArchived(), reqRepoCodeWriter, context.RepoRef()) | |||||
m.Group("/releases", func() { | m.Group("/releases", func() { | ||||
m.Get("/edit/*", repo.EditRelease) | m.Get("/edit/*", repo.EditRelease) | ||||
m.Post("/edit/*", bindIgnErr(auth.EditReleaseForm{}), repo.EditReleasePost) | m.Post("/edit/*", bindIgnErr(auth.EditReleaseForm{}), repo.EditReleasePost) | ||||
@@ -157,10 +157,6 @@ func DeleteReleaseByID(id int64, doer *models.User, delTag bool) error { | |||||
} | } | ||||
} else { | } else { | ||||
rel.IsTag = true | rel.IsTag = true | ||||
rel.IsDraft = false | |||||
rel.IsPrerelease = false | |||||
rel.Title = "" | |||||
rel.Note = "" | |||||
if err = models.UpdateRelease(models.DefaultDBContext(), rel); err != nil { | if err = models.UpdateRelease(models.DefaultDBContext(), rel); err != nil { | ||||
return fmt.Errorf("Update: %v", err) | return fmt.Errorf("Update: %v", err) | ||||
@@ -3,20 +3,67 @@ | |||||
{{template "repo/header" .}} | {{template "repo/header" .}} | ||||
<div class="ui container"> | <div class="ui container"> | ||||
{{template "base/alert" .}} | {{template "base/alert" .}} | ||||
<h2 class="ui header"> | |||||
{{.i18n.Tr "repo.release.releases"}} | |||||
{{if .CanCreateRelease}} | |||||
<div class="ui right"> | |||||
<a class="ui small green button" href="{{$.RepoLink}}/releases/new"> | |||||
{{.i18n.Tr "repo.release.new_release"}} | |||||
</a> | |||||
</div> | |||||
<h2 class="ui compact small menu header"> | |||||
{{if .Permission.CanRead $.UnitTypeReleases}} | |||||
<a class="{{if (not .PageIsTagList)}}active{{end}} item" href="{{.RepoLink}}/releases">{{.i18n.Tr "repo.release.releases"}}</a> | |||||
{{end}} | |||||
{{if .Permission.CanRead $.UnitTypeCode}} | |||||
<a class="{{if .PageIsTagList}}active{{end}} item" href="{{.RepoLink}}/tags">{{.i18n.Tr "repo.release.tags"}}</a> | |||||
{{end}} | {{end}} | ||||
</h2> | </h2> | ||||
{{if (and .CanCreateRelease (not .PageIsTagList))}} | |||||
<a class="ui right small green button" href="{{$.RepoLink}}/releases/new"> | |||||
{{.i18n.Tr "repo.release.new_release"}} | |||||
</a> | |||||
{{end}} | |||||
{{if .PageIsTagList}} | |||||
<div class="ui divider"></div> | |||||
{{if gt .ReleasesNum 0}} | |||||
<h4 class="ui top attached header"> | |||||
<div class="five wide column df ac"> | |||||
{{svg "octicon-tag" 16 "mr-2"}}{{.i18n.Tr "repo.release.tags"}} | |||||
</div> | |||||
</h4> | |||||
<div class="ui attached table segment"> | |||||
<table class="ui very basic striped fixed table single line" id="tags-table"> | |||||
<thead></thead> | |||||
<tbody class="tag-list"> | |||||
{{range $idx, $release := .Releases}} | |||||
<tr> | |||||
<td class="tag"> | |||||
<h3 class="release-tag-name mb-3"> | |||||
<a class="df ac" href="{{$.RepoLink}}/src/tag/{{.TagName | EscapePound}}" rel="nofollow">{{.TagName}}</a> | |||||
</h3> | |||||
<div class="download df ac"> | |||||
{{if $.Permission.CanRead $.UnitTypeCode}} | |||||
<a class="mr-3 mono" href="{{$.RepoLink}}/src/commit/{{.Sha1}}" rel="nofollow">{{svg "octicon-git-commit" 16 "mr-2"}}{{ShortSha .Sha1}}</a> | |||||
<a class="mr-3" href="{{$.RepoLink}}/archive/{{.TagName | EscapePound}}.zip" rel="nofollow">{{svg "octicon-file-zip" 16 "mr-2"}}ZIP</a> | |||||
<a class="mr-3" href="{{$.RepoLink}}/archive/{{.TagName | EscapePound}}.tar.gz">{{svg "octicon-file-zip" 16 "mr-2"}}TAR.GZ</a> | |||||
{{if (and $.CanCreateRelease $release.IsTag)}} | |||||
<a class="mr-3" href="{{$.RepoLink}}/releases/new?tag={{.TagName | EscapePound}}">{{svg "octicon-tag" 16 "mr-2"}}{{$.i18n.Tr "repo.release.new_release"}}</a> | |||||
{{end}} | |||||
{{if (and ($.Permission.CanWrite $.UnitTypeCode) $release.IsTag)}} | |||||
<a class="ui red delete-button mr-3" data-url="{{$.RepoLink}}/tags/delete" data-id="{{.ID}}"> | |||||
{{svg "octicon-trashcan" 16 "mr-2"}}{{$.i18n.Tr "repo.release.delete_tag"}} | |||||
</a> | |||||
{{end}} | |||||
{{if (not $release.IsTag)}} | |||||
<a class="mr-3" href="{{$.RepoLink}}/releases/tag/{{.TagName | EscapePound}}">{{svg "octicon-tag" 16 "mr-2"}}{{$.i18n.Tr "repo.release.detail"}}</a> | |||||
{{end}} | |||||
{{end}} | |||||
</div> | |||||
</td> | |||||
</tr> | |||||
{{end}} | |||||
</tbody> | |||||
</table> | |||||
</div> | |||||
{{end}} | |||||
{{else}} | |||||
<ul id="release-list"> | <ul id="release-list"> | ||||
{{range $idx, $release := .Releases}} | {{range $idx, $release := .Releases}} | ||||
<li class="ui grid"> | <li class="ui grid"> | ||||
<div class="ui four wide column meta"> | |||||
<div class="ui four wide column meta mt-2"> | |||||
{{if .IsTag}} | {{if .IsTag}} | ||||
{{if .CreatedUnix}}<span class="time">{{TimeSinceUnix .CreatedUnix $.Lang}}</span>{{end}} | {{if .CreatedUnix}}<span class="time">{{TimeSinceUnix .CreatedUnix $.Lang}}</span>{{end}} | ||||
{{else}} | {{else}} | ||||
@@ -28,7 +75,7 @@ | |||||
<span class="ui green label">{{$.i18n.Tr "repo.release.stable"}}</span> | <span class="ui green label">{{$.i18n.Tr "repo.release.stable"}}</span> | ||||
{{end}} | {{end}} | ||||
<span class="tag text blue"> | <span class="tag text blue"> | ||||
<a href="{{$.RepoLink}}/src/tag/{{.TagName | EscapePound}}" rel="nofollow">{{svg "octicon-tag" 16 "mr-2"}}{{.TagName}}</a> | |||||
<a class="df ac je" href="{{$.RepoLink}}/src/tag/{{.TagName | EscapePound}}" rel="nofollow">{{svg "octicon-tag" 16 "mr-2"}}{{.TagName}}</a> | |||||
</span> | </span> | ||||
<span class="commit"> | <span class="commit"> | ||||
<a class="mono" href="{{$.RepoLink}}/src/commit/{{.Sha1}}" rel="nofollow">{{svg "octicon-git-commit" 16 "mr-2"}}{{ShortSha .Sha1}}</a> | <a class="mono" href="{{$.RepoLink}}/src/commit/{{.Sha1}}" rel="nofollow">{{svg "octicon-git-commit" 16 "mr-2"}}{{ShortSha .Sha1}}</a> | ||||
@@ -57,15 +104,18 @@ | |||||
{{end}} | {{end}} | ||||
</div> | </div> | ||||
{{else}} | {{else}} | ||||
<h3> | |||||
<h4 class="release-list-title df ac"> | |||||
<a href="{{$.RepoLink}}/releases/tag/{{.TagName | EscapePound}}">{{.Title}}</a> | <a href="{{$.RepoLink}}/releases/tag/{{.TagName | EscapePound}}">{{.Title}}</a> | ||||
{{if $.CanCreateRelease}}<small>(<a href="{{$.RepoLink}}/releases/edit/{{.TagName | EscapePound}}" rel="nofollow">{{$.i18n.Tr "repo.release.edit"}}</a>)</small>{{end}} | |||||
</h3> | |||||
{{if $.CanCreateRelease}} | |||||
<small class="ml-2"> | |||||
(<a href="{{$.RepoLink}}/releases/edit/{{.TagName | EscapePound}}" rel="nofollow">{{$.i18n.Tr "repo.release.edit"}}</a>) | |||||
</small> | |||||
{{end}} | |||||
</h4> | |||||
<p class="text grey"> | <p class="text grey"> | ||||
<span class="author"> | <span class="author"> | ||||
{{if .OriginalAuthor}} | {{if .OriginalAuthor}} | ||||
{{svg "octicon-mark-github"}} | |||||
{{.OriginalAuthor}} | |||||
{{svg "octicon-mark-github" 16 "mr-2"}}{{.OriginalAuthor}} | |||||
{{else if .Publisher}} | {{else if .Publisher}} | ||||
<img class="img-10" src="{{.Publisher.RelAvatarLink}}"> | <img class="img-10" src="{{.Publisher.RelAvatarLink}}"> | ||||
<a href="{{AppSubUrl}}/{{.Publisher.Name}}">{{.Publisher.Name}}</a> | <a href="{{AppSubUrl}}/{{.Publisher.Name}}">{{.Publisher.Name}}</a> | ||||
@@ -73,41 +123,44 @@ | |||||
Ghost | Ghost | ||||
{{end}} | {{end}} | ||||
</span> | </span> | ||||
{{if .CreatedUnix}}<span class="time">{{TimeSinceUnix .CreatedUnix $.Lang}}</span> | {{end}} | |||||
<span class="released"> | |||||
{{$.i18n.Tr "repo.released_this"}} | |||||
</span> | |||||
{{if .CreatedUnix}} | |||||
<span class="time">{{TimeSinceUnix .CreatedUnix $.Lang}}</span> | | |||||
{{end}} | |||||
<span class="ahead"><a href="{{$.RepoLink}}/compare/{{.TagName | EscapePound}}...{{.Target}}">{{$.i18n.Tr "repo.release.ahead.commits" .NumCommitsBehind | Str2html}}</a> {{$.i18n.Tr "repo.release.ahead.target" .Target}}</span> | <span class="ahead"><a href="{{$.RepoLink}}/compare/{{.TagName | EscapePound}}...{{.Target}}">{{$.i18n.Tr "repo.release.ahead.commits" .NumCommitsBehind | Str2html}}</a> {{$.i18n.Tr "repo.release.ahead.target" .Target}}</span> | ||||
</p> | </p> | ||||
<div class="markdown desc"> | <div class="markdown desc"> | ||||
{{Str2html .Note}} | {{Str2html .Note}} | ||||
</div> | </div> | ||||
<div class="download"> | |||||
<div class="ui accordion"> | |||||
<h2 class="title {{if eq $idx 0}}active{{end}}"> | |||||
{{svg "octicon-triangle-down" 14 "dropdown icon"}} | |||||
{{$.i18n.Tr "repo.release.downloads"}} | |||||
</h2> | |||||
<div class="content {{if eq $idx 0}}active{{end}}"> | |||||
<ul class="list"> | |||||
{{if $.Permission.CanRead $.UnitTypeCode}} | |||||
<li> | |||||
<a href="{{$.RepoLink}}/archive/{{.TagName | EscapePound}}.zip" rel="nofollow"><strong>{{svg "octicon-file-zip"}} {{$.i18n.Tr "repo.release.source_code"}} (ZIP)</strong></a> | |||||
</li> | |||||
<div class="ui accordion download"> | |||||
<h2 class="title {{if eq $idx 0}}active{{end}} df ac mb-0"> | |||||
{{svg "octicon-triangle-right" 14 "dropdown icon"}} | |||||
{{$.i18n.Tr "repo.release.downloads"}} | |||||
</h2> | |||||
<div class="content {{if eq $idx 0}}active{{end}}"> | |||||
<ul class="list"> | |||||
{{if $.Permission.CanRead $.UnitTypeCode}} | |||||
<li> | |||||
<a href="{{$.RepoLink}}/archive/{{.TagName | EscapePound}}.zip" rel="nofollow"><strong>{{svg "octicon-file-zip" 16 "mr-2"}}{{$.i18n.Tr "repo.release.source_code"}} (ZIP)</strong></a> | |||||
</li> | |||||
<li> | |||||
<a href="{{$.RepoLink}}/archive/{{.TagName | EscapePound}}.tar.gz"><strong>{{svg "octicon-file-zip" 16 "mr-2"}}{{$.i18n.Tr "repo.release.source_code"}} (TAR.GZ)</strong></a> | |||||
</li> | |||||
{{end}} | |||||
{{if .Attachments}} | |||||
{{range .Attachments}} | |||||
<li> | <li> | ||||
<a href="{{$.RepoLink}}/archive/{{.TagName | EscapePound}}.tar.gz"><strong>{{svg "octicon-file-zip"}} {{$.i18n.Tr "repo.release.source_code"}} (TAR.GZ)</strong></a> | |||||
<span class="ui text right" data-tooltip="{{$.i18n.Tr "repo.release.download_count" (.DownloadCount | PrettyNumber)}}" data-position="bottom right">{{svg "octicon-info"}}</span> | |||||
<a target="_blank" rel="noopener noreferrer" href="{{.DownloadURL}}"> | |||||
<strong><span class="ui image" title='{{.Name}}'>{{svg "octicon-package" 16 "mr-2"}}</span>{{.Name}}</strong> | |||||
<span class="ui text grey right">{{.Size | FileSize}}</span> | |||||
</a> | |||||
</li> | </li> | ||||
{{end}} | {{end}} | ||||
{{if .Attachments}} | |||||
{{range .Attachments}} | |||||
<li> | |||||
<span class="ui text right" data-tooltip="{{$.i18n.Tr "repo.release.download_count" (.DownloadCount | PrettyNumber)}}" data-position="bottom right">{{svg "octicon-info"}}</span> | |||||
<a target="_blank" rel="noopener noreferrer" href="{{.DownloadURL}}"> | |||||
<strong><span class="ui image" title='{{.Name}}'>{{svg "octicon-package"}}</span> {{.Name}}</strong> | |||||
<span class="ui text grey right">{{.Size | FileSize}}</span> | |||||
</a> | |||||
</li> | |||||
{{end}} | |||||
{{end}} | |||||
</ul> | |||||
</div> | |||||
{{end}} | |||||
</ul> | |||||
</div> | </div> | ||||
</div> | </div> | ||||
{{end}} | {{end}} | ||||
@@ -116,7 +169,22 @@ | |||||
</li> | </li> | ||||
{{end}} | {{end}} | ||||
</ul> | </ul> | ||||
{{end}} | |||||
{{template "base/paginate" .}} | {{template "base/paginate" .}} | ||||
</div> | </div> | ||||
</div> | </div> | ||||
{{if (and ($.Permission.CanWrite $.UnitTypeCode) .PageIsTagList)}} | |||||
<div class="ui small basic delete modal"> | |||||
<div class="ui header"> | |||||
{{svg "octicon-trashcan" 16 "mr-2"}} | |||||
{{.i18n.Tr "repo.release.delete_tag"}} | |||||
</div> | |||||
<div class="content"> | |||||
<p>{{.i18n.Tr "repo.release.deletion_tag_desc"}}</p> | |||||
</div> | |||||
{{template "base/delete_modal_actions" .}} | |||||
</div> | |||||
{{end}} | |||||
{{template "base/footer" .}} | {{template "base/footer" .}} |
@@ -5,11 +5,14 @@ | |||||
<div class="item{{if .PageIsCommits}} active{{end}}"> | <div class="item{{if .PageIsCommits}} active{{end}}"> | ||||
<a class="ui" href="{{.RepoLink}}/commits{{if .IsViewBranch}}/branch{{else if .IsViewTag}}/tag{{else if .IsViewCommit}}/commit{{end}}/{{EscapePound .BranchName}}">{{svg "octicon-history"}} <b>{{.CommitsCount}}</b> {{.i18n.Tr (TrN .i18n.Lang .CommitsCount "repo.commit" "repo.commits") }}</a> | <a class="ui" href="{{.RepoLink}}/commits{{if .IsViewBranch}}/branch{{else if .IsViewTag}}/tag{{else if .IsViewCommit}}/commit{{end}}/{{EscapePound .BranchName}}">{{svg "octicon-history"}} <b>{{.CommitsCount}}</b> {{.i18n.Tr (TrN .i18n.Lang .CommitsCount "repo.commit" "repo.commits") }}</a> | ||||
</div> | </div> | ||||
{{end}} | |||||
{{if and (.Permission.CanRead $.UnitTypeCode) (not .IsEmptyRepo) }} | |||||
<div class="item{{if .PageIsBranches}} active{{end}}"> | <div class="item{{if .PageIsBranches}} active{{end}}"> | ||||
<a class="ui" href="{{.RepoLink}}/branches/">{{svg "octicon-git-branch"}} <b>{{.BranchesCount}}</b> {{.i18n.Tr (TrN .i18n.Lang .BranchesCount "repo.branch" "repo.branches") }}</a> | <a class="ui" href="{{.RepoLink}}/branches/">{{svg "octicon-git-branch"}} <b>{{.BranchesCount}}</b> {{.i18n.Tr (TrN .i18n.Lang .BranchesCount "repo.branch" "repo.branches") }}</a> | ||||
</div> | </div> | ||||
{{if $.Permission.CanRead $.UnitTypeCode}} | |||||
<div class="item"> | |||||
<a class="ui" href="{{.RepoLink}}/tags">{{svg "octicon-tag"}} <b>{{.NumReleases}}</b> {{.i18n.Tr (TrN .i18n.Lang .NumReleases "repo.release" "repo.releases") }}</a> | |||||
</div> | |||||
{{end}} | |||||
<div class="item"> | <div class="item"> | ||||
<span class="ui">{{svg "octicon-database"}} <b>{{SizeFmt .Repository.Size}}</b></span> | <span class="ui">{{svg "octicon-database"}} <b>{{SizeFmt .Repository.Size}}</b></span> | ||||
</div> | </div> | ||||
@@ -1901,6 +1901,12 @@ | |||||
margin-top: 20px; | margin-top: 20px; | ||||
padding-top: 15px; | padding-top: 15px; | ||||
.release-list-title { | |||||
font-size: 2rem; | |||||
font-weight: normal; | |||||
margin-top: -6px; | |||||
} | |||||
> li { | > li { | ||||
list-style: none; | list-style: none; | ||||
@@ -1926,7 +1932,7 @@ | |||||
} | } | ||||
.detail { | .detail { | ||||
border-left: 1px solid #dddddd; | |||||
border-left: 2px solid #dddddd; | |||||
.author { | .author { | ||||
img { | img { | ||||
@@ -1965,7 +1971,7 @@ | |||||
.dot { | .dot { | ||||
width: 9px; | width: 9px; | ||||
height: 9px; | height: 9px; | ||||
background-color: #cccccc; | |||||
background-color: #ddd; | |||||
z-index: 999; | z-index: 999; | ||||
position: absolute; | position: absolute; | ||||
display: block; | display: block; | ||||
@@ -1977,6 +1983,13 @@ | |||||
} | } | ||||
} | } | ||||
} | } | ||||
#tags-table { | |||||
.release-tag-name { | |||||
font-size: 1.5rem; | |||||
font-weight: normal; | |||||
} | |||||
} | |||||
} | } | ||||
&.new.release { | &.new.release { | ||||
@@ -1,6 +1,8 @@ | |||||
.df { display: flex; } | .df { display: flex; } | ||||
.ac { align-items: center; } | .ac { align-items: center; } | ||||
.jc { justify-content: center; } | .jc { justify-content: center; } | ||||
.js { justify-content: flex-start; } | |||||
.je { justify-content: flex-end; } | |||||
.sb { justify-content: space-between; } | .sb { justify-content: space-between; } | ||||
.m-0 { margin: 0 !important; } | .m-0 { margin: 0 !important; } | ||||
@@ -1510,7 +1510,7 @@ input { | |||||
.ui.radio.checkbox label::after, | .ui.radio.checkbox label::after, | ||||
.ui.radio.checkbox input:checked ~ label::after, | .ui.radio.checkbox input:checked ~ label::after, | ||||
.ui.radio.checkbox input:focus ~ label::after, | .ui.radio.checkbox input:focus ~ label::after, | ||||
.ui.radio.checkbox input:focus:checked ~ label::after, { | |||||
.ui.radio.checkbox input:focus:checked ~ label::after { | |||||
background: #dbdbdb; | background: #dbdbdb; | ||||
} | } | ||||
@@ -2075,7 +2075,7 @@ footer .container .links > * { | |||||
} | } | ||||
.repository.release #release-list > li .detail .dot { | .repository.release #release-list > li .detail .dot { | ||||
background-color: #888; | |||||
background-color: #505667; | |||||
border-color: #383c4a; | border-color: #383c4a; | ||||
} | } | ||||