Browse Source

Add label descriptions (#3662)

* Add label descriptions

* Add default descriptions to label template
tags/v1.5.0-dev
Lauris BH 6 years ago
parent
commit
c0d41b1b77

+ 14
- 5
models/issue_label.go View File

var labelColorPattern = regexp.MustCompile("#([a-fA-F0-9]{6})") var labelColorPattern = regexp.MustCompile("#([a-fA-F0-9]{6})")


// GetLabelTemplateFile loads the label template file by given name, // 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) {
// then parses and returns a list of name-color pairs and optionally description.
func GetLabelTemplateFile(name string) ([][3]string, error) {
data, err := getRepoInitFile("label", name) data, err := getRepoInitFile("label", name)
if err != nil { if err != nil {
return nil, fmt.Errorf("getRepoInitFile: %v", err) return nil, fmt.Errorf("getRepoInitFile: %v", err)
} }


lines := strings.Split(string(data), "\n") lines := strings.Split(string(data), "\n")
list := make([][2]string, 0, len(lines))
list := make([][3]string, 0, len(lines))
for i := 0; i < len(lines); i++ { for i := 0; i < len(lines); i++ {
line := strings.TrimSpace(lines[i]) line := strings.TrimSpace(lines[i])
if len(line) == 0 { if len(line) == 0 {
continue continue
} }


fields := strings.SplitN(line, " ", 2)
parts := strings.SplitN(line, ";", 2)

fields := strings.SplitN(parts[0], " ", 2)
if len(fields) != 2 { if len(fields) != 2 {
return nil, fmt.Errorf("line is malformed: %s", line) return nil, fmt.Errorf("line is malformed: %s", line)
} }
return nil, fmt.Errorf("bad HTML color code in line: %s", line) return nil, fmt.Errorf("bad HTML color code in line: %s", line)
} }


var description string

if len(parts) > 1 {
description = strings.TrimSpace(parts[1])
}

fields[1] = strings.TrimSpace(fields[1]) fields[1] = strings.TrimSpace(fields[1])
list = append(list, [2]string{fields[1], fields[0]})
list = append(list, [3]string{fields[1], fields[0], description})
} }


return list, nil return list, nil
ID int64 `xorm:"pk autoincr"` ID int64 `xorm:"pk autoincr"`
RepoID int64 `xorm:"INDEX"` RepoID int64 `xorm:"INDEX"`
Name string Name string
Description string
Color string `xorm:"VARCHAR(7)"` Color string `xorm:"VARCHAR(7)"`
NumIssues int NumIssues int
NumClosedIssues int NumClosedIssues int

+ 2
- 0
models/migrations/migrations.go View File

NewMigration("remove is_owner, num_teams columns from org_user", removeIsOwnerColumnFromOrgUser), NewMigration("remove is_owner, num_teams columns from org_user", removeIsOwnerColumnFromOrgUser),
// v57 -> v58 // v57 -> v58
NewMigration("add closed_unix column for issues", addIssueClosedTime), NewMigration("add closed_unix column for issues", addIssueClosedTime),
// v58 -> v59
NewMigration("add label descriptions", addLabelsDescriptions),
} }


// Migrate database to current version // Migrate database to current version

+ 22
- 0
models/migrations/v58.go View File

// Copyright 2018 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package migrations

import (
"fmt"

"github.com/go-xorm/xorm"
)

func addLabelsDescriptions(x *xorm.Engine) error {
type Label struct {
Description string
}

if err := x.Sync2(new(Label)); err != nil {
return fmt.Errorf("Sync2: %v", err)
}
return nil
}

+ 4
- 3
modules/auth/repo_form.go View File



// CreateLabelForm form for creating label // CreateLabelForm form for creating label
type CreateLabelForm struct { type CreateLabelForm struct {
ID int64
Title string `binding:"Required;MaxSize(50)" locale:"repo.issues.label_name"`
Color string `binding:"Required;Size(7)" locale:"repo.issues.label_color"`
ID int64
Title string `binding:"Required;MaxSize(50)" locale:"repo.issues.label_title"`
Description string `binding:"MaxSize(200)" locale:"repo.issues.label_description"`
Color string `binding:"Required;Size(7)" locale:"repo.issues.label_color"`
} }


// Validate validates the fields // Validate validates the fields

+ 7
- 7
options/label/Default View File

