| @@ -186,6 +186,7 @@ func runWeb(*cli.Context) { | |||||
| r.Post("/issues/:index", bindIgnErr(auth.CreateIssueForm{}), repo.UpdateIssue) | r.Post("/issues/:index", bindIgnErr(auth.CreateIssueForm{}), repo.UpdateIssue) | ||||
| r.Post("/issues/:index/assignee", repo.UpdateAssignee) | r.Post("/issues/:index/assignee", repo.UpdateAssignee) | ||||
| r.Post("/issues/:index/milestone", repo.UpdateIssueMilestone) | r.Post("/issues/:index/milestone", repo.UpdateIssueMilestone) | ||||
| r.Post("/issues/labels/new", bindIgnErr(auth.CreateLabelForm{}), repo.NewLabel) | |||||
| r.Get("/issues/milestones", repo.Milestones) | r.Get("/issues/milestones", repo.Milestones) | ||||
| r.Get("/issues/milestones/new", repo.NewMilestone) | r.Get("/issues/milestones/new", repo.NewMilestone) | ||||
| r.Post("/issues/milestones/new", bindIgnErr(auth.CreateMilestoneForm{}), repo.NewMilestonePost) | r.Post("/issues/milestones/new", bindIgnErr(auth.CreateMilestoneForm{}), repo.NewMilestonePost) | ||||
| @@ -17,7 +17,7 @@ import ( | |||||
| "github.com/gogits/gogs/modules/base" | "github.com/gogits/gogs/modules/base" | ||||
| ) | ) | ||||
| const APP_VER = "0.3.5.0516 Alpha" | |||||
| const APP_VER = "0.3.5.0518 Alpha" | |||||
| func init() { | func init() { | ||||
| base.AppVer = APP_VER | base.AppVer = APP_VER | ||||
| @@ -400,17 +400,6 @@ func UpdateIssueUserPairsByMentions(uids []int64, iid int64) error { | |||||
| return nil | return nil | ||||
| } | } | ||||
| // Label represents a label of repository for issues. | |||||
| type Label struct { | |||||
| Id int64 | |||||
| RepoId int64 `xorm:"INDEX"` | |||||
| Name string | |||||
| Color string | |||||
| NumIssues int | |||||
| NumClosedIssues int | |||||
| NumOpenIssues int `xorm:"-"` | |||||
| } | |||||
| // _____ .__.__ __ | // _____ .__.__ __ | ||||
| // / \ |__| | ____ _______/ |_ ____ ____ ____ | // / \ |__| | ____ _______/ |_ ____ ____ ____ | ||||
| // / \ / \| | | _/ __ \ / ___/\ __\/ _ \ / \_/ __ \ | // / \ / \| | | _/ __ \ / ___/\ __\/ _ \ / \_/ __ \ | ||||
| @@ -622,6 +611,42 @@ func DeleteMilestone(m *Milestone) (err error) { | |||||
| return sess.Commit() | return sess.Commit() | ||||
| } | } | ||||
| // .____ ___. .__ | |||||
| // | | _____ \_ |__ ____ | | | |||||
| // | | \__ \ | __ \_/ __ \| | | |||||
| // | |___ / __ \| \_\ \ ___/| |__ | |||||
| // |_______ (____ /___ /\___ >____/ | |||||
| // \/ \/ \/ \/ | |||||
| // Label represents a label of repository for issues. | |||||
| type Label struct { | |||||
| Id int64 | |||||
| RepoId int64 `xorm:"INDEX"` | |||||
| Name string | |||||
| Color string `xorm:"VARCHAR(7)"` | |||||
| NumIssues int | |||||
| NumClosedIssues int | |||||
| NumOpenIssues int `xorm:"-"` | |||||
| } | |||||
| // CalOpenIssues calculates the open issues of label. | |||||
| func (m *Label) CalOpenIssues() { | |||||
| m.NumOpenIssues = m.NumIssues - m.NumClosedIssues | |||||
| } | |||||
| // NewLabel creates new label of repository. | |||||
| func NewLabel(l *Label) error { | |||||
| _, err := orm.Insert(l) | |||||
| return err | |||||
| } | |||||
| // GetLabels returns a list of labels of given repository ID. | |||||
| func GetLabels(repoId int64) ([]*Label, error) { | |||||
| labels := make([]*Label, 0, 10) | |||||
| err := orm.Where("repo_id=?", repoId).Find(&labels) | |||||
| return labels, err | |||||
| } | |||||
| // _________ __ | // _________ __ | ||||
| // \_ ___ \ ____ _____ _____ ____ _____/ |_ | // \_ ___ \ ____ _____ _____ ____ _____/ |_ | ||||
| // / \ \/ / _ \ / \ / \_/ __ \ / \ __\ | // / \ \/ / _ \ / \ / \_/ __ \ / \ __\ | ||||
| @@ -185,9 +185,8 @@ func LoginUser(uname, passwd string) (*User, error) { | |||||
| } else { | } else { | ||||
| if !has { | if !has { | ||||
| var sources []LoginSource | var sources []LoginSource | ||||
| cond := &LoginSource{IsActived: true, AllowAutoRegister: true} | |||||
| err = orm.UseBool().Find(&sources, cond) | |||||
| if err != nil { | |||||
| if err = orm.UseBool().Find(&sources, | |||||
| &LoginSource{IsActived: true, AllowAutoRegister: true}); err != nil { | |||||
| return nil, err | return nil, err | ||||
| } | } | ||||
| @@ -35,7 +35,7 @@ func init() { | |||||
| tables = append(tables, new(User), new(PublicKey), new(Repository), new(Watch), | tables = append(tables, new(User), new(PublicKey), new(Repository), new(Watch), | ||||
| new(Action), new(Access), new(Issue), new(Comment), new(Oauth2), new(Follow), | new(Action), new(Access), new(Issue), new(Comment), new(Oauth2), new(Follow), | ||||
| new(Mirror), new(Release), new(LoginSource), new(Webhook), new(IssueUser), | new(Mirror), new(Release), new(LoginSource), new(Webhook), new(IssueUser), | ||||
| new(Milestone)) | |||||
| new(Milestone), new(Label)) | |||||
| } | } | ||||
| func LoadModelsConfig() { | func LoadModelsConfig() { | ||||
| @@ -171,6 +171,31 @@ func (f *CreateMilestoneForm) Validate(errors *binding.Errors, req *http.Request | |||||
| validate(errors, data, f) | validate(errors, data, f) | ||||
| } | } | ||||
| // .____ ___. .__ | |||||
| // | | _____ \_ |__ ____ | | | |||||
| // | | \__ \ | __ \_/ __ \| | | |||||
| // | |___ / __ \| \_\ \ ___/| |__ | |||||
| // |_______ (____ /___ /\___ >____/ | |||||
| // \/ \/ \/ \/ | |||||
| type CreateLabelForm struct { | |||||
| Title string `form:"title" binding:"Required;MaxSize(50)"` | |||||
| Color string `form:"color" binding:"Required;Size(7)"` | |||||
| } | |||||
| func (f *CreateLabelForm) Name(field string) string { | |||||
| names := map[string]string{ | |||||
| "Title": "Label name", | |||||
| "Color": "Label color", | |||||
| } | |||||
| return names[field] | |||||
| } | |||||
| func (f *CreateLabelForm) Validate(errors *binding.Errors, req *http.Request, context martini.Context) { | |||||
| data := context.Get(reflect.TypeOf(base.TmplData{})).Interface().(base.TmplData) | |||||
| validate(errors, data, f) | |||||
| } | |||||
| // __________ .__ | // __________ .__ | ||||
| // \______ \ ____ | | ____ _____ ______ ____ | // \______ \ ____ | | ____ _____ ______ ____ | ||||
| // | _// __ \| | _/ __ \\__ \ / ___// __ \ | // | _// __ \| | _/ __ \\__ \ / ___// __ \ | ||||
| @@ -63,7 +63,16 @@ func Issues(ctx *middleware.Context) { | |||||
| } | } | ||||
| mid = mile.Id | mid = mile.Id | ||||
| } | } | ||||
| fmt.Println(mid) | |||||
| labels, err := models.GetLabels(ctx.Repo.Repository.Id) | |||||
| if err != nil { | |||||
| ctx.Handle(500, "issue.Issues(GetLabels): %v", err) | |||||
| return | |||||
| } | |||||
| for _, l := range labels { | |||||
| l.CalOpenIssues() | |||||
| } | |||||
| ctx.Data["Labels"] = labels | |||||
| page, _ := base.StrTo(ctx.Query("page")).Int() | page, _ := base.StrTo(ctx.Query("page")).Int() | ||||
| @@ -591,6 +600,28 @@ func Comment(ctx *middleware.Context, params martini.Params) { | |||||
| ctx.Redirect(fmt.Sprintf("%s/issues/%d", ctx.Repo.RepoLink, index)) | ctx.Redirect(fmt.Sprintf("%s/issues/%d", ctx.Repo.RepoLink, index)) | ||||
| } | } | ||||
| func NewLabel(ctx *middleware.Context, form auth.CreateLabelForm) { | |||||
| if ctx.HasError() { | |||||
| Issues(ctx) | |||||
| return | |||||
| } | |||||
| l := &models.Label{ | |||||
| RepoId: ctx.Repo.Repository.Id, | |||||
| Name: form.Title, | |||||
| Color: form.Color, | |||||
| } | |||||
| if err := models.NewLabel(l); err != nil { | |||||
| ctx.Handle(500, "issue.NewLabel(NewLabel)", err) | |||||
| return | |||||
| } | |||||
| ctx.Redirect(ctx.Repo.RepoLink + "/issues") | |||||
| } | |||||
| func UpdateLabel(ctx *middleware.Context, params martini.Params) { | |||||
| } | |||||
| func Milestones(ctx *middleware.Context) { | func Milestones(ctx *middleware.Context) { | ||||
| ctx.Data["Title"] = "Milestones" | ctx.Data["Title"] = "Milestones" | ||||
| ctx.Data["IsRepoToolbarIssues"] = true | ctx.Data["IsRepoToolbarIssues"] = true | ||||
| @@ -16,17 +16,18 @@ | |||||
| <div class="label-filter"> | <div class="label-filter"> | ||||
| <h4>Label</h4> | <h4>Label</h4> | ||||
| <ul class="list-unstyled"> | <ul class="list-unstyled"> | ||||
| <li><a href="#"><span class="pull-right count">1</span><span class="color" style="background-color: red"></span>bug</a></li> | |||||
| <li><a href=""><span class="pull-right count">1</span><span class="color" style="background-color: #AAA"></span>duplicate</a></li> | |||||
| <li><a href=""><span class="pull-right count">1</span><span class="color" style="background-color: #0072E3"></span>enhancement</a></li> | |||||
| {{range .Labels}} | |||||
| <li><a href="#"><span class="pull-right count">{{if $.IsShowClosed}}{{.NumClosedIssues}}{{else}}{{.NumOpenIssues}}{{end}}</span><span class="color" style="background-color: {{.Color}}"></span>{{.Name}}</a></li> | |||||
| {{end}} | |||||
| </ul> | </ul> | ||||
| <button class="btn btn-default btn-block label-button">Manage Labels</button> | <button class="btn btn-default btn-block label-button">Manage Labels</button> | ||||
| <hr/> | <hr/> | ||||
| <form id="label-add-form" action="#" method="post"> | |||||
| <form id="label-add-form" action="{{$.RepoLink}}/issues/labels/new" method="post"> | |||||
| {{.CsrfTokenHtml}} | |||||
| <h5><strong>New Label</strong></h5> | <h5><strong>New Label</strong></h5> | ||||
| <div class="input-group label-color-picker form-group"> | <div class="input-group label-color-picker form-group"> | ||||
| <input type="text" value="" class="form-control" name="name" required="required" id="label-name-ipt"/> | |||||
| <input type="hidden" value="" name="color" id="label-color-ipt"/> | |||||
| <input type="text" class="form-control" name="title" required="required" id="label-name-ipt"/> | |||||
| <input type="hidden" name="color" id="label-color-ipt"/> | |||||
| <span class="input-group-addon"><i></i></span> | <span class="input-group-addon"><i></i></span> | ||||
| </div> | </div> | ||||
| <div class="form-group text-right"> | <div class="form-group text-right"> | ||||
| @@ -36,6 +37,7 @@ | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| <div class="col-md-9"> | <div class="col-md-9"> | ||||
| {{template "base/alert" .}} | |||||
| <div class="filter-option"> | <div class="filter-option"> | ||||
| <div class="btn-group"> | <div class="btn-group"> | ||||
| <a class="btn btn-default issue-open{{if not .IsShowClosed}} active{{end}}" href="{{.RepoLink}}/issues?type={{.ViewType}}">{{..IssueStats.OpenCount}} Open</a> | <a class="btn btn-default issue-open{{if not .IsShowClosed}} active{{end}}" href="{{.RepoLink}}/issues?type={{.ViewType}}">{{..IssueStats.OpenCount}} Open</a> | ||||