mirror of
https://github.com/go-gitea/gitea.git
synced 2025-02-20 11:43:57 +08:00
Compare commits
7 Commits
206c0b8028
...
e60c4c7078
Author | SHA1 | Date | |
---|---|---|---|
|
e60c4c7078 | ||
|
40faa6dc78 | ||
|
c2e23d3301 | ||
|
84d2159ef6 | ||
|
8d71b733ad | ||
|
12e3e0b3ad | ||
|
a5035eadba |
@ -152,7 +152,7 @@ func (p *Permission) ReadableUnitTypes() []unit.Type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *Permission) LogString() string {
|
func (p *Permission) LogString() string {
|
||||||
format := "<Permission AccessMode=%s, %d Units, %d UnitsMode(s): [ "
|
format := "<Permission AccessMode=%s, %d Units, %d UnitsMode(s): ["
|
||||||
args := []any{p.AccessMode.ToString(), len(p.units), len(p.unitsMode)}
|
args := []any{p.AccessMode.ToString(), len(p.units), len(p.unitsMode)}
|
||||||
|
|
||||||
for i, u := range p.units {
|
for i, u := range p.units {
|
||||||
@ -164,14 +164,16 @@ func (p *Permission) LogString() string {
|
|||||||
config = err.Error()
|
config = err.Error()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
format += "\nUnits[%d]: ID: %d RepoID: %d Type: %s Config: %s"
|
format += "\n\tunits[%d]: ID=%d RepoID=%d Type=%s Config=%s"
|
||||||
args = append(args, i, u.ID, u.RepoID, u.Type.LogString(), config)
|
args = append(args, i, u.ID, u.RepoID, u.Type.LogString(), config)
|
||||||
}
|
}
|
||||||
for key, value := range p.unitsMode {
|
for key, value := range p.unitsMode {
|
||||||
format += "\nUnitMode[%-v]: %-v"
|
format += "\n\tunitsMode[%-v]: %-v"
|
||||||
args = append(args, key.LogString(), value.LogString())
|
args = append(args, key.LogString(), value.LogString())
|
||||||
}
|
}
|
||||||
format += " ]>"
|
format += "\n\teveryoneAccessMode: %-v"
|
||||||
|
args = append(args, p.everyoneAccessMode)
|
||||||
|
format += "\n\t]>"
|
||||||
return fmt.Sprintf(format, args...)
|
return fmt.Sprintf(format, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -298,6 +298,26 @@ func GetTagNamesByRepoID(ctx context.Context, repoID int64) ([]string, error) {
|
|||||||
return tags, sess.Find(&tags)
|
return tags, sess.Find(&tags)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetTagMappingsByRepoID returns a mapping from tag name to commit SHA by repo id
|
||||||
|
func GetTagMappingsByRepoID(ctx context.Context, repoID int64) (map[string]string, error) {
|
||||||
|
mapping := make(map[string]string)
|
||||||
|
rels := make([]*Release, 0)
|
||||||
|
if err := db.GetEngine(ctx).
|
||||||
|
Desc("created_unix").
|
||||||
|
Find(&rels, Release{RepoID: repoID}); err != nil {
|
||||||
|
return mapping, err
|
||||||
|
}
|
||||||
|
for _, r := range rels {
|
||||||
|
mapping[r.TagName] = r.Sha1
|
||||||
|
}
|
||||||
|
return mapping, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CountReleasesByRepoID returns a number of releases matching FindReleaseOptions and RepoID.
|
||||||
|
func CountReleasesByRepoID(ctx context.Context, repoID int64, opts FindReleasesOptions) (int64, error) {
|
||||||
|
return db.GetEngine(ctx).Where(opts.ToConds()).Count(new(Release))
|
||||||
|
}
|
||||||
|
|
||||||
// GetLatestReleaseByRepoID returns the latest release for a repository
|
// GetLatestReleaseByRepoID returns the latest release for a repository
|
||||||
func GetLatestReleaseByRepoID(ctx context.Context, repoID int64) (*Release, error) {
|
func GetLatestReleaseByRepoID(ctx context.Context, repoID int64) (*Release, error) {
|
||||||
cond := builder.NewCond().
|
cond := builder.NewCond().
|
||||||
|
@ -5,6 +5,7 @@ package log
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"reflect"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
@ -175,6 +176,20 @@ func (l *LoggerImpl) IsEnabled() bool {
|
|||||||
return l.level.Load() < int32(FATAL) && len(l.eventWriters) > 0
|
return l.level.Load() < int32(FATAL) && len(l.eventWriters) > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func asLogStringer(v any) LogStringer {
|
||||||
|
if s, ok := v.(LogStringer); ok {
|
||||||
|
return s
|
||||||
|
} else if a := reflect.ValueOf(v); a.Kind() == reflect.Struct {
|
||||||
|
// in case the receiver is a pointer, but the value is a struct
|
||||||
|
vp := reflect.New(a.Type())
|
||||||
|
vp.Elem().Set(a)
|
||||||
|
if s, ok := vp.Interface().(LogStringer); ok {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Log prepares the log event, if the level matches, the event will be sent to the writers
|
// Log prepares the log event, if the level matches, the event will be sent to the writers
|
||||||
func (l *LoggerImpl) Log(skip int, level Level, format string, logArgs ...any) {
|
func (l *LoggerImpl) Log(skip int, level Level, format string, logArgs ...any) {
|
||||||
if Level(l.level.Load()) > level {
|
if Level(l.level.Load()) > level {
|
||||||
@ -207,11 +222,11 @@ func (l *LoggerImpl) Log(skip int, level Level, format string, logArgs ...any) {
|
|||||||
// handle LogStringer values
|
// handle LogStringer values
|
||||||
for i, v := range msgArgs {
|
for i, v := range msgArgs {
|
||||||
if cv, ok := v.(*ColoredValue); ok {
|
if cv, ok := v.(*ColoredValue); ok {
|
||||||
if s, ok := cv.v.(LogStringer); ok {
|
if ls := asLogStringer(cv.v); ls != nil {
|
||||||
cv.v = logStringFormatter{v: s}
|
cv.v = logStringFormatter{v: ls}
|
||||||
}
|
}
|
||||||
} else if s, ok := v.(LogStringer); ok {
|
} else if ls := asLogStringer(v); ls != nil {
|
||||||
msgArgs[i] = logStringFormatter{v: s}
|
msgArgs[i] = logStringFormatter{v: ls}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,6 +116,14 @@ func (t testLogString) LogString() string {
|
|||||||
return "log-string"
|
return "log-string"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type testLogStringPtrReceiver struct {
|
||||||
|
Field string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *testLogStringPtrReceiver) LogString() string {
|
||||||
|
return "log-string-ptr-receiver"
|
||||||
|
}
|
||||||
|
|
||||||
func TestLoggerLogString(t *testing.T) {
|
func TestLoggerLogString(t *testing.T) {
|
||||||
logger := NewLoggerWithWriters(context.Background(), "test")
|
logger := NewLoggerWithWriters(context.Background(), "test")
|
||||||
|
|
||||||
@ -124,9 +132,13 @@ func TestLoggerLogString(t *testing.T) {
|
|||||||
logger.AddWriters(w1)
|
logger.AddWriters(w1)
|
||||||
|
|
||||||
logger.Info("%s %s %#v %v", testLogString{}, &testLogString{}, testLogString{Field: "detail"}, NewColoredValue(testLogString{}, FgRed))
|
logger.Info("%s %s %#v %v", testLogString{}, &testLogString{}, testLogString{Field: "detail"}, NewColoredValue(testLogString{}, FgRed))
|
||||||
|
logger.Info("%s %s %#v %v", testLogStringPtrReceiver{}, &testLogStringPtrReceiver{}, testLogStringPtrReceiver{Field: "detail"}, NewColoredValue(testLogStringPtrReceiver{}, FgRed))
|
||||||
logger.Close()
|
logger.Close()
|
||||||
|
|
||||||
assert.Equal(t, []string{"log-string log-string log.testLogString{Field:\"detail\"} \x1b[31mlog-string\x1b[0m\n"}, w1.GetLogs())
|
assert.Equal(t, []string{
|
||||||
|
"log-string log-string log.testLogString{Field:\"detail\"} \x1b[31mlog-string\x1b[0m\n",
|
||||||
|
"log-string-ptr-receiver log-string-ptr-receiver &log.testLogStringPtrReceiver{Field:\"detail\"} \x1b[31mlog-string-ptr-receiver\x1b[0m\n",
|
||||||
|
}, w1.GetLogs())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLoggerExpressionFilter(t *testing.T) {
|
func TestLoggerExpressionFilter(t *testing.T) {
|
||||||
|
@ -1702,7 +1702,9 @@ issues.time_estimate_invalid = Time estimate format is invalid
|
|||||||
issues.start_tracking_history = started working %s
|
issues.start_tracking_history = started working %s
|
||||||
issues.tracker_auto_close = Timer will be stopped automatically when this issue gets closed
|
issues.tracker_auto_close = Timer will be stopped automatically when this issue gets closed
|
||||||
issues.tracking_already_started = `You have already started time tracking on <a href="%s">another issue</a>!`
|
issues.tracking_already_started = `You have already started time tracking on <a href="%s">another issue</a>!`
|
||||||
|
issues.stop_tracking = Stop Timer
|
||||||
issues.stop_tracking_history = worked for <b>%[1]s</b> %[2]s
|
issues.stop_tracking_history = worked for <b>%[1]s</b> %[2]s
|
||||||
|
issues.cancel_tracking = Discard
|
||||||
issues.cancel_tracking_history = `canceled time tracking %s`
|
issues.cancel_tracking_history = `canceled time tracking %s`
|
||||||
issues.del_time = Delete this time log
|
issues.del_time = Delete this time log
|
||||||
issues.add_time_history = added spent time <b>%[1]s</b> %[2]s
|
issues.add_time_history = added spent time <b>%[1]s</b> %[2]s
|
||||||
@ -2692,6 +2694,12 @@ release.add_tag_msg = Use the title and content of release as tag message.
|
|||||||
release.add_tag = Create Tag Only
|
release.add_tag = Create Tag Only
|
||||||
release.releases_for = Releases for %s
|
release.releases_for = Releases for %s
|
||||||
release.tags_for = Tags for %s
|
release.tags_for = Tags for %s
|
||||||
|
release.existing_tag_header = New release with an old tag
|
||||||
|
release.existing_tag_draft_header = Draft release with an old tag
|
||||||
|
release.existing_tag = You are about to create a new release with an <b>existing tag</b>. Make sure that the tag is pointing to the right commit.
|
||||||
|
release.existing_draft_tag = You are about to create a draft release with an <b>existing tag</b>. Make sure that the tag is pointing to the right commit.
|
||||||
|
release.create_confirmation = Do you want to continue with the release creation?
|
||||||
|
release.create_draft_confirmation = Do you want to continue with the release draft creation?
|
||||||
|
|
||||||
branch.name = Branch Name
|
branch.name = Branch Name
|
||||||
branch.already_exists = A branch named "%s" already exists.
|
branch.already_exists = A branch named "%s" already exists.
|
||||||
|
@ -330,9 +330,9 @@ func newReleaseCommon(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
|
||||||
|
|
||||||
tags, err := repo_model.GetTagNamesByRepoID(ctx, ctx.Repo.Repository.ID)
|
tags, err := repo_model.GetTagMappingsByRepoID(ctx, ctx.Repo.Repository.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("GetTagNamesByRepoID", err)
|
ctx.ServerError("GetTagMappingsByRepoID", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctx.Data["Tags"] = tags
|
ctx.Data["Tags"] = tags
|
||||||
|
@ -1196,6 +1196,10 @@ func registerRoutes(m *web.Router) {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
// FIXME: many "pulls" requests are sent to "issues" endpoints correctly, so the issue endpoints have to tolerate pull request permissions at the moment
|
||||||
|
m.Group("/{username}/{reponame}/{type:issues}", addIssuesPullsViewRoutes, optSignIn, context.RepoAssignment, context.RequireUnitReader(unit.TypeIssues, unit.TypePullRequests))
|
||||||
|
m.Group("/{username}/{reponame}/{type:pulls}", addIssuesPullsViewRoutes, optSignIn, context.RepoAssignment, reqUnitPullsReader)
|
||||||
|
|
||||||
m.Group("/{username}/{reponame}", func() {
|
m.Group("/{username}/{reponame}", func() {
|
||||||
m.Get("/comments/{id}/attachments", repo.GetCommentAttachments)
|
m.Get("/comments/{id}/attachments", repo.GetCommentAttachments)
|
||||||
m.Get("/labels", repo.RetrieveLabelsForList, repo.Labels)
|
m.Get("/labels", repo.RetrieveLabelsForList, repo.Labels)
|
||||||
@ -1203,9 +1207,6 @@ func registerRoutes(m *web.Router) {
|
|||||||
m.Get("/milestone/{id}", context.RepoRef(), repo.MilestoneIssuesAndPulls)
|
m.Get("/milestone/{id}", context.RepoRef(), repo.MilestoneIssuesAndPulls)
|
||||||
m.Get("/issues/suggestions", repo.IssueSuggestions)
|
m.Get("/issues/suggestions", repo.IssueSuggestions)
|
||||||
}, optSignIn, context.RepoAssignment, reqRepoIssuesOrPullsReader) // issue/pull attachments, labels, milestones
|
}, optSignIn, context.RepoAssignment, reqRepoIssuesOrPullsReader) // issue/pull attachments, labels, milestones
|
||||||
|
|
||||||
m.Group("/{username}/{reponame}/{type:issues}", addIssuesPullsViewRoutes, optSignIn, context.RepoAssignment, reqUnitIssuesReader)
|
|
||||||
m.Group("/{username}/{reponame}/{type:pulls}", addIssuesPullsViewRoutes, optSignIn, context.RepoAssignment, reqUnitPullsReader)
|
|
||||||
// end "/{username}/{reponame}": view milestone, label, issue, pull, etc
|
// end "/{username}/{reponame}": view milestone, label, issue, pull, etc
|
||||||
|
|
||||||
m.Group("/{username}/{reponame}/{type:issues}", func() {
|
m.Group("/{username}/{reponame}/{type:issues}", func() {
|
||||||
@ -1224,7 +1225,7 @@ func registerRoutes(m *web.Router) {
|
|||||||
m.Get("/search", repo.SearchRepoIssuesJSON)
|
m.Get("/search", repo.SearchRepoIssuesJSON)
|
||||||
}, reqUnitIssuesReader)
|
}, reqUnitIssuesReader)
|
||||||
|
|
||||||
addIssuesPullsRoutes := func() {
|
addIssuesPullsUpdateRoutes := func() {
|
||||||
// for "/{username}/{reponame}/issues" or "/{username}/{reponame}/pulls"
|
// for "/{username}/{reponame}/issues" or "/{username}/{reponame}/pulls"
|
||||||
m.Group("/{index}", func() {
|
m.Group("/{index}", func() {
|
||||||
m.Post("/title", repo.UpdateIssueTitle)
|
m.Post("/title", repo.UpdateIssueTitle)
|
||||||
@ -1267,8 +1268,9 @@ func registerRoutes(m *web.Router) {
|
|||||||
m.Delete("/unpin/{index}", reqRepoAdmin, repo.IssueUnpin)
|
m.Delete("/unpin/{index}", reqRepoAdmin, repo.IssueUnpin)
|
||||||
m.Post("/move_pin", reqRepoAdmin, repo.IssuePinMove)
|
m.Post("/move_pin", reqRepoAdmin, repo.IssuePinMove)
|
||||||
}
|
}
|
||||||
m.Group("/{type:issues}", addIssuesPullsRoutes, reqUnitIssuesReader, context.RepoMustNotBeArchived())
|
// FIXME: many "pulls" requests are sent to "issues" endpoints incorrectly, so the issue endpoints have to tolerate pull request permissions at the moment
|
||||||
m.Group("/{type:pulls}", addIssuesPullsRoutes, reqUnitPullsReader, context.RepoMustNotBeArchived())
|
m.Group("/{type:issues}", addIssuesPullsUpdateRoutes, context.RequireUnitReader(unit.TypeIssues, unit.TypePullRequests), context.RepoMustNotBeArchived())
|
||||||
|
m.Group("/{type:pulls}", addIssuesPullsUpdateRoutes, reqUnitPullsReader, context.RepoMustNotBeArchived())
|
||||||
|
|
||||||
m.Group("/comments/{id}", func() {
|
m.Group("/comments/{id}", func() {
|
||||||
m.Post("", repo.UpdateCommentContent)
|
m.Post("", repo.UpdateCommentContent)
|
||||||
@ -1292,7 +1294,7 @@ func registerRoutes(m *web.Router) {
|
|||||||
m.Post("/delete", repo.DeleteMilestone)
|
m.Post("/delete", repo.DeleteMilestone)
|
||||||
}, reqRepoIssuesOrPullsWriter, context.RepoRef())
|
}, reqRepoIssuesOrPullsWriter, context.RepoRef())
|
||||||
|
|
||||||
// FIXME: need to move these routes to the proper place
|
// FIXME: many "pulls" requests are sent to "issues" endpoints incorrectly, need to move these routes to the proper place
|
||||||
m.Group("/issues", func() {
|
m.Group("/issues", func() {
|
||||||
m.Post("/request_review", repo.UpdatePullReviewRequest)
|
m.Post("/request_review", repo.UpdatePullReviewRequest)
|
||||||
m.Post("/dismiss_review", reqRepoAdmin, web.Bind(forms.DismissReviewForm{}), repo.DismissReview)
|
m.Post("/dismiss_review", reqRepoAdmin, web.Bind(forms.DismissReviewForm{}), repo.DismissReview)
|
||||||
|
@ -29,7 +29,7 @@ func GetCommitGraph(r *git.Repository, page, maxAllowedColors int, hidePRRefs bo
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(branches) == 0 {
|
if len(branches) == 0 {
|
||||||
graphCmd.AddArguments("--all")
|
graphCmd.AddArguments("--tags", "--branches")
|
||||||
}
|
}
|
||||||
|
|
||||||
graphCmd.AddArguments("-C", "-M", "--date=iso-strict").
|
graphCmd.AddArguments("-C", "-M", "--date=iso-strict").
|
||||||
|
@ -38,6 +38,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div id="tag-warning" class="gt-dib gt-hidden" data-commit-url-stub="{{.RepoLink}}/commit">
|
||||||
|
{{svg "octicon-alert-fill" 16}} Existing tag referencing <span class="gt-px-3">{{svg "octicon-git-commit" 16}} <a target="_blank" rel="noopener noreferrer" class="tag-warning-detail"></a></span>
|
||||||
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<span id="tag-helper" class="help tw-mt-2 tw-pb-0">{{ctx.Locale.Tr "repo.release.tag_helper"}}</span>
|
<span id="tag-helper" class="help tw-mt-2 tw-pb-0">{{ctx.Locale.Tr "repo.release.tag_helper"}}</span>
|
||||||
</div>
|
</div>
|
||||||
@ -118,8 +121,8 @@
|
|||||||
{{if .ShowCreateTagOnlyButton}}
|
{{if .ShowCreateTagOnlyButton}}
|
||||||
<button class="ui small button" name="tag_only" value="1">{{ctx.Locale.Tr "repo.release.add_tag"}}</button>
|
<button class="ui small button" name="tag_only" value="1">{{ctx.Locale.Tr "repo.release.add_tag"}}</button>
|
||||||
{{end}}
|
{{end}}
|
||||||
<button class="ui small button" name="draft" value="1">{{ctx.Locale.Tr "repo.release.save_draft"}}</button>
|
<button class="ui small button tag-confirm tag-draft" name="draft" value="1">{{ctx.Locale.Tr "repo.release.save_draft"}}</button>
|
||||||
<button class="ui small primary button">{{ctx.Locale.Tr "repo.release.publish"}}</button>
|
<button class="ui small primary button tag-confirm">{{ctx.Locale.Tr "repo.release.publish"}}</button>
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -128,6 +131,29 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div id="tag-confirm-modal" class="ui g-modal-confirm modal">
|
||||||
|
<div class="header">
|
||||||
|
{{ctx.Locale.Tr "repo.release.existing_tag_header"}}
|
||||||
|
</div>
|
||||||
|
<div class="content">
|
||||||
|
<p>{{svg "octicon-alert-fill" 16}} Existing tag referencing <span class="gt-px-3">{{svg "octicon-git-commit" 16}} <a target="_blank" rel="noopener noreferrer" class="tag-warning-detail"></a></span></p>
|
||||||
|
<p>{{ctx.Locale.Tr "repo.release.existing_tag"}}</p>
|
||||||
|
<p>{{ctx.Locale.Tr "repo.release.create_confirmation"}}</p>
|
||||||
|
</div>
|
||||||
|
{{template "base/modal_actions_confirm" .}}
|
||||||
|
</div>
|
||||||
|
<div id="tag-confirm-draft-modal" class="ui g-modal-confirm modal">
|
||||||
|
<div class="header">
|
||||||
|
{{ctx.Locale.Tr "repo.release.existing_tag_draft_header"}}
|
||||||
|
</div>
|
||||||
|
<div class="content">
|
||||||
|
<p>{{svg "octicon-alert-fill" 16}} Existing tag referencing <span class="gt-px-3">{{svg "octicon-git-commit" 16}} <a target="_blank" rel="noopener noreferrer" class="tag-warning-detail"></a></span></p>
|
||||||
|
<p>{{ctx.Locale.Tr "repo.release.existing_draft_tag"}}</p>
|
||||||
|
<p>{{ctx.Locale.Tr "repo.release.create_draft_confirmation"}}</p>
|
||||||
|
</div>
|
||||||
|
{{template "base/modal_actions_confirm" .}}
|
||||||
|
</div>
|
||||||
|
|
||||||
{{if .PageIsEditRelease}}
|
{{if .PageIsEditRelease}}
|
||||||
<div class="ui g-modal-confirm delete modal">
|
<div class="ui g-modal-confirm delete modal">
|
||||||
<div class="header">
|
<div class="header">
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
|
import $ from 'jquery';
|
||||||
import {hideElem, showElem, type DOMEvent} from '../utils/dom.ts';
|
import {hideElem, showElem, type DOMEvent} from '../utils/dom.ts';
|
||||||
|
import {fomanticQuery} from '../modules/fomantic/base.ts';
|
||||||
|
|
||||||
export function initRepoRelease() {
|
export function initRepoRelease() {
|
||||||
document.addEventListener('click', (e: DOMEvent<MouseEvent>) => {
|
document.addEventListener('click', (e: DOMEvent<MouseEvent>) => {
|
||||||
@ -21,24 +23,66 @@ function initTagNameEditor() {
|
|||||||
const el = document.querySelector('#tag-name-editor');
|
const el = document.querySelector('#tag-name-editor');
|
||||||
if (!el) return;
|
if (!el) return;
|
||||||
|
|
||||||
|
const tagWarning = document.querySelector('#tag-warning');
|
||||||
|
const tagWarningDetailLinks = Array.from(document.querySelectorAll('.tag-warning-detail'));
|
||||||
const existingTags = JSON.parse(el.getAttribute('data-existing-tags'));
|
const existingTags = JSON.parse(el.getAttribute('data-existing-tags'));
|
||||||
if (!Array.isArray(existingTags)) return;
|
|
||||||
|
|
||||||
const defaultTagHelperText = el.getAttribute('data-tag-helper');
|
const defaultTagHelperText = el.getAttribute('data-tag-helper');
|
||||||
const newTagHelperText = el.getAttribute('data-tag-helper-new');
|
const newTagHelperText = el.getAttribute('data-tag-helper-new');
|
||||||
const existingTagHelperText = el.getAttribute('data-tag-helper-existing');
|
const existingTagHelperText = el.getAttribute('data-tag-helper-existing');
|
||||||
|
const tagURLStub = tagWarning.getAttribute('data-commit-url-stub');
|
||||||
|
const tagConfirmDraftModal = document.querySelector('#tag-confirm-draft-modal');
|
||||||
|
const tagConfirmModal = document.querySelector('#tag-confirm-modal');
|
||||||
|
|
||||||
|
// show the confirmation modal if release is using an existing tag
|
||||||
|
let requiresConfirmation = false;
|
||||||
|
$('.tag-confirm').on('click', (event) => {
|
||||||
|
if (requiresConfirmation) {
|
||||||
|
event.preventDefault();
|
||||||
|
const form = event.target.closest('form');
|
||||||
|
if (event.target.classList.contains('tag-draft')) {
|
||||||
|
fomanticQuery(tagConfirmDraftModal).modal({
|
||||||
|
onApprove() {
|
||||||
|
// need to add hidden input with draft form value
|
||||||
|
// (triggering form submission doesn't include the button data)
|
||||||
|
const input = document.createElement('input');
|
||||||
|
input.type = 'hidden';
|
||||||
|
input.name = 'draft';
|
||||||
|
input.value = '1';
|
||||||
|
form.append(input);
|
||||||
|
$(form).trigger('submit');
|
||||||
|
},
|
||||||
|
}).modal('show');
|
||||||
|
} else {
|
||||||
|
fomanticQuery(tagConfirmModal).modal({
|
||||||
|
onApprove() {
|
||||||
|
$(form).trigger('submit');
|
||||||
|
},
|
||||||
|
}).modal('show');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const tagNameInput = document.querySelector<HTMLInputElement>('#tag-name');
|
const tagNameInput = document.querySelector<HTMLInputElement>('#tag-name');
|
||||||
const hideTargetInput = function(tagNameInput: HTMLInputElement) {
|
const hideTargetInput = function(tagNameInput: HTMLInputElement) {
|
||||||
const value = tagNameInput.value;
|
const value = tagNameInput.value;
|
||||||
const tagHelper = document.querySelector('#tag-helper');
|
const tagHelper = document.querySelector('#tag-helper');
|
||||||
if (existingTags.includes(value)) {
|
if (value in existingTags) {
|
||||||
// If the tag already exists, hide the target branch selector.
|
// If the tag already exists, hide the target branch selector.
|
||||||
hideElem('#tag-target-selector');
|
hideElem('#tag-target-selector');
|
||||||
tagHelper.textContent = existingTagHelperText;
|
tagHelper.textContent = existingTagHelperText;
|
||||||
|
showElem('#tag-warning');
|
||||||
|
for (const detail of tagWarningDetailLinks) {
|
||||||
|
const anchor = detail as HTMLAnchorElement;
|
||||||
|
anchor.href = `${tagURLStub}/${existingTags[value]}`;
|
||||||
|
anchor.textContent = existingTags[value].substring(0, 10);
|
||||||
|
}
|
||||||
|
requiresConfirmation = true;
|
||||||
} else {
|
} else {
|
||||||
showElem('#tag-target-selector');
|
showElem('#tag-target-selector');
|
||||||
tagHelper.textContent = value ? newTagHelperText : defaultTagHelperText;
|
tagHelper.textContent = value ? newTagHelperText : defaultTagHelperText;
|
||||||
|
hideElem('#tag-warning');
|
||||||
|
requiresConfirmation = false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
hideTargetInput(tagNameInput); // update on page load because the input may have a value
|
hideTargetInput(tagNameInput); // update on page load because the input may have a value
|
||||||
|
Loading…
x
Reference in New Issue
Block a user