mirror of
				https://gitee.com/gitea/gitea
				synced 2025-11-04 08:30:25 +08:00 
			
		
		
		
	Load a set of predefined labels (#3459)
* 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 variable
This commit is contained in:
		@@ -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).
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										7
									
								
								conf/label/Default
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								conf/label/Default
									
									
									
									
									
										Normal file
									
								
							@@ -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)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// __________       .__
 | 
			
		||||
// \______   \ ____ |  |   ____ _____    ______ ____
 | 
			
		||||
//  |       _// __ \|  | _/ __ \\__  \  /  ___// __ \
 | 
			
		||||
 
 | 
			
		||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							@@ -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}}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user