#ee0701 bug
#cccccc duplicate
#84b6eb enhancement
#128a0c help wanted
#e6e6e6 invalid
#cc317c question
#ffffff wontfix
#ee0701 bug ; Something is not working
#cccccc duplicate ; This issue or pull request already exists
#84b6eb enhancement ; New feature
#128a0c help wanted ; Need some help
#e6e6e6 invalid ; Something is wrong
#cc317c question ; More information is needed
#ffffff wontfix ; This won't be fixed

+ 2
- 0
options/locale/locale_en-US.ini View File

issues.create = Create Issue issues.create = Create Issue
issues.new_label = New Label issues.new_label = New Label
issues.new_label_placeholder = Label name… issues.new_label_placeholder = Label name…
issues.new_label_desc_placeholder = Description…
issues.create_label = Create Label issues.create_label = Create Label
issues.label_templates.title = Load a predefined set of labels issues.label_templates.title = Load a predefined set of labels
issues.label_templates.info = There are not any labels yet. You can click on the "New Label" button above to create one or use a predefined set below. issues.label_templates.info = There are not any labels yet. You can click on the "New Label" button above to create one or use a predefined set below.
issues.cancel = Cancel issues.cancel = Cancel
issues.save = Save issues.save = Save
issues.label_title = Label name issues.label_title = Label name
issues.label_description = Label description
issues.label_color = Label color issues.label_color = Label color
issues.label_count = %d labels issues.label_count = %d labels
issues.label_open_issues = %d open issues issues.label_open_issues = %d open issues

+ 1
- 1
public/css/index.css
File diff suppressed because it is too large
View File


+ 1
- 0
public/js/index.js View File

