| @@ -3,7 +3,7 @@ Gogs - Go Git Service [ | |||
| ##### Current tip version: 0.9.93 (see [Releases](https://github.com/gogits/gogs/releases) for binary versions) | |||
| ##### Current tip version: 0.9.94 (see [Releases](https://github.com/gogits/gogs/releases) for binary versions) | |||
| | Web | UI | Preview | | |||
| |:-------------:|:-------:|:-------:| | |||
| @@ -489,10 +489,11 @@ 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.label_templates.title = Load a predefined set of labels | |||
| issues.label_templates.info = There aren’t any labels yet. 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.label_templates.fail_to_load_file = Failed to load label template file '%s': %v | |||
| issues.open_tab = %d Open | |||
| issues.close_tab = %d Closed | |||
| issues.filter_label = Label | |||
| @@ -17,7 +17,7 @@ import ( | |||
| "github.com/gogits/gogs/modules/setting" | |||
| ) | |||
| const APP_VER = "0.9.93.0829" | |||
| const APP_VER = "0.9.94.0829" | |||
| func init() { | |||
| runtime.GOMAXPROCS(runtime.NumCPU()) | |||
| @@ -7,6 +7,7 @@ package models | |||
| import ( | |||
| "fmt" | |||
| "html/template" | |||
| "regexp" | |||
| "strconv" | |||
| "strings" | |||
| @@ -17,6 +18,40 @@ import ( | |||
| "github.com/gogits/gogs/modules/base" | |||
| ) | |||
| var labelColorPattern = regexp.MustCompile("#([a-fA-F0-9]{6})") | |||
| // GetLabelTemplateFile loads the label template file by given name, | |||
| // then parses and returns a list of name-color pairs. | |||
| func GetLabelTemplateFile(name string) ([][2]string, error) { | |||
| data, err := getRepoInitFile("label", name) | |||
| if err != nil { | |||
| return nil, fmt.Errorf("getRepoInitFile: %v", err) | |||
| } | |||
| lines := strings.Split(string(data), "\n") | |||
| list := make([][2]string, 0, len(lines)) | |||
| for i := 0; i < len(lines); i++ { | |||
| line := strings.TrimSpace(lines[i]) | |||
| if len(line) == 0 { | |||
| continue | |||
| } | |||
| fields := strings.SplitN(line, " ", 2) | |||
| if len(fields) != 2 { | |||
| return nil, fmt.Errorf("line is malformed: %s", line) | |||
| } | |||
| if !labelColorPattern.MatchString(fields[0]) { | |||
| return nil, fmt.Errorf("bad HTML color code in line: %s", line) | |||
| } | |||
| fields[1] = strings.TrimSpace(fields[1]) | |||
| list = append(list, [2]string{fields[1], fields[0]}) | |||
| } | |||
| return list, nil | |||
| } | |||
| // Label represents a label of repository for issues. | |||
| type Label struct { | |||
| ID int64 `xorm:"pk autoincr"` | |||
| @@ -62,9 +97,9 @@ func (l *Label) ForegroundColor() template.CSS { | |||
| return template.CSS("#000") | |||
| } | |||
| // NewLabel creates new label of repository. | |||
| func NewLabel(l *Label) error { | |||
| _, err := x.Insert(l) | |||
| // NewLabels creates new label(s) for a repository. | |||
| func NewLabels(labels ...*Label) error { | |||
| _, err := x.Insert(labels) | |||
| return err | |||
| } | |||
| @@ -220,8 +220,6 @@ 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"` | |||
| } | |||
| @@ -50,7 +50,7 @@ func CreateLabel(ctx *context.APIContext, form api.CreateLabelOption) { | |||
| Color: form.Color, | |||
| RepoID: ctx.Repo.Repository.ID, | |||
| } | |||
| if err := models.NewLabel(label); err != nil { | |||
| if err := models.NewLabels(label); err != nil { | |||
| ctx.Error(500, "NewLabel", err) | |||
| return | |||
| } | |||
| @@ -11,8 +11,6 @@ import ( | |||
| "io/ioutil" | |||
| "net/http" | |||
| "net/url" | |||
| "path" | |||
| "regexp" | |||
| "strings" | |||
| "time" | |||
| @@ -22,7 +20,6 @@ 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" | |||
| @@ -945,51 +942,30 @@ func Labels(ctx *context.Context) { | |||
| 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) | |||
| list, err := models.GetLabelTemplateFile(form.TemplateName) | |||
| if err != nil { | |||
| ctx.Flash.Error(ctx.Tr("repo.issues.label_templates.fail_to_load_file", form.TemplateName, err)) | |||
| 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) | |||
| } | |||
| labels := make([]*models.Label, len(list)) | |||
| for i := 0; i < len(list); i++ { | |||
| labels[i] = &models.Label{ | |||
| RepoID: ctx.Repo.Repository.ID, | |||
| Name: list[i][0], | |||
| Color: list[i][1], | |||
| } | |||
| } | |||
| if err := models.NewLabels(labels...); err != nil { | |||
| ctx.Handle(500, "NewLabels", err) | |||
| return | |||
| } | |||
| ctx.Redirect(ctx.Repo.RepoLink + "/labels") | |||
| } | |||
| @@ -1008,7 +984,7 @@ func NewLabel(ctx *context.Context, form auth.CreateLabelForm) { | |||
| Name: form.Title, | |||
| Color: form.Color, | |||
| } | |||
| if err := models.NewLabel(l); err != nil { | |||
| if err := models.NewLabels(l); err != nil { | |||
| ctx.Handle(500, "NewLabel", err) | |||
| return | |||
| } | |||
| @@ -1 +1 @@ | |||
| 0.9.93.0829 | |||
| 0.9.94.0829 | |||
| @@ -36,15 +36,15 @@ | |||
| {{template "base/alert" .}} | |||
| <div class="ui black label">{{.i18n.Tr "repo.issues.label_count" .NumLabels}}</div> | |||
| {{if $.IsRepositoryWriter}} | |||
| {{if eq .NumLabels 0}} | |||
| <div class="label list"> | |||
| {{if and $.IsRepositoryWriter (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"> | |||
| <div class="ui attached left aligned segment"> | |||
| <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"> | |||
| href="https://discuss.gogs.io/t/how-to-use-predefined-label-templates/599"> | |||
| <span class="octicon octicon-question"></span> | |||
| </a> | |||
| </h4> | |||
| @@ -54,7 +54,7 @@ | |||
| {{.CsrfTokenHtml}} | |||
| <div class="field"> | |||
| <div class="ui selection dropdown"> | |||
| <input type="hidden" name="template_name" id="templatename" value="Default"> | |||
| <input type="hidden" name="template_name" value="Default"> | |||
| <div class="default text">{{.i18n.Tr "repo.issues.label_templates.helper"}}</div> | |||
| <div class="menu"> | |||
| {{range .LabelTemplates}} | |||
| @@ -69,9 +69,7 @@ | |||
| </div> | |||
| </div> | |||
| {{end}} | |||
| {{end}} | |||
| <div class="label list"> | |||
| {{range .Labels}} | |||
| <li class="item"> | |||
| <div class="ui label" style="color: {{.ForegroundColor}}; background-color: {{.Color}}"><i class="octicon octicon-tag"></i> {{.Name}}</div> | |||