* Can use a predefined set of labels * Change UI * Fix HTML file indentation * Avoid reading file from other directory (security issue) * Apply a better fix * Remove not used variable * Merge upstream/develop * Do modifications * Raname * remove binding + rename variabletags/v0.9.99
@@ -477,6 +477,7 @@ func runWeb(ctx *cli.Context) error { | |||
m.Post("/new", bindIgnErr(auth.CreateLabelForm{}), repo.NewLabel) | |||
m.Post("/edit", bindIgnErr(auth.CreateLabelForm{}), repo.UpdateLabel) | |||
m.Post("/delete", repo.DeleteLabel) | |||
m.Post("/initialize", bindIgnErr(auth.InitializeLabelsForm{}), repo.InitializeLabels) | |||
}, repo.MustEnableIssues, reqRepoWriter, context.RepoRef()) | |||
m.Group("/milestones", func() { | |||
m.Combo("/new").Get(repo.NewMilestone). |
@@ -0,0 +1,7 @@ | |||
#ee0701 bug | |||
#cccccc duplicate | |||
#84b6eb enhancement | |||
#128a0c help wanted | |||
#e6e6e6 invalid | |||
#cc317c question | |||
#ffffff wontfix |
@@ -489,6 +489,10 @@ issues.create = Create Issue | |||
issues.new_label = New Label | |||
issues.new_label_placeholder = Label name... | |||
issues.create_label = Create Label | |||
issues.label_templates.title=Load a set of labels | |||
issues.label_templates.info=There aren’t any labels. You can click on the "New Label" button above to create one or use a predefined set below. | |||
issues.label_templates.helper=Select a label set | |||
issues.label_templates.use=Use this label set | |||
issues.open_tab = %d Open | |||
issues.close_tab = %d Closed | |||
issues.filter_label = Label |
@@ -54,7 +54,7 @@ var ( | |||
) | |||
var ( | |||
Gitignores, Licenses, Readmes []string | |||
Gitignores, Licenses, Readmes, LabelTemplates []string | |||
// Maximum items per page in forks, watchers and stars of a repo | |||
ItemsPerPage = 40 | |||
@@ -62,9 +62,8 @@ var ( | |||
func LoadRepoConfig() { | |||
// Load .gitignore and license files and readme templates. | |||
// TODO: should we allow custom files overwrite default ones? | |||
types := []string{"gitignore", "license", "readme"} | |||
typeFiles := make([][]string, 3) | |||
types := []string{"gitignore", "license", "readme", "label"} | |||
typeFiles := make([][]string, 4) | |||
for i, t := range types { | |||
files, err := bindata.AssetDir("conf/" + t) | |||
if err != nil { | |||
@@ -89,9 +88,11 @@ func LoadRepoConfig() { | |||
Gitignores = typeFiles[0] | |||
Licenses = typeFiles[1] | |||
Readmes = typeFiles[2] | |||
LabelTemplates = typeFiles[3] | |||
sort.Strings(Gitignores) | |||
sort.Strings(Licenses) | |||
sort.Strings(Readmes) | |||
sort.Strings(LabelTemplates) | |||
// Filter out invalid names and promote preferred licenses. | |||
sortedLicenses := make([]string, 0, len(Licenses)) |
@@ -220,6 +220,16 @@ func (f *CreateLabelForm) Validate(ctx *macaron.Context, errs binding.Errors) bi | |||
return validate(errs, ctx.Data, f, ctx.Locale) | |||
} | |||
// Label templates | |||
type InitializeLabelsForm struct { | |||
TemplateName string `binding:"Required"` | |||
} | |||
func (f *InitializeLabelsForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors { | |||
return validate(errs, ctx.Data, f, ctx.Locale) | |||
} | |||
// __________ .__ | |||
// \______ \ ____ | | ____ _____ ______ ____ | |||
// | _// __ \| | _/ __ \\__ \ / ___// __ \ |
@@ -11,6 +11,8 @@ import ( | |||
"io/ioutil" | |||
"net/http" | |||
"net/url" | |||
"path" | |||
"regexp" | |||
"strings" | |||
"time" | |||
@@ -20,6 +22,7 @@ import ( | |||
"github.com/gogits/gogs/models" | |||
"github.com/gogits/gogs/modules/auth" | |||
"github.com/gogits/gogs/modules/base" | |||
"github.com/gogits/gogs/modules/bindata" | |||
"github.com/gogits/gogs/modules/context" | |||
"github.com/gogits/gogs/modules/log" | |||
"github.com/gogits/gogs/modules/markdown" | |||
@@ -938,9 +941,58 @@ func Labels(ctx *context.Context) { | |||
ctx.Data["PageIsIssueList"] = true | |||
ctx.Data["PageIsLabels"] = true | |||
ctx.Data["RequireMinicolors"] = true | |||
ctx.Data["LabelTemplates"] = models.LabelTemplates | |||
ctx.HTML(200, LABELS) | |||
} | |||
func getLabelTemplateFile(name string) ([]byte, error) { | |||
relPath := path.Join("conf/label", strings.TrimLeft(name, "./")) | |||
// Use custom file when available. | |||
customPath := path.Join(setting.CustomPath, relPath) | |||
if com.IsFile(customPath) { | |||
return ioutil.ReadFile(customPath) | |||
} | |||
return bindata.Asset(relPath) | |||
} | |||
func InitializeLabels(ctx *context.Context, form auth.InitializeLabelsForm) { | |||
if ctx.HasError() { | |||
ctx.Flash.Error(ctx.Data["ErrorMsg"].(string)) | |||
ctx.Redirect(ctx.Repo.RepoLink + "/labels") | |||
return | |||
} | |||
data, err := getLabelTemplateFile(form.TemplateName) | |||
if err != nil { | |||
ctx.Redirect(ctx.Repo.RepoLink + "/labels") | |||
return | |||
} | |||
r, _ := regexp.Compile("#([a-fA-F0-9]{6})") | |||
for i, line := range strings.Split(string(data), "\n") { | |||
if len(line) > 0 { | |||
line_x := strings.SplitN(strings.Trim(line, " \t"), " ", 2) | |||
if len(line_x) == 2 && len(line_x[1]) > 0 { | |||
if r.MatchString(line_x[0]) { | |||
l := &models.Label{ | |||
RepoID: ctx.Repo.Repository.ID, | |||
Name: line_x[1], | |||
Color: line_x[0], | |||
} | |||
if err := models.NewLabel(l); err != nil { | |||
ctx.Handle(500, "InitializeLabelsFromTemplate", err) | |||
return | |||
} | |||
} else { | |||
log.Warn("Line %d on the label template file '%s': Bad HTML color code", i+1, form.TemplateName) | |||
} | |||
} else { | |||
log.Warn("Line %d on the label template file '%s': Line is malformed", i+1, form.TemplateName) | |||
} | |||
} | |||
} | |||
ctx.Redirect(ctx.Repo.RepoLink + "/labels") | |||
} | |||
func NewLabel(ctx *context.Context, form auth.CreateLabelForm) { | |||
ctx.Data["Title"] = ctx.Tr("repo.labels") | |||
ctx.Data["PageIsLabels"] = true |
@@ -33,8 +33,43 @@ | |||
</form> | |||
</div> | |||
<div class="ui divider"></div> | |||
{{template "base/alert" .}} | |||
<div class="ui black label">{{.i18n.Tr "repo.issues.label_count" .NumLabels}}</div> | |||
{{if $.IsRepositoryWriter}} | |||
{{if eq .NumLabels 0}} | |||
<div class="ui centered grid"> | |||
<div class="twelve wide column eight wide computer column"> | |||
<div class="ui attached left aligned segment" style="margin-top:30px"> | |||
<h4 class="ui header"> | |||
{{.i18n.Tr "repo.issues.label_templates.title"}} | |||
<a target="_blank" | |||
href="https://github.com/gogits/go-gogs-client/wiki/Repositories#litte-notes-on-label-template"> | |||
<span class="octicon octicon-question"></span> | |||
</a> | |||
</h4> | |||
<p>{{.i18n.Tr "repo.issues.label_templates.info"}}</p> | |||
<br/> | |||
<form class="ui form center" action="{{.Link}}/initialize" method="post"> | |||
{{.CsrfTokenHtml}} | |||
<div class="field"> | |||
<div class="ui selection dropdown"> | |||
<input type="hidden" name="template_name" id="templatename" value="Default"> | |||
<div class="default text">{{.i18n.Tr "repo.issues.label_templates.helper"}}</div> | |||
<div class="menu"> | |||
{{range .LabelTemplates}} | |||
<div class="item" data-value="{{.}}">{{.}}</div> | |||
{{end}} | |||
</div> | |||
</div> | |||
</div> | |||
<button type="submit" class="ui blue button">{{.i18n.Tr "repo.issues.label_templates.use"}}</button> | |||
</form> | |||
</div> | |||
</div> | |||
</div> | |||
{{end}} | |||
{{end}} | |||
<div class="label list"> | |||
{{range .Labels}} |