$('.edit-label-button').click(function () { $('.edit-label-button').click(function () {
$('#label-modal-id').val($(this).data('id')); $('#label-modal-id').val($(this).data('id'));
$('.edit-label .new-label-input').val($(this).data('title')); $('.edit-label .new-label-input').val($(this).data('title'));
$('.edit-label .new-label-desc-input').val($(this).data('description'));
$('.edit-label .color-picker').val($(this).data('color')); $('.edit-label .color-picker').val($(this).data('color'));
$('.minicolors-swatch-color').css("background-color", $(this).data('color')); $('.minicolors-swatch-color').css("background-color", $(this).data('color'));
$('.edit-label.modal').modal({ $('.edit-label.modal').modal({

+ 11
- 0
public/less/_repository.less View File

} }
} }


.select-label {
.item {
max-width: 250px;
overflow: hidden;
text-overflow: ellipsis;
}
.desc {
padding-left: 16px;
}
}

.ui.tabs { .ui.tabs {
&.container { &.container {
margin-top: 14px; margin-top: 14px;

+ 9
- 6
routers/repo/issue_label.go View File

labels := make([]*models.Label, len(list)) labels := make([]*models.Label, len(list))
for i := 0; i < len(list); i++ { for i := 0; i < len(list); i++ {
labels[i] = &models.Label{ labels[i] = &models.Label{
RepoID: ctx.Repo.Repository.ID,
Name: list[i][0],
Color: list[i][1],
RepoID: ctx.Repo.Repository.ID,
Name: list[i][0],
Description: list[i][2],
Color: list[i][1],
} }
} }
if err := models.NewLabels(labels...); err != nil { if err := models.NewLabels(labels...); err != nil {
} }


l := &models.Label{ l := &models.Label{
RepoID: ctx.Repo.Repository.ID,
Name: form.Title,
Color: form.Color,
RepoID: ctx.Repo.Repository.ID,
Name: form.Title,
Description: form.Description,
Color: form.Color,
} }
if err := models.NewLabel(l); err != nil { if err := models.NewLabel(l); err != nil {
ctx.ServerError("NewLabel", err) ctx.ServerError("NewLabel", err)
} }


l.Name = form.Title l.Name = form.Title
l.Description = form.Description
l.Color = form.Color l.Color = form.Color
if err := models.UpdateLabel(l); err != nil { if err := models.UpdateLabel(l); err != nil {
ctx.ServerError("UpdateLabel", err) ctx.ServerError("UpdateLabel", err)

+ 31
- 8
templates/repo/issue/labels.tmpl View File

<form class="ui form" action="{{$.RepoLink}}/labels/new" method="post"> <form class="ui form" action="{{$.RepoLink}}/labels/new" method="post">
{{.CsrfTokenHtml}} {{.CsrfTokenHtml}}
<div class="ui grid"> <div class="ui grid">
<div class="five wide column">
<div class="three wide column">
<div class="ui small input"> <div class="ui small input">
<input class="new-label-input" name="title" placeholder="{{.i18n.Tr "repo.issues.new_label_placeholder"}}" autofocus required> <input class="new-label-input" name="title" placeholder="{{.i18n.Tr "repo.issues.new_label_placeholder"}}" autofocus required>
</div> </div>
</div> </div>
<div class="five wide column">
<div class="ui small fluid input">
<input class="new-label-desc-input" name="description" placeholder="{{.i18n.Tr "repo.issues.new_label_desc_placeholder"}}">
</div>
</div>
<div class="color picker column"> <div class="color picker column">
<input class="color-picker" name="color" value="#70c24a" required> <input class="color-picker" name="color" value="#70c24a" required>
</div> </div>
</div> </div>
{{end}} {{end}}


<div class="ui divider"></div>

{{range .Labels}} {{range .Labels}}
<li class="item"> <li class="item">
<div class="ui label" style="color: {{.ForegroundColor}}; background-color: {{.Color}}"><i class="octicon octicon-tag"></i> {{.Name}}</div>
{{if $.IsRepositoryWriter}}
<a class="ui right delete-button" href="#" data-url="{{$.RepoLink}}/labels/delete" data-id="{{.ID}}"><i class="octicon octicon-trashcan"></i> {{$.i18n.Tr "repo.issues.label_delete"}}</a>
<a class="ui right edit-label-button" href="#" data-id={{.ID}} data-title={{.Name}} data-color={{.Color}}><i class="octicon octicon-pencil"></i> {{$.i18n.Tr "repo.issues.label_edit"}}</a>
{{end}}
<a class="ui right open-issues" href="{{$.RepoLink}}/issues?labels={{.ID}}"><i class="octicon octicon-issue-opened"></i> {{$.i18n.Tr "repo.issues.label_open_issues" .NumOpenIssues}}</a>
<div class="ui grid">
<div class="three wide column">
<div class="ui label" style="color: {{.ForegroundColor}}; background-color: {{.Color}}"><i class="octicon octicon-tag"></i> {{.Name}}</div>
</div>
<div class="seven wide column">
{{.Description}}
</div>
<div class="three wide column">
<a class="ui right open-issues" href="{{$.RepoLink}}/issues?labels={{.ID}}"><i class="octicon octicon-issue-opened"></i> {{$.i18n.Tr "repo.issues.label_open_issues" .NumOpenIssues}}</a>
</div>
<div class="three wide column">
{{if $.IsRepositoryWriter}}
<a class="ui right delete-button" href="#" data-url="{{$.RepoLink}}/labels/delete" data-id="{{.ID}}"><i class="octicon octicon-trashcan"></i> {{$.i18n.Tr "repo.issues.label_delete"}}</a>
<a class="ui right edit-label-button" href="#" data-id="{{.ID}}" data-title="{{.Name}}" data-description="{{.Description}}" data-color={{.Color}}><i class="octicon octicon-pencil"></i> {{$.i18n.Tr "repo.issues.label_edit"}}</a>
{{end}}
</div>
</div>
</li> </li>
{{end}} {{end}}
</div> </div>
{{.CsrfTokenHtml}} {{.CsrfTokenHtml}}
<input id="label-modal-id" name="id" type="hidden"> <input id="label-modal-id" name="id" type="hidden">
<div class="ui grid"> <div class="ui grid">
<div class="five wide column">
<div class="three wide column">
<div class="ui small input"> <div class="ui small input">
<input class="new-label-input" name="title" placeholder="{{.i18n.Tr "repo.issues.new_label_placeholder"}}" autofocus required> <input class="new-label-input" name="title" placeholder="{{.i18n.Tr "repo.issues.new_label_placeholder"}}" autofocus required>
</div> </div>
</div> </div>
<div class="five wide column">
<div class="ui small fluid input">
<input class="new-label-desc-input" name="description" placeholder="{{.i18n.Tr "repo.issues.new_label_desc_placeholder"}}">
</div>
</div>
<div class="color picker column"> <div class="color picker column">
<input class="color-picker" name="color" value="#70c24a" required> <input class="color-picker" name="color" value="#70c24a" required>
</div> </div>

+ 1
- 1
templates/repo/issue/list.tmpl View File

<a class="ui label" href="{{$.RepoLink}}/src/branch/{{.Ref}}">{{.Ref}}</a> <a class="ui label" href="{{$.RepoLink}}/src/branch/{{.Ref}}">{{.Ref}}</a>
{{end}} {{end}}
{{range .Labels}} {{range .Labels}}
<a class="ui label" href="{{$.Link}}?q={{$.Keyword}}&type={{$.ViewType}}&state={{$.State}}&labels={{.ID}}&milestone={{$.MilestoneID}}&assignee={{$.AssigneeID}}" style="color: {{.ForegroundColor}}; background-color: {{.Color}}">{{.Name}}</a>
<a class="ui label" href="{{$.Link}}?q={{$.Keyword}}&type={{$.ViewType}}&state={{$.State}}&labels={{.ID}}&milestone={{$.MilestoneID}}&assignee={{$.AssigneeID}}" style="color: {{.ForegroundColor}}; background-color: {{.Color}}" title="{{.Description}}">{{.Name}}</a>
{{end}} {{end}}


{{if .NumComments}} {{if .NumComments}}

+ 3
- 2
templates/repo/issue/view_content/sidebar.tmpl View File

<div class="filter menu" data-action="update" data-issue-id="{{$.Issue.ID}}" data-update-url="{{$.RepoLink}}/issues/labels"> <div class="filter menu" data-action="update" data-issue-id="{{$.Issue.ID}}" data-update-url="{{$.RepoLink}}/issues/labels">
<div class="no-select item">{{.i18n.Tr "repo.issues.new.clear_labels"}}</div> <div class="no-select item">{{.i18n.Tr "repo.issues.new.clear_labels"}}</div>
{{range .Labels}} {{range .Labels}}
<a class="{{if .IsChecked}}checked{{end}} item" href="#" data-id="{{.ID}}" data-id-selector="#label_{{.ID}}"><span class="octicon {{if .IsChecked}}octicon-check{{end}}"></span><span class="label color" style="background-color: {{.Color}}"></span> {{.Name}}</a>
<a class="{{if .IsChecked}}checked{{end}} item" href="#" data-id="{{.ID}}" data-id-selector="#label_{{.ID}}"><span class="octicon {{if .IsChecked}}octicon-check{{end}}"></span><span class="label color" style="background-color: {{.Color}}"></span> {{.Name}}
{{if .Description }}<br><small class="desc">{{.Description}}</small>{{end}}</a>
{{end}} {{end}}
</div> </div>
</div> </div>
<span class="no-select item {{if .HasSelectedLabel}}hide{{end}}">{{.i18n.Tr "repo.issues.new.no_label"}}</span> <span class="no-select item {{if .HasSelectedLabel}}hide{{end}}">{{.i18n.Tr "repo.issues.new.no_label"}}</span>
{{range .Labels}} {{range .Labels}}
<div class="item"> <div class="item">
<a class="ui label {{if not .IsChecked}}hide{{end}}" id="label_{{.ID}}" href="{{$.RepoLink}}/issues?labels={{.ID}}" style="color: {{.ForegroundColor}}; background-color: {{.Color}}">{{.Name}}</a>
<a class="ui label {{if not .IsChecked}}hide{{end}}" id="label_{{.ID}}" href="{{$.RepoLink}}/issues?labels={{.ID}}" style="color: {{.ForegroundColor}}; background-color: {{.Color}}" title="{{.Description}}">{{.Name}}</a>
</div> </div>


{{end}} {{end}}

+ 1
- 1
templates/user/dashboard/issues.tmpl View File

especially on mobile views. */}} especially on mobile views. */}}
<span style="line-height: 2.5"> <span style="line-height: 2.5">
{{range .}} {{range .}}
<a class="ui label" href="{{$.Link}}?q={{$.Keyword}}&type={{$.ViewType}}&state={{$.State}}&labels={{.ID}}&milestone={{$.MilestoneID}}&assignee={{$.AssigneeID}}" style="color: {{.ForegroundColor}}; background-color: {{.Color}}">{{.Name}}</a>
<a class="ui label" href="{{$.Link}}?q={{$.Keyword}}&type={{$.ViewType}}&state={{$.State}}&labels={{.ID}}&milestone={{$.MilestoneID}}&assignee={{$.AssigneeID}}" style="color: {{.ForegroundColor}}; background-color: {{.Color}}" title="{{.Description}}">{{.Name}}</a>
{{end}} {{end}}
</span> </span>
{{end}} {{end}}

Loading…
Cancel
Save