Merge b82ffc1dbb
into cc9fa062e6
This commit is contained in:
commit
774abff779
|
@ -527,10 +527,13 @@ func (repo *Repository) ComposeMetas() map[string]string {
|
|||
"format": unit.ExternalTrackerConfig().ExternalTrackerFormat,
|
||||
"user": repo.MustOwner().Name,
|
||||
"repo": repo.Name,
|
||||
"regexp": unit.ExternalTrackerConfig().ExternalTrackerRegexpPattern,
|
||||
}
|
||||
switch unit.ExternalTrackerConfig().ExternalTrackerStyle {
|
||||
case markup.IssueNameStyleAlphanumeric:
|
||||
repo.ExternalMetas["style"] = markup.IssueNameStyleAlphanumeric
|
||||
case markup.IssueNameStyleRegexp:
|
||||
repo.ExternalMetas["style"] = markup.IssueNameStyleRegexp
|
||||
default:
|
||||
repo.ExternalMetas["style"] = markup.IssueNameStyleNumeric
|
||||
}
|
||||
|
|
|
@ -46,6 +46,9 @@ func TestRepo(t *testing.T) {
|
|||
|
||||
externalTracker.ExternalTrackerConfig().ExternalTrackerStyle = markup.IssueNameStyleNumeric
|
||||
testSuccess(markup.IssueNameStyleNumeric)
|
||||
|
||||
externalTracker.ExternalTrackerConfig().ExternalTrackerStyle = markup.IssueNameStyleRegexp
|
||||
testSuccess(markup.IssueNameStyleRegexp)
|
||||
}
|
||||
|
||||
func TestGetRepositoryCount(t *testing.T) {
|
||||
|
|
|
@ -54,9 +54,10 @@ func (cfg *ExternalWikiConfig) ToDB() ([]byte, error) {
|
|||
|
||||
// ExternalTrackerConfig describes external tracker config
|
||||
type ExternalTrackerConfig struct {
|
||||
ExternalTrackerURL string
|
||||
ExternalTrackerFormat string
|
||||
ExternalTrackerStyle string
|
||||
ExternalTrackerURL string
|
||||
ExternalTrackerFormat string
|
||||
ExternalTrackerStyle string
|
||||
ExternalTrackerRegexpPattern string
|
||||
}
|
||||
|
||||
// FromDB fills up a ExternalTrackerConfig from serialized format.
|
||||
|
|
|
@ -106,6 +106,7 @@ type RepoSettingForm struct {
|
|||
ExternalTrackerURL string
|
||||
TrackerURLFormat string
|
||||
TrackerIssueStyle string
|
||||
ExternalTrackerRegexpPattern string
|
||||
EnablePulls bool
|
||||
PullsIgnoreWhitespace bool
|
||||
PullsAllowMerge bool
|
||||
|
|
|
@ -25,6 +25,7 @@ import (
|
|||
const (
|
||||
IssueNameStyleNumeric = "numeric"
|
||||
IssueNameStyleAlphanumeric = "alphanumeric"
|
||||
IssueNameStyleRegexp = "regexp"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -543,28 +544,52 @@ func issueIndexPatternProcessor(ctx *postProcessCtx, node *html.Node) {
|
|||
|
||||
// default to numeric pattern, unless alphanumeric is requested.
|
||||
pattern := issueNumericPattern
|
||||
if ctx.metas["style"] == IssueNameStyleAlphanumeric {
|
||||
switch ctx.metas["style"] {
|
||||
case IssueNameStyleAlphanumeric:
|
||||
pattern = issueAlphanumericPattern
|
||||
case IssueNameStyleRegexp:
|
||||
var err error
|
||||
pattern, err = regexp.Compile(ctx.metas["regexp"])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
match := pattern.FindStringSubmatchIndex(node.Data)
|
||||
if match == nil {
|
||||
if match == nil || len(match) < 4 {
|
||||
return
|
||||
}
|
||||
id := node.Data[match[2]:match[3]]
|
||||
|
||||
var index string
|
||||
var content string
|
||||
var start int
|
||||
var end int
|
||||
switch ctx.metas["style"] {
|
||||
case IssueNameStyleAlphanumeric:
|
||||
content = node.Data[match[2]:match[3]]
|
||||
index = content
|
||||
start = match[2]
|
||||
end = match[3]
|
||||
case IssueNameStyleRegexp:
|
||||
index = node.Data[match[2]:match[3]]
|
||||
content = node.Data[match[0]:match[1]]
|
||||
start = match[0]
|
||||
end = match[1]
|
||||
default:
|
||||
content = node.Data[match[2]:match[3]]
|
||||
index = content[1:]
|
||||
start = match[2]
|
||||
end = match[3]
|
||||
}
|
||||
|
||||
var link *html.Node
|
||||
if ctx.metas == nil {
|
||||
link = createLink(util.URLJoin(prefix, "issues", id[1:]), id)
|
||||
link = createLink(util.URLJoin(prefix, "issues", index), content)
|
||||
} else {
|
||||
// Support for external issue tracker
|
||||
if ctx.metas["style"] == IssueNameStyleAlphanumeric {
|
||||
ctx.metas["index"] = id
|
||||
} else {
|
||||
ctx.metas["index"] = id[1:]
|
||||
}
|
||||
link = createLink(com.Expand(ctx.metas["format"], ctx.metas), id)
|
||||
ctx.metas["index"] = index
|
||||
link = createLink(com.Expand(ctx.metas["format"], ctx.metas), content)
|
||||
}
|
||||
replaceContent(node, match[2], match[3], link)
|
||||
replaceContent(node, start, end, link)
|
||||
}
|
||||
|
||||
func crossReferenceIssueIndexPatternProcessor(ctx *postProcessCtx, node *html.Node) {
|
||||
|
|
|
@ -53,6 +53,13 @@ var alphanumericMetas = map[string]string{
|
|||
"style": IssueNameStyleAlphanumeric,
|
||||
}
|
||||
|
||||
var regexpMetas = map[string]string{
|
||||
"format": "https://someurl.com/{user}/{repo}/{index}",
|
||||
"user": "someUser",
|
||||
"repo": "someRepo",
|
||||
"style": IssueNameStyleRegexp,
|
||||
}
|
||||
|
||||
func TestRender_IssueIndexPattern(t *testing.T) {
|
||||
// numeric: render inputs without valid mentions
|
||||
test := func(s string) {
|
||||
|
@ -160,6 +167,40 @@ func TestRender_IssueIndexPattern4(t *testing.T) {
|
|||
test("test issue ABCDEFGHIJ-1234567890", "test issue %s", "ABCDEFGHIJ-1234567890")
|
||||
}
|
||||
|
||||
func TestRender_IssueIndexPattern5(t *testing.T) {
|
||||
test := func(s, expectedFmt string, pattern string, ids []string, names []string) {
|
||||
metas := regexpMetas
|
||||
metas["regexp"] = pattern
|
||||
links := make([]interface{}, len(ids))
|
||||
for i, id := range ids {
|
||||
links[i] = link(util.URLJoin("https://someurl.com/someUser/someRepo/", id), names[i])
|
||||
}
|
||||
|
||||
expected := fmt.Sprintf(expectedFmt, links...)
|
||||
testRenderIssueIndexPattern(t, s, expected, &postProcessCtx{metas: metas})
|
||||
}
|
||||
|
||||
test("abc ISSUE-123 def", "abc %s def", "ISSUE-(\\d+)",
|
||||
[]string{"123"},
|
||||
[]string{"ISSUE-123"},
|
||||
)
|
||||
|
||||
test("abc (ISSUE 123) def", "abc %s def",
|
||||
"\\(ISSUE (\\d+)\\)",
|
||||
[]string{"123"},
|
||||
[]string{"(ISSUE 123)"},
|
||||
)
|
||||
|
||||
test("abc (ISSUE 123) def (TASK 456) ghi", "abc %s def %s ghi", "\\((?:ISSUE|TASK) (\\d+)\\)",
|
||||
[]string{"123", "456"},
|
||||
[]string{"(ISSUE 123)", "(TASK 456)"},
|
||||
)
|
||||
|
||||
metas := regexpMetas
|
||||
metas["regexp"] = "no matches"
|
||||
testRenderIssueIndexPattern(t, "will not match", "will not match", &postProcessCtx{metas: metas})
|
||||
}
|
||||
|
||||
func testRenderIssueIndexPattern(t *testing.T, input, expected string, ctx *postProcessCtx) {
|
||||
if ctx == nil {
|
||||
ctx = new(postProcessCtx)
|
||||
|
|
|
@ -974,6 +974,9 @@ settings.tracker_url_format = External Issue Tracker URL Format
|
|||
settings.tracker_issue_style = External Issue Tracker Number Format
|
||||
settings.tracker_issue_style.numeric = Numeric
|
||||
settings.tracker_issue_style.alphanumeric = Alphanumeric
|
||||
settings.tracker_issue_style.regexp = Regular Expression
|
||||
settings.tracker_issue_style.regexp_pattern = Regular Expression Pattern
|
||||
settings.tracker_issue_style.regexp_pattern_desc = The first captured group will be used in place of <code>{index}</code>.
|
||||
settings.tracker_url_format_desc = Use the placeholders <code>{user}</code>, <code>{repo}</code> and <code>{index}</code> for the username, repository name and issue index.
|
||||
settings.enable_timetracker = Enable Time Tracking
|
||||
settings.allow_only_contributors_to_track_time = Let Only Contributors Track Time
|
||||
|
|
|
@ -501,6 +501,15 @@ function initRepository() {
|
|||
if (typeof $(this).data('context') !== 'undefined') $($(this).data('context')).addClass('disabled');
|
||||
}
|
||||
});
|
||||
$('.enable-system-pick').change(function () {
|
||||
if ($(this).data('context') && $(this).data('target')) {
|
||||
if ($(this).data('context') === this.value) {
|
||||
$($(this).data('target')).removeClass('disabled')
|
||||
} else {
|
||||
$($(this).data('target')).addClass('disabled')
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Labels
|
||||
|
|
|
@ -190,9 +190,10 @@ func SettingsPost(ctx *context.Context, form auth.RepoSettingForm) {
|
|||
RepoID: repo.ID,
|
||||
Type: models.UnitTypeExternalTracker,
|
||||
Config: &models.ExternalTrackerConfig{
|
||||
ExternalTrackerURL: form.ExternalTrackerURL,
|
||||
ExternalTrackerFormat: form.TrackerURLFormat,
|
||||
ExternalTrackerStyle: form.TrackerIssueStyle,
|
||||
ExternalTrackerURL: form.ExternalTrackerURL,
|
||||
ExternalTrackerFormat: form.TrackerURLFormat,
|
||||
ExternalTrackerStyle: form.TrackerIssueStyle,
|
||||
ExternalTrackerRegexpPattern: form.ExternalTrackerRegexpPattern,
|
||||
},
|
||||
})
|
||||
} else {
|
||||
|
|
|
@ -183,16 +183,27 @@
|
|||
<div class="ui radio checkbox">
|
||||
{{$externalTracker := (.Repository.MustGetUnit $.UnitTypeExternalTracker)}}
|
||||
{{$externalTrackerStyle := $externalTracker.ExternalTrackerConfig.ExternalTrackerStyle}}
|
||||
<input class="hidden" tabindex="0" name="tracker_issue_style" type="radio" value="numeric" {{if $externalTrackerStyle}}{{if eq $externalTrackerStyle "numeric"}}checked=""{{end}}{{end}}/>
|
||||
<input class="hidden enable-system-pick" tabindex="0" name="tracker_issue_style" type="radio" value="numeric" data-context="regexp" data-target="#tracker_regexp_pattern_box" {{if $externalTrackerStyle}}{{if eq $externalTrackerStyle "numeric"}}checked=""{{end}}{{end}}/>
|
||||
<label>{{.i18n.Tr "repo.settings.tracker_issue_style.numeric"}} <span class="ui light grey text">(#1234)</span></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui radio checkbox">
|
||||
<input class="hidden" tabindex="0" name="tracker_issue_style" type="radio" value="alphanumeric" {{if $externalTrackerStyle}}{{if eq $externalTracker.ExternalTrackerConfig.ExternalTrackerStyle "alphanumeric"}}checked=""{{end}}{{end}} />
|
||||
<input class="hidden enable-system-pick" tabindex="0" name="tracker_issue_style" type="radio" value="alphanumeric" data-context="regexp" data-target="#tracker_regexp_pattern_box" {{if $externalTrackerStyle}}{{if eq $externalTracker.ExternalTrackerConfig.ExternalTrackerStyle "alphanumeric"}}checked=""{{end}}{{end}} />
|
||||
<label>{{.i18n.Tr "repo.settings.tracker_issue_style.alphanumeric"}} <span class="ui light grey text">(ABC-123, DEFG-234)</span></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui radio checkbox">
|
||||
<input class="hidden enable-system-pick" tabindex="0" name="tracker_issue_style" type="radio" value="regexp" data-context="regexp" data-target="#tracker_regexp_pattern_box" {{if $externalTrackerStyle}}{{if eq $externalTracker.ExternalTrackerConfig.ExternalTrackerStyle "regexp"}}checked=""{{end}}{{end}} />
|
||||
<label>{{.i18n.Tr "repo.settings.tracker_issue_style.regexp"}} <span class="ui light grey text">((?:TASK|ISSUE) (\d+))</span></label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field {{if ne $externalTracker.ExternalTrackerConfig.ExternalTrackerStyle "regexp"}}disabled{{end}}" id="tracker_regexp_pattern_box">
|
||||
<label for="external_tracker_regexp_pattern">{{.i18n.Tr "repo.settings.tracker_issue_style.regexp_pattern"}}</label>
|
||||
<input id="external_tracker_regexp_pattern" name="external_tracker_regexp_pattern" value="{{(.Repository.MustGetUnit $.UnitTypeExternalTracker).ExternalTrackerConfig.ExternalTrackerRegexpPattern}}">
|
||||
<p class="help">{{.i18n.Tr "repo.settings.tracker_issue_style.regexp_pattern_desc" | Str2html}}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
Loading…
Reference in New Issue
Block a user