Browse Source

#1253 : Remove label from repositories

pull/5260/head
isundil 7 years ago
parent
commit
b5998f3ee3
  1. 2
      models/issue_label.go
  2. 2
      models/models.go
  3. 45
      models/repo.go
  4. 3
      public/css/gogs.css
  5. 12
      public/js/gogs.js
  6. 3
      public/less/_repository.less
  7. 23
      routes/repo/setting.go
  8. 3
      routes/user/setting.go
  9. 27
      templates/repo/settings/options.tmpl

2
models/issue_label.go

@ -237,7 +237,7 @@ func DeleteLabel(repoID, labelID int64) error {
// |___/____ >____ >____/ \___ >_______ (____ /___ /\___ >____/ // |___/____ >____ >____/ \___ >_______ (____ /___ /\___ >____/
// \/ \/ \/ \/ \/ \/ \/ // \/ \/ \/ \/ \/ \/ \/
// IssueLabel represetns an issue-lable relation. // IssueLabel represents an issue-label relation.
type IssueLabel struct { type IssueLabel struct {
ID int64 ID int64
IssueID int64 `xorm:"UNIQUE(s)"` IssueID int64 `xorm:"UNIQUE(s)"`

2
models/models.go

@ -65,7 +65,7 @@ func init() {
new(Mirror), new(Release), new(LoginSource), new(Webhook), new(HookTask), new(Mirror), new(Release), new(LoginSource), new(Webhook), new(HookTask),
new(ProtectBranch), new(ProtectBranchWhitelist), new(ProtectBranch), new(ProtectBranchWhitelist),
new(Team), new(OrgUser), new(TeamUser), new(TeamRepo), new(Team), new(OrgUser), new(TeamUser), new(TeamRepo),
new(Notice), new(EmailAddress), new (RepositoryLabel)) new(Notice), new(EmailAddress), new (RepositoryLabel), new (RepositoryRepoLabel))
gonicNames := []string{"SSL"} gonicNames := []string{"SSL"}
for _, name := range gonicNames { for _, name := range gonicNames {

45
models/repo.go

@ -158,6 +158,13 @@ type RepositoryLabel struct {
UpdatedUnix int64 UpdatedUnix int64
} }
// RepositoryRepoLabel represents an Repository-label relation.
type RepositoryRepoLabel struct {
ID int64
RepositoryID int64 `xorm:"UNIQUE(s)"`
LabelID int64 `xorm:"UNIQUE(s)"`
}
// Repository contains information of a repository. // Repository contains information of a repository.
type Repository struct { type Repository struct {
ID int64 ID int64
@ -1658,12 +1665,13 @@ func (l *RepositoryLabel) ForegroundColor() template.CSS {
return template.CSS("#000") return template.CSS("#000")
} }
func CreateRepositoryLabel(owner *User, opts *CreateRepoLabelOptions) (_ *RepositoryLabel, err error) { func CreateRepositoryLabel(owner *User, opts *CreateRepoLabelOptions) (_ *RepositoryLabel, err error) {
if !owner.CanCreateRepo() { if !owner.CanCreateRepo() {
return nil, errors.ReachLimitOfRepo{owner.RepoCreationNum()} return nil, errors.ReachLimitOfRepo{owner.RepoCreationNum()}
} }
// FIXME check color is /#[0-9A-Fa-F]{6}/ if !labelColorPattern.MatchString(opts.Color) {
return nil, fmt.Errorf("bad HTML color code %s", opts.Color)
}
repoLabel := &RepositoryLabel{ repoLabel := &RepositoryLabel{
OwnerID: owner.ID, OwnerID: owner.ID,
@ -1690,7 +1698,9 @@ func UpdateRepositoryLabel(id int64, owner *User, opts *CreateRepoLabelOptions)
if !owner.CanCreateRepo() { if !owner.CanCreateRepo() {
return nil, errors.ReachLimitOfRepo{owner.RepoCreationNum()} return nil, errors.ReachLimitOfRepo{owner.RepoCreationNum()}
} }
// FIXME check color is /#[0-9A-Fa-F]{6}/ if !labelColorPattern.MatchString(opts.Color) {
return nil, fmt.Errorf("bad HTML color code %s", opts.Color)
}
repoLabel, err := GetRepositoryLabel(id, owner) repoLabel, err := GetRepositoryLabel(id, owner)
if err != nil { if err != nil {
@ -1743,10 +1753,37 @@ func GetRepositoryLabels(userID int64) ([]*RepositoryLabel, error) {
return labels, nil return labels, nil
} }
func GetRepositoryLabelsForRepository(repo *Repository) ([]*RepositoryLabel, error) {
labels := make([]*RepositoryLabel, 0, 5)
if err := x.
Where("repository_id = ?", repo.ID).
Join("INNER", "repository_repo_label", "repository_repo_label.label_id = repository_label.id").
Find(&labels); err != nil {
return nil, fmt.Errorf("select repository labels: %v", err)
}
return labels, nil
}
func RemoveRepoLabelFromRepository(repo *Repository, labelID int64, user *User) (err error) {
sess := x.NewSession()
defer sess.Close()
if err = sess.Begin(); err != nil {
return err
}
// FIXME check that user is OwnerID of the label and admin on the repository
label := &RepositoryRepoLabel{ RepositoryID: repo.ID, LabelID: labelID }
if _, err = sess.Delete(label); err != nil {
return fmt.Errorf("remove label '%d' for repository '%d' : %v", labelID, repo.ID, err)
}
return sess.Commit()
}
func GetRepositoryLabel(labelId int64, owner *User) (*RepositoryLabel, error) { func GetRepositoryLabel(labelId int64, owner *User) (*RepositoryLabel, error) {
label := new(RepositoryLabel) label := new(RepositoryLabel)
if has, err := x.Where("ID = ? AND ownerID = ?", labelId, owner.ID).Get(label); err != nil { if has, err := x.Where("ID = ? AND owner_id = ?", labelId, owner.ID).Get(label); err != nil {
return nil, fmt.Errorf("select repository labels: %v", err) return nil, fmt.Errorf("select repository labels: %v", err)
} else if !has { } else if !has {
return nil, fmt.Errorf("Label %d not found", labelId) return nil, fmt.Errorf("Label %d not found", labelId)

3
public/css/gogs.css

@ -1631,6 +1631,9 @@ footer .ui.language .menu {
.repository.options .danger .ui.divider { .repository.options .danger .ui.divider {
margin: 0; margin: 0;
} }
.repository.options .repository-label-list .removed {
text-decoration: line-through;
}
.repository.new.issue .comment.form .comment .avatar { .repository.new.issue .comment.form .comment .avatar {
width: 3em; width: 3em;
} }

12
public/js/gogs.js

@ -254,6 +254,18 @@ function initRepository() {
$prompt.hide(); $prompt.hide();
} }
}); });
var addLabels = [],
removeLabels = [];
$('.repository-label-list').click(function(e) {
if (e.target.classList.contains("button") && e.target.classList.contains("delete")) {
var $target = $(e.target).parent(".label");
$target.addClass("removed");
$(e.target).remove();
removeLabels.push($target.data("labelid"));
$('.repository-label-to-remove').val(removeLabels.join(';'));
}
});
} }
// Branches // Branches

3
public/less/_repository.less

@ -546,6 +546,9 @@
margin: 0; margin: 0;
} }
} }
.repository-label-list .removed {
text-decoration: line-through;
}
} }
@comment-avatar-width: 3em; @comment-avatar-width: 3em;

