| @@ -330,7 +330,7 @@ func runWeb(ctx *cli.Context) { | |||||
| m.Get("/template/*", dev.TemplatePreview) | m.Get("/template/*", dev.TemplatePreview) | ||||
| } | } | ||||
| reqAdmin := middleware.RequireAdmin() | |||||
| reqRepoAdmin := middleware.RequireRepoAdmin() | |||||
| // Organization. | // Organization. | ||||
| m.Group("/org", func() { | m.Group("/org", func() { | ||||
| @@ -405,7 +405,7 @@ func runWeb(ctx *cli.Context) { | |||||
| m.Post("/:name", repo.GitHooksEditPost) | m.Post("/:name", repo.GitHooksEditPost) | ||||
| }, middleware.GitHookService()) | }, middleware.GitHookService()) | ||||
| }) | }) | ||||
| }, reqSignIn, middleware.RepoAssignment(true), reqAdmin) | |||||
| }, reqSignIn, middleware.RepoAssignment(true), reqRepoAdmin) | |||||
| m.Group("/:username/:reponame", func() { | m.Group("/:username/:reponame", func() { | ||||
| m.Get("/action/:action", repo.Action) | m.Get("/action/:action", repo.Action) | ||||
| @@ -423,14 +423,14 @@ func runWeb(ctx *cli.Context) { | |||||
| m.Post("/new", bindIgnErr(auth.CreateLabelForm{}), repo.NewLabel) | m.Post("/new", bindIgnErr(auth.CreateLabelForm{}), repo.NewLabel) | ||||
| m.Post("/edit", bindIgnErr(auth.CreateLabelForm{}), repo.UpdateLabel) | m.Post("/edit", bindIgnErr(auth.CreateLabelForm{}), repo.UpdateLabel) | ||||
| m.Post("/delete", repo.DeleteLabel) | m.Post("/delete", repo.DeleteLabel) | ||||
| }) | |||||
| }, reqRepoAdmin) | |||||
| m.Group("/milestones", func() { | m.Group("/milestones", func() { | ||||
| m.Get("/new", repo.NewMilestone) | m.Get("/new", repo.NewMilestone) | ||||
| m.Post("/new", bindIgnErr(auth.CreateMilestoneForm{}), repo.NewMilestonePost) | m.Post("/new", bindIgnErr(auth.CreateMilestoneForm{}), repo.NewMilestonePost) | ||||
| m.Get("/:index/edit", repo.UpdateMilestone) | m.Get("/:index/edit", repo.UpdateMilestone) | ||||
| m.Post("/:index/edit", bindIgnErr(auth.CreateMilestoneForm{}), repo.UpdateMilestonePost) | m.Post("/:index/edit", bindIgnErr(auth.CreateMilestoneForm{}), repo.UpdateMilestonePost) | ||||
| m.Get("/:index/:action", repo.UpdateMilestone) | m.Get("/:index/:action", repo.UpdateMilestone) | ||||
| }) | |||||
| }, reqRepoAdmin) | |||||
| m.Post("/comment/:action", repo.Comment) | m.Post("/comment/:action", repo.Comment) | ||||
| @@ -439,7 +439,7 @@ func runWeb(ctx *cli.Context) { | |||||
| m.Post("/new", bindIgnErr(auth.NewReleaseForm{}), repo.NewReleasePost) | m.Post("/new", bindIgnErr(auth.NewReleaseForm{}), repo.NewReleasePost) | ||||
| m.Get("/edit/:tagname", repo.EditRelease) | m.Get("/edit/:tagname", repo.EditRelease) | ||||
| m.Post("/edit/:tagname", bindIgnErr(auth.EditReleaseForm{}), repo.EditReleasePost) | m.Post("/edit/:tagname", bindIgnErr(auth.EditReleaseForm{}), repo.EditReleasePost) | ||||
| }, middleware.RepoRef()) | |||||
| }, reqRepoAdmin, middleware.RepoRef()) | |||||
| }, reqSignIn, middleware.RepoAssignment(true)) | }, reqSignIn, middleware.RepoAssignment(true)) | ||||
| m.Group("/:username/:reponame", func() { | m.Group("/:username/:reponame", func() { | ||||
| @@ -392,6 +392,14 @@ issues.label_deletion = Label Deletion | |||||
| issues.label_deletion_desc = Delete label will remove its information in all related issues. Do you want to continue? | issues.label_deletion_desc = Delete label will remove its information in all related issues. Do you want to continue? | ||||
| issues.label_deletion_success = Label has been deleted successfully! | issues.label_deletion_success = Label has been deleted successfully! | ||||
| milestones.new = New Milestone | |||||
| milestones.open_tab = %d Open | |||||
| milestones.close_tab = %d Closed | |||||
| milestones.closed = Closed %s | |||||
| milestones.no_due_date = No due date | |||||
| milestones.open = Open | |||||
| milestones.close = Close | |||||
| settings = Settings | settings = Settings | ||||
| settings.options = Options | settings.options = Options | ||||
| settings.collaboration = Collaboration | settings.collaboration = Collaboration | ||||
| @@ -17,7 +17,7 @@ import ( | |||||
| "github.com/gogits/gogs/modules/setting" | "github.com/gogits/gogs/modules/setting" | ||||
| ) | ) | ||||
| const APP_VER = "0.6.3.0802 Beta" | |||||
| const APP_VER = "0.6.3.0803 Beta" | |||||
| func init() { | func init() { | ||||
| runtime.GOMAXPROCS(runtime.NumCPU()) | runtime.GOMAXPROCS(runtime.NumCPU()) | ||||
| @@ -626,7 +626,7 @@ func DeleteLabel(repoID, labelID int64) error { | |||||
| // Milestone represents a milestone of repository. | // Milestone represents a milestone of repository. | ||||
| type Milestone struct { | type Milestone struct { | ||||
| Id int64 | |||||
| ID int64 `xorm:"pk autoincr"` | |||||
| RepoId int64 `xorm:"INDEX"` | RepoId int64 `xorm:"INDEX"` | ||||
| Index int64 | Index int64 | ||||
| Name string | Name string | ||||
| @@ -670,7 +670,7 @@ func NewMilestone(m *Milestone) (err error) { | |||||
| // GetMilestoneById returns the milestone by given ID. | // GetMilestoneById returns the milestone by given ID. | ||||
| func GetMilestoneById(id int64) (*Milestone, error) { | func GetMilestoneById(id int64) (*Milestone, error) { | ||||
| m := &Milestone{Id: id} | |||||
| m := &Milestone{ID: id} | |||||
| has, err := x.Get(m) | has, err := x.Get(m) | ||||
| if err != nil { | if err != nil { | ||||
| return nil, err | return nil, err | ||||
| @@ -692,16 +692,15 @@ func GetMilestoneByIndex(repoId, idx int64) (*Milestone, error) { | |||||
| return m, nil | return m, nil | ||||
| } | } | ||||
| // GetMilestones returns a list of milestones of given repository and status. | |||||
| func GetMilestones(repoId int64, isClosed bool) ([]*Milestone, error) { | |||||
| // Milestones returns a list of milestones of given repository and status. | |||||
| func Milestones(repoID int64, isClosed bool) ([]*Milestone, error) { | |||||
| miles := make([]*Milestone, 0, 10) | miles := make([]*Milestone, 0, 10) | ||||
| err := x.Where("repo_id=?", repoId).And("is_closed=?", isClosed).Find(&miles) | |||||
| return miles, err | |||||
| return miles, x.Where("repo_id=? AND is_closed=?", repoID, isClosed).Find(&miles) | |||||
| } | } | ||||
| // UpdateMilestone updates information of given milestone. | // UpdateMilestone updates information of given milestone. | ||||
| func UpdateMilestone(m *Milestone) error { | func UpdateMilestone(m *Milestone) error { | ||||
| _, err := x.Id(m.Id).Update(m) | |||||
| _, err := x.Id(m.ID).AllCols().Update(m) | |||||
| return err | return err | ||||
| } | } | ||||
| @@ -719,7 +718,7 @@ func ChangeMilestoneStatus(m *Milestone, isClosed bool) (err error) { | |||||
| } | } | ||||
| m.IsClosed = isClosed | m.IsClosed = isClosed | ||||
| if _, err = sess.Id(m.Id).AllCols().Update(m); err != nil { | |||||
| if _, err = sess.Id(m.ID).AllCols().Update(m); err != nil { | |||||
| sess.Rollback() | sess.Rollback() | ||||
| return err | return err | ||||
| } | } | ||||
| @@ -786,7 +785,7 @@ func ChangeMilestoneAssign(oldMid, mid int64, issue *Issue) (err error) { | |||||
| m.Completeness = 0 | m.Completeness = 0 | ||||
| } | } | ||||
| if _, err = sess.Id(m.Id).Cols("num_issues,num_completeness,num_closed_issues").Update(m); err != nil { | |||||
| if _, err = sess.Id(m.ID).Cols("num_issues,num_completeness,num_closed_issues").Update(m); err != nil { | |||||
| sess.Rollback() | sess.Rollback() | ||||
| return err | return err | ||||
| } | } | ||||
| @@ -814,13 +813,13 @@ func ChangeMilestoneAssign(oldMid, mid int64, issue *Issue) (err error) { | |||||
| } | } | ||||
| m.Completeness = m.NumClosedIssues * 100 / m.NumIssues | m.Completeness = m.NumClosedIssues * 100 / m.NumIssues | ||||
| if _, err = sess.Id(m.Id).Cols("num_issues,num_completeness,num_closed_issues").Update(m); err != nil { | |||||
| if _, err = sess.Id(m.ID).Cols("num_issues,num_completeness,num_closed_issues").Update(m); err != nil { | |||||
| sess.Rollback() | sess.Rollback() | ||||
| return err | return err | ||||
| } | } | ||||
| rawSql := "UPDATE `issue_user` SET milestone_id = ? WHERE issue_id = ?" | rawSql := "UPDATE `issue_user` SET milestone_id = ? WHERE issue_id = ?" | ||||
| if _, err = sess.Exec(rawSql, m.Id, issue.ID); err != nil { | |||||
| if _, err = sess.Exec(rawSql, m.ID, issue.ID); err != nil { | |||||
| sess.Rollback() | sess.Rollback() | ||||
| return err | return err | ||||
| } | } | ||||
| @@ -849,19 +848,26 @@ func DeleteMilestone(m *Milestone) (err error) { | |||||
| } | } | ||||
| rawSql = "UPDATE `issue` SET milestone_id = 0 WHERE milestone_id = ?" | rawSql = "UPDATE `issue` SET milestone_id = 0 WHERE milestone_id = ?" | ||||
| if _, err = sess.Exec(rawSql, m.Id); err != nil { | |||||
| if _, err = sess.Exec(rawSql, m.ID); err != nil { | |||||
| sess.Rollback() | sess.Rollback() | ||||
| return err | return err | ||||
| } | } | ||||
| rawSql = "UPDATE `issue_user` SET milestone_id = 0 WHERE milestone_id = ?" | rawSql = "UPDATE `issue_user` SET milestone_id = 0 WHERE milestone_id = ?" | ||||
| if _, err = sess.Exec(rawSql, m.Id); err != nil { | |||||
| if _, err = sess.Exec(rawSql, m.ID); err != nil { | |||||
| sess.Rollback() | sess.Rollback() | ||||
| return err | return err | ||||
| } | } | ||||
| return sess.Commit() | return sess.Commit() | ||||
| } | } | ||||
| // MilestoneStats returns stats of open and closed milestone count of given repository. | |||||
| func MilestoneStats(repoID int64) (open int64, closed int64) { | |||||
| open, _ = x.Where("repo_id=? AND is_closed=?", repoID, false).Count(new(Milestone)) | |||||
| closed, _ = x.Where("repo_id=? AND is_closed=?", repoID, true).Count(new(Milestone)) | |||||
| return open, closed | |||||
| } | |||||
| // _________ __ | // _________ __ | ||||
| // \_ ___ \ ____ _____ _____ ____ _____/ |_ | // \_ ___ \ ____ _____ _____ ____ _____/ |_ | ||||
| // / \ \/ / _ \ / \ / \_/ __ \ / \ __\ | // / \ \/ / _ \ / \ / \_/ __ \ / \ __\ | ||||
| @@ -348,7 +348,7 @@ func RepoAssignment(redirect bool, args ...bool) macaron.Handler { | |||||
| } | } | ||||
| } | } | ||||
| func RequireAdmin() macaron.Handler { | |||||
| func RequireRepoAdmin() macaron.Handler { | |||||
| return func(ctx *Context) { | return func(ctx *Context) { | ||||
| if ctx.Repo.AccessMode < models.ACCESS_MODE_ADMIN { | if ctx.Repo.AccessMode < models.ACCESS_MODE_ADMIN { | ||||
| if !ctx.IsSigned { | if !ctx.IsSigned { | ||||
| @@ -93,6 +93,9 @@ $(document).ready(function () { | |||||
| }); | }); | ||||
| $('.ui.accordion').accordion(); | $('.ui.accordion').accordion(); | ||||
| $('.ui.checkbox').checkbox(); | $('.ui.checkbox').checkbox(); | ||||
| $('.ui.progress').progress({ | |||||
| showActivity: false | |||||
| }); | |||||
| $('.poping.up').popup(); | $('.poping.up').popup(); | ||||
| initInstall(); | initInstall(); | ||||
| @@ -97,11 +97,10 @@ | |||||
| right: 0!important; | right: 0!important; | ||||
| left: auto!important; | left: auto!important; | ||||
| } | } | ||||
| .issue.list { | .issue.list { | ||||
| clear: both; | clear: both; | ||||
| list-style: none; | list-style: none; | ||||
| font-size: 13px; | |||||
| padding-top: 15px; | |||||
| >.item { | >.item { | ||||
| padding-top: 15px; | padding-top: 15px; | ||||
| padding-bottom: 10px; | padding-bottom: 10px; | ||||
| @@ -128,9 +127,10 @@ | |||||
| padding-top: 15px; | padding-top: 15px; | ||||
| } | } | ||||
| } | } | ||||
| .label.list { | .label.list { | ||||
| clear: both; | clear: both; | ||||
| padding-top: 15px; | |||||
| list-style: none; | |||||
| .item { | .item { | ||||
| padding-top: 10px; | padding-top: 10px; | ||||
| padding-bottom: 10px; | padding-bottom: 10px; | ||||
| @@ -149,6 +149,55 @@ | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| .milestone.list { | |||||
| clear: both; | |||||
| list-style: none; | |||||
| .item { | |||||
| padding-top: 10px; | |||||
| padding-bottom: 10px; | |||||
| border-bottom: 1px dashed #AAA; | |||||
| > a { | |||||
| padding-top: 5px; | |||||
| padding-right: 10px; | |||||
| color: #000; | |||||
| &:hover { | |||||
| color: #4078c0; | |||||
| } | |||||
| } | |||||
| .ui.progress { | |||||
| width: 40%; | |||||
| padding: 0; | |||||
| border: 0; | |||||
| margin: 0; | |||||
| .bar { | |||||
| height: 20px; | |||||
| } | |||||
| } | |||||
| .meta { | |||||
| color: #999; | |||||
| padding-top: 5px; | |||||
| .issue-stats .octicon{ | |||||
| padding-left: 5px; | |||||
| } | |||||
| } | |||||
| .operate { | |||||
| margin-top: -15px; | |||||
| > a { | |||||
| font-size: 15px; | |||||
| padding-top: 5px; | |||||
| padding-right: 10px; | |||||
| color: #666; | |||||
| &:hover { | |||||
| color: #000; | |||||
| } | |||||
| } | |||||
| } | |||||
| .content { | |||||
| padding-top: 10px; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | } | ||||
| .edit-label.modal { | .edit-label.modal { | ||||
| @@ -159,10 +159,8 @@ func Issues(ctx *middleware.Context) { | |||||
| ctx.Data["IsShowClosed"] = isShowClosed | ctx.Data["IsShowClosed"] = isShowClosed | ||||
| if isShowClosed { | if isShowClosed { | ||||
| ctx.Data["State"] = "closed" | ctx.Data["State"] = "closed" | ||||
| ctx.Data["ShowCount"] = issueStats.ClosedCount | |||||
| } else { | } else { | ||||
| ctx.Data["State"] = "open" | ctx.Data["State"] = "open" | ||||
| ctx.Data["ShowCount"] = issueStats.OpenCount | |||||
| } | } | ||||
| ctx.HTML(200, ISSUES) | ctx.HTML(200, ISSUES) | ||||
| @@ -176,12 +174,12 @@ func CreateIssue(ctx *middleware.Context) { | |||||
| var err error | var err error | ||||
| // Get all milestones. | // Get all milestones. | ||||
| ctx.Data["OpenMilestones"], err = models.GetMilestones(ctx.Repo.Repository.Id, false) | |||||
| ctx.Data["OpenMilestones"], err = models.Milestones(ctx.Repo.Repository.Id, false) | |||||
| if err != nil { | if err != nil { | ||||
| ctx.Handle(500, "issue.ViewIssue(GetMilestones.1): %v", err) | ctx.Handle(500, "issue.ViewIssue(GetMilestones.1): %v", err) | ||||
| return | return | ||||
| } | } | ||||
| ctx.Data["ClosedMilestones"], err = models.GetMilestones(ctx.Repo.Repository.Id, true) | |||||
| ctx.Data["ClosedMilestones"], err = models.Milestones(ctx.Repo.Repository.Id, true) | |||||
| if err != nil { | if err != nil { | ||||
| ctx.Handle(500, "issue.ViewIssue(GetMilestones.2): %v", err) | ctx.Handle(500, "issue.ViewIssue(GetMilestones.2): %v", err) | ||||
| return | return | ||||
| @@ -220,12 +218,12 @@ func CreateIssuePost(ctx *middleware.Context, form auth.CreateIssueForm) { | |||||
| var err error | var err error | ||||
| // Get all milestones. | // Get all milestones. | ||||
| _, err = models.GetMilestones(ctx.Repo.Repository.Id, false) | |||||
| _, err = models.Milestones(ctx.Repo.Repository.Id, false) | |||||
| if err != nil { | if err != nil { | ||||
| send(500, nil, err) | send(500, nil, err) | ||||
| return | return | ||||
| } | } | ||||
| _, err = models.GetMilestones(ctx.Repo.Repository.Id, true) | |||||
| _, err = models.Milestones(ctx.Repo.Repository.Id, true) | |||||
| if err != nil { | if err != nil { | ||||
| send(500, nil, err) | send(500, nil, err) | ||||
| return | return | ||||
| @@ -385,12 +383,12 @@ func ViewIssue(ctx *middleware.Context) { | |||||
| } | } | ||||
| // Get all milestones. | // Get all milestones. | ||||
| ctx.Data["OpenMilestones"], err = models.GetMilestones(ctx.Repo.Repository.Id, false) | |||||
| ctx.Data["OpenMilestones"], err = models.Milestones(ctx.Repo.Repository.Id, false) | |||||
| if err != nil { | if err != nil { | ||||
| ctx.Handle(500, "issue.ViewIssue(GetMilestones.1): %v", err) | ctx.Handle(500, "issue.ViewIssue(GetMilestones.1): %v", err) | ||||
| return | return | ||||
| } | } | ||||
| ctx.Data["ClosedMilestones"], err = models.GetMilestones(ctx.Repo.Repository.Id, true) | |||||
| ctx.Data["ClosedMilestones"], err = models.Milestones(ctx.Repo.Repository.Id, true) | |||||
| if err != nil { | if err != nil { | ||||
| ctx.Handle(500, "issue.ViewIssue(GetMilestones.2): %v", err) | ctx.Handle(500, "issue.ViewIssue(GetMilestones.2): %v", err) | ||||
| return | return | ||||
| @@ -967,13 +965,12 @@ func DeleteLabel(ctx *middleware.Context) { | |||||
| } | } | ||||
| func Milestones(ctx *middleware.Context) { | func Milestones(ctx *middleware.Context) { | ||||
| ctx.Data["Title"] = "Milestones" | |||||
| ctx.Data["IsRepoToolbarIssues"] = true | |||||
| ctx.Data["IsRepoToolbarIssuesList"] = true | |||||
| ctx.Data["Title"] = ctx.Tr("repo.milestones") | |||||
| ctx.Data["PageIsMilestones"] = true | |||||
| isShowClosed := ctx.Query("state") == "closed" | isShowClosed := ctx.Query("state") == "closed" | ||||
| miles, err := models.GetMilestones(ctx.Repo.Repository.Id, isShowClosed) | |||||
| miles, err := models.Milestones(ctx.Repo.Repository.Id, isShowClosed) | |||||
| if err != nil { | if err != nil { | ||||
| ctx.Handle(500, "GetMilestones", err) | ctx.Handle(500, "GetMilestones", err) | ||||
| return | return | ||||
| @@ -984,11 +981,17 @@ func Milestones(ctx *middleware.Context) { | |||||
| } | } | ||||
| ctx.Data["Milestones"] = miles | ctx.Data["Milestones"] = miles | ||||
| openCount, closedCount := models.MilestoneStats(ctx.Repo.Repository.Id) | |||||
| ctx.Data["OpenCount"] = openCount | |||||
| ctx.Data["ClosedCount"] = closedCount | |||||
| if isShowClosed { | if isShowClosed { | ||||
| ctx.Data["State"] = "closed" | ctx.Data["State"] = "closed" | ||||
| } else { | } else { | ||||
| ctx.Data["State"] = "open" | ctx.Data["State"] = "open" | ||||
| } | } | ||||
| ctx.Data["IsShowClosed"] = isShowClosed | |||||
| ctx.HTML(200, MILESTONE) | ctx.HTML(200, MILESTONE) | ||||
| } | } | ||||
| @@ -1 +1 @@ | |||||
| 0.6.3.0802 Beta | |||||
| 0.6.3.0803 Beta | |||||
| @@ -32,17 +32,19 @@ | |||||
| <div class="ui black label">{{.i18n.Tr "repo.issues.label_count" .NumLabels}}</div> | <div class="ui black label">{{.i18n.Tr "repo.issues.label_count" .NumLabels}}</div> | ||||
| </div> | </div> | ||||
| <div class="label list"> | |||||
| {{range .Labels}} | |||||
| <li class="item"> | |||||
| <div class="ui label" style="background-color: {{.Color}}"><i class="octicon octicon-tag"></i> {{.Name}}</div> | |||||
| {{if $.IsRepositoryAdmin}} | |||||
| <a class="ui right delete-label-button" href="#" data-url="{{$.RepoLink}}/labels/delete" data-id="{{.ID}}"><i class="octicon octicon-x"></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> | |||||
| <div class="sixteen wide column"> | |||||
| <div class="label list"> | |||||
| {{range .Labels}} | |||||
| <li class="item"> | |||||
| <div class="ui label" style="background-color: {{.Color}}"><i class="octicon octicon-tag"></i> {{.Name}}</div> | |||||
| {{if $.IsRepositoryAdmin}} | |||||
| <a class="ui right delete-label-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> | |||||
| </li> | |||||
| {{end}} | {{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> | |||||
| </li> | |||||
| {{end}} | |||||
| </div> | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| @@ -70,43 +70,45 @@ | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| <div class="issue list"> | |||||
| {{range .Issues}} | |||||
| {{ $timeStr:= TimeSince .Created $.Lang }} | |||||
| <li class="item"> | |||||
| <div class="ui {{if .IsRead}}black{{else}}green{{end}} label">#{{.Index}}</div> | |||||
| <a class="title" href="{{$.RepoLink}}/issues/{{.Index}}">{{.Name}}</a> | |||||
| <div class="sixteen wide column"> | |||||
| <div class="issue list"> | |||||
| {{range .Issues}} | |||||
| {{ $timeStr:= TimeSince .Created $.Lang }} | |||||
| <li class="item"> | |||||
| <div class="ui {{if .IsRead}}black{{else}}green{{end}} label">#{{.Index}}</div> | |||||
| <a class="title" href="{{$.RepoLink}}/issues/{{.Index}}">{{.Name}}</a> | |||||
| {{range .Labels}} | |||||
| <a class="ui label" href="{{$.RepoLink}}/issues?type={{$.ViewType}}&state={{$.State}}&labels={{.ID}}" style="background-color: {{.Color}}">{{.Name}}</a> | |||||
| {{end}} | |||||
| {{range .Labels}} | |||||
| <a class="ui label" href="{{$.RepoLink}}/issues?type={{$.ViewType}}&state={{$.State}}&labels={{.ID}}" style="background-color: {{.Color}}">{{.Name}}</a> | |||||
| {{end}} | |||||
| {{if .NumComments}}<span class="comment ui right"><i class="octicon octicon-comment"></i> {{.NumComments}}</span>{{end}} | |||||
| <p class="desc">{{$.i18n.Tr "repo.issues.opened_by" $timeStr .Poster.Name|Str2html}}</p> | |||||
| </li> | |||||
| {{end}} | |||||
| {{with .Page}} | |||||
| {{if gt .Total 1}} | |||||
| <div class="center page buttons"> | |||||
| <div class="ui borderless pagination menu"> | |||||
| <a class="{{if not .HasPrevious}}disabled{{end}} item" {{if .HasPrevious}}href="{{$.RepoLink}}/issues?type={{$.ViewType}}&state={{$.State}}&labels={{$.SelectLabels}}&page={{.Previous}}"{{end}}> | |||||
| <i class="left arrow icon"></i> {{$.i18n.Tr "repo.issues.previous"}} | |||||
| </a> | |||||
| {{range .Pages}} | |||||
| {{if eq .Num -1}} | |||||
| <a class="disabled item">...</a> | |||||
| {{else}} | |||||
| <a class="{{if .IsCurrent}}active{{end}} item" {{if not .IsCurrent}}href="{{$.RepoLink}}/issues?type={{$.ViewType}}&state={{$.State}}&labels={{$.SelectLabels}}&page={{.Num}}"{{end}}>{{.Num}}</a> | |||||
| {{end}} | |||||
| {{end}} | |||||
| <a class="{{if not .HasNext}}disabled{{end}} item" {{if .HasNext}}href="{{$.RepoLink}}/issues?type={{$.ViewType}}&state={{$.State}}&labels={{$.SelectLabels}}&page={{.Next}}"{{end}}> | |||||
| {{$.i18n.Tr "repo.issues.next"}} <i class="icon right arrow"></i> | |||||
| </a> | |||||
| {{if .NumComments}}<span class="comment ui right"><i class="octicon octicon-comment"></i> {{.NumComments}}</span>{{end}} | |||||
| <p class="desc">{{$.i18n.Tr "repo.issues.opened_by" $timeStr .Poster.Name|Str2html}}</p> | |||||
| </li> | |||||
| {{end}} | |||||
| {{with .Page}} | |||||
| {{if gt .Total 1}} | |||||
| <div class="center page buttons"> | |||||
| <div class="ui borderless pagination menu"> | |||||
| <a class="{{if not .HasPrevious}}disabled{{end}} item" {{if .HasPrevious}}href="{{$.RepoLink}}/issues?type={{$.ViewType}}&state={{$.State}}&labels={{$.SelectLabels}}&page={{.Previous}}"{{end}}> | |||||
| <i class="left arrow icon"></i> {{$.i18n.Tr "repo.issues.previous"}} | |||||
| </a> | |||||
| {{range .Pages}} | |||||
| {{if eq .Num -1}} | |||||
| <a class="disabled item">...</a> | |||||
| {{else}} | |||||
| <a class="{{if .IsCurrent}}active{{end}} item" {{if not .IsCurrent}}href="{{$.RepoLink}}/issues?type={{$.ViewType}}&state={{$.State}}&labels={{$.SelectLabels}}&page={{.Num}}"{{end}}>{{.Num}}</a> | |||||
| {{end}} | |||||
| {{end}} | |||||
| <a class="{{if not .HasNext}}disabled{{end}} item" {{if .HasNext}}href="{{$.RepoLink}}/issues?type={{$.ViewType}}&state={{$.State}}&labels={{$.SelectLabels}}&page={{.Next}}"{{end}}> | |||||
| {{$.i18n.Tr "repo.issues.next"}} <i class="icon right arrow"></i> | |||||
| </a> | |||||
| </div> | |||||
| </div> | </div> | ||||
| {{end}} | |||||
| {{end}} | |||||
| </div> | </div> | ||||
| {{end}} | |||||
| {{end}} | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| @@ -1,43 +1,70 @@ | |||||
| {{template "base/head_old" .}} | |||||
| {{template "base/navbar" .}} | |||||
| {{template "repo/nav" .}} | |||||
| {{template "repo/toolbar" .}} | |||||
| <div id="body" class="container"> | |||||
| <div id="issue"> | |||||
| <div class="col-md-3 filter-list"> | |||||
| <ul class="list-unstyled"> | |||||
| <li><a href="{{.RepoLink}}/milestones"{{if eq .State "open"}} class="active"{{end}}>Open Milestones <strong class="pull-right">{{.Repository.NumOpenMilestones}}</strong></a></li> | |||||
| <li><a href="{{.RepoLink}}/milestones?state=closed"{{if eq .State "closed"}} class="active"{{end}}>Close Milestones <strong class="pull-right">{{.Repository.NumClosedMilestones}}</strong></a></li> | |||||
| </ul> | |||||
| <hr/> | |||||
| <a href="{{.RepoLink}}/milestones/new" class="text-center"> | |||||
| <button class="btn btn-default btn-block">Create new milestone</button> | |||||
| </a> | |||||
| </div> | |||||
| <div class="col-md-9"> | |||||
| <div class="milestones list-group"> | |||||
| {{range .Milestones}} | |||||
| <div class="list-group-item milestone-item"> | |||||
| <h4 class="title pull-left"><a href="{{$.RepoLink}}/issues?milestone={{.Index}}{{if .IsClosed}}&state=closed{{end}}">{{.Name}}</a></h4> | |||||
| <span class="issue-open label label-success">{{.NumOpenIssues}}</span> | |||||
| <span class="issue-close label label-warning">{{.NumClosedIssues}}</span> | |||||
| <p class="actions pull-right"> | |||||
| <a href="{{$.RepoLink}}/milestones/{{.Index}}/edit">Edit</a> | |||||
| {{if .IsClosed}} | |||||
| <a href="{{$.RepoLink}}/milestones/{{.Index}}/open">Open</a> | |||||
| {{else}} | |||||
| <a href="{{$.RepoLink}}/milestones/{{.Index}}/close">Close</a> | |||||
| {{end}} | |||||
| <a class="text-danger" href="{{$.RepoLink}}/milestones/{{.Index}}/delete">Delete</a> | |||||
| <a href="{{$.RepoLink}}/issues?milestone={{.Index}}{{if .IsClosed}}&state=closed{{end}}">Issues</a> | |||||
| </p> | |||||
| <hr/> | |||||
| <p class="description">{{.RenderedContent | Str2html}}</p> | |||||
| </div> | |||||
| {{end}} | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| {{template "base/head" .}} | |||||
| <div class="repository"> | |||||
| {{template "repo/header" .}} | |||||
| <div class="ui middle page grid body"> | |||||
| <div class="navbar"> | |||||
| {{template "repo/issue/navbar" .}} | |||||
| <div class="ui right floated secondary menu"> | |||||
| <a class="ui green button" href="{{$.RepoLink}}/milestones/new">{{.i18n.Tr "repo.milestones.new"}}</a> | |||||
| </div> | |||||
| </div> | |||||
| <div class="ui divider"></div> | |||||
| <div class="ui left"> | |||||
| <div class="ui tiny buttons"> | |||||
| <a class="ui green basic button {{if not .IsShowClosed}}active{{end}}" href="{{.RepoLink}}/milestones?state=open"> | |||||
| <i class="octicon octicon-milestone"></i> | |||||
| {{.i18n.Tr "repo.milestones.open_tab" .OpenCount}} | |||||
| </a> | |||||
| <a class="ui red basic button {{if .IsShowClosed}}active{{end}}" href="{{.RepoLink}}/milestones?state=closed"> | |||||
| <i class="octicon octicon-milestone"></i> | |||||
| {{.i18n.Tr "repo.milestones.close_tab" .ClosedCount}} | |||||
| </a> | |||||
| </div> | |||||
| </div> | |||||
| <div class="sixteen wide column"> | |||||
| <div class="milestone list"> | |||||
| {{range .Milestones}} | |||||
| <li class="item"> | |||||
| <i class="octicon octicon-milestone"></i> <a href="{{$.RepoLink}}/issues?state={{$.State}}&midx={{.Index}}">{{.Name}}</a> | |||||
| <div class="ui right blue progress" data-percent="{{if .Completeness}}{{.Completeness}}{{else}}100{{end}}"> | |||||
| <div class="bar"> | |||||
| <div class="progress"></div> | |||||
| </div> | |||||
| </div> | |||||
| <div class="meta"> | |||||
| {{ $closedDate:= TimeSince .ClosedDate $.Lang }} | |||||
| {{if .IsClosed}} | |||||
| <span class="octicon octicon-clock"></span> {{$.i18n.Tr "repo.milestones.closed" $closedDate|Str2html}} | |||||
| {{else}} | |||||
| <span class="octicon octicon-calendar"></span> {{if .DeadlineString}}{{.DeadlineString}}{{else}}{{$.i18n.Tr "repo.milestones.no_due_date"}}{{end}} | |||||
| {{end}} | |||||
| <span class="issue-stats"> | |||||
| <i class="octicon octicon-issue-opened"></i> {{$.i18n.Tr "repo.issues.open_tab" .NumOpenIssues}} | |||||
| <i class="octicon octicon-issue-closed"></i> {{$.i18n.Tr "repo.issues.close_tab" .NumClosedIssues}} | |||||
| </span> | |||||
| </div> | |||||
| {{if $.IsRepositoryAdmin}} | |||||
| <div class="ui right operate"> | |||||
| <a href="{{$.RepoLink}}/milestones/{{.Index}}/edit" data-id={{.ID}} data-title={{.Name}}><i class="octicon octicon-pencil"></i> {{$.i18n.Tr "repo.issues.label_edit"}}</a> | |||||
| {{if .IsClosed}} | |||||
| <a href="{{$.RepoLink}}/milestones/{{.Index}}/open" data-id={{.ID}} data-title={{.Name}}><i class="octicon octicon-check"></i> {{$.i18n.Tr "repo.milestones.open"}}</a> | |||||
| {{else}} | |||||
| <a href="{{$.RepoLink}}/milestones/{{.Index}}/close" data-id={{.ID}} data-title={{.Name}}><i class="octicon octicon-x"></i> {{$.i18n.Tr "repo.milestones.close"}}</a> | |||||
| {{end}} | |||||
| <a class="delete-milestone-button" href="#" data-url="{{$.RepoLink}}/milestone/delete" data-id="{{.ID}}"><i class="octicon octicon-trashcan"></i> {{$.i18n.Tr "repo.issues.label_delete"}}</a> | |||||
| </div> | |||||
| {{if .Content}} | |||||
| <div class="content"> | |||||
| {{.RenderedContent|Str2html}} | |||||
| </div> | |||||
| {{end}} | |||||
| {{end}} | |||||
| </li> | |||||
| {{end}} | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| </div> | </div> | ||||
| </div> | |||||
| {{template "base/footer_old" .}} | |||||
| {{template "base/footer" .}} | |||||
| @@ -0,0 +1,43 @@ | |||||
| {{template "base/head_old" .}} | |||||
| {{template "base/navbar" .}} | |||||
| {{template "repo/nav" .}} | |||||
| {{template "repo/toolbar" .}} | |||||
| <div id="body" class="container"> | |||||
| <div id="issue"> | |||||
| <div class="col-md-3 filter-list"> | |||||
| <ul class="list-unstyled"> | |||||
| <li><a href="{{.RepoLink}}/milestones"{{if eq .State "open"}} class="active"{{end}}>Open Milestones <strong class="pull-right">{{.Repository.NumOpenMilestones}}</strong></a></li> | |||||
| <li><a href="{{.RepoLink}}/milestones?state=closed"{{if eq .State "closed"}} class="active"{{end}}>Close Milestones <strong class="pull-right">{{.Repository.NumClosedMilestones}}</strong></a></li> | |||||
| </ul> | |||||
| <hr/> | |||||
| <a href="{{.RepoLink}}/milestones/new" class="text-center"> | |||||
| <button class="btn btn-default btn-block">Create new milestone</button> | |||||
| </a> | |||||
| </div> | |||||
| <div class="col-md-9"> | |||||
| <div class="milestones list-group"> | |||||
| {{range .Milestones}} | |||||
| <div class="list-group-item milestone-item"> | |||||
| <h4 class="title pull-left"><a href="{{$.RepoLink}}/issues?milestone={{.Index}}{{if .IsClosed}}&state=closed{{end}}">{{.Name}}</a></h4> | |||||
| <span class="issue-open label label-success">{{.NumOpenIssues}}</span> | |||||
| <span class="issue-close label label-warning">{{.NumClosedIssues}}</span> | |||||
| <p class="actions pull-right"> | |||||
| <a href="{{$.RepoLink}}/milestones/{{.Index}}/edit">Edit</a> | |||||
| {{if .IsClosed}} | |||||
| <a href="{{$.RepoLink}}/milestones/{{.Index}}/open">Open</a> | |||||
| {{else}} | |||||
| <a href="{{$.RepoLink}}/milestones/{{.Index}}/close">Close</a> | |||||
| {{end}} | |||||
| <a class="text-danger" href="{{$.RepoLink}}/milestones/{{.Index}}/delete">Delete</a> | |||||
| <a href="{{$.RepoLink}}/issues?milestone={{.Index}}{{if .IsClosed}}&state=closed{{end}}">Issues</a> | |||||
| </p> | |||||
| <hr/> | |||||
| <p class="description">{{.RenderedContent | Str2html}}</p> | |||||
| </div> | |||||
| {{end}} | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| {{template "base/footer_old" .}} | |||||
| @@ -2,6 +2,6 @@ | |||||
| <div class="ui compact menu"> | <div class="ui compact menu"> | ||||
| <a class="{{if .PageIsIssueList}}active{{end}} item" href="{{.RepoLink}}/issues">{{.i18n.Tr "repo.issues"}}</a> | <a class="{{if .PageIsIssueList}}active{{end}} item" href="{{.RepoLink}}/issues">{{.i18n.Tr "repo.issues"}}</a> | ||||
| <a class="{{if .PageIsLabels}}active{{end}} item" href="{{.RepoLink}}/labels">{{.i18n.Tr "repo.labels"}}</a> | <a class="{{if .PageIsLabels}}active{{end}} item" href="{{.RepoLink}}/labels">{{.i18n.Tr "repo.labels"}}</a> | ||||
| <a class="item" href="{{.RepoLink}}/milestones">{{.i18n.Tr "repo.milestones"}}</a> | |||||
| <a class="{{if .PageIsMilestones}}active{{end}} item" href="{{.RepoLink}}/milestones">{{.i18n.Tr "repo.milestones"}}</a> | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||