23
routes/repo/setting.go

@ -8,6 +8,7 @@ import (
"fmt" "fmt"
"strings" "strings"
"time" "time"
"strconv"
log "gopkg.in/clog.v1" log "gopkg.in/clog.v1"
@ -34,6 +35,13 @@ const (
func Settings(c *context.Context) { func Settings(c *context.Context) {
c.Title("repo.settings") c.Title("repo.settings")
c.PageIs("SettingsOptions") c.PageIs("SettingsOptions")
repoLabels, err := models.GetRepositoryLabelsForRepository(c.Repo.Repository)
if err != nil {
c.ServerError("GetUserAndCollaborativeRepositories", err)
return
}
c.Data["RepositoryLabels"] = repoLabels
c.Success(SETTINGS_OPTIONS) c.Success(SETTINGS_OPTIONS)
} }
@ -135,6 +143,21 @@ func SettingsPost(c *context.Context, f form.RepoSetting) {
c.Flash.Info(c.Tr("repo.settings.mirror_sync_in_progress")) c.Flash.Info(c.Tr("repo.settings.mirror_sync_in_progress"))
c.Redirect(repo.Link() + "/settings") c.Redirect(repo.Link() + "/settings")
case "repository-labels":
repositoryLabelsToRemove := strings.Split(c.Query("repositoryLabelsToRemove"), ";")
for i := 0; i < len(repositoryLabelsToRemove) ; i++ {
if labelId, err := strconv.ParseInt(repositoryLabelsToRemove[i], 10, 64); err == nil {
models.RemoveRepoLabelFromRepository(c.Repo.Repository, labelId, c.User)
}
}
repositoryLabelsToAdd := strings.Split(c.Query("repositoryLabelsToAdd"), ";")
for i := 0; i < len(repositoryLabelsToAdd) ; i++ {
if labelId, err := strconv.ParseInt(repositoryLabelsToAdd[i], 10, 64); err == nil {
// FIXME models.AddRepoLabelToRepository(c.Repo.Repository, labelId, c.User)
}
}
c.Redirect(repo.Link() + "/settings")
case "advanced": case "advanced":
repo.EnableWiki = f.EnableWiki repo.EnableWiki = f.EnableWiki
repo.AllowPublicWiki = f.AllowPublicWiki repo.AllowPublicWiki = f.AllowPublicWiki

3
routes/user/setting.go

@ -564,8 +564,7 @@ func SettingsAddOrEditRepoLabel(c *context.Context) {
func SettingsDeleteRepoLabel(c *context.Context) { func SettingsDeleteRepoLabel(c *context.Context) {
if err := models.DeleteRepositoryLabel(c.QueryInt64("id"), c.User); err != nil { if err := models.DeleteRepositoryLabel(c.QueryInt64("id"), c.User); err != nil {
//c.NotFound() c.NotFound()
c.ServerError("", err)
return return
} }
c.JSONSuccess(map[string]interface{}{ c.JSONSuccess(map[string]interface{}{

27
templates/repo/settings/options.tmpl

@ -88,6 +88,33 @@
</div> </div>
{{end}} {{end}}
<div class="ui top attached header">
{{.i18n.Tr "repo.settings.labels"}}
</div>
<div class="repository-label ui attached segment">
<form class="ui form" method="POST">
{{.CSRFTokenHTML}}
<input type="hidden" name="action" value="repository-labels">
<input type="hidden" name="repositoryLabelsToAdd" value="" class="repository-label-to-add" />
<input type="hidden" name="repositoryLabelsToRemove" value="" class="repository-label-to-remove"/>
<div class="field repository-label-list">
{{range .RepositoryLabels}}
<span class="">
<span class="column">
<span class="ui label" style="background-color: {{.Color}}; color: {{.ForegroundColor}}" data-labelid="{{.ID}}">
{{.Name}}
<i class="delete button icon"></i>
</span>
</span>
</span>
{{end}}
</div>
<div class="field">
<button class="ui green button submit">{{$.i18n.Tr "repo.settings.update_settings"}}</button>
</div>
</form>
</div>
<div class="ui top attached header"> <div class="ui top attached header">
{{.i18n.Tr "repo.settings.advanced_settings"}} {{.i18n.Tr "repo.settings.advanced_settings"}}
</div> </div>

Loading…
Cancel
Save