milestone: pagination

release/v0.9
Unknwon 9 years ago
parent e7f015db8c
commit 9311a9858a

@ -427,9 +427,9 @@ func runWeb(ctx *cli.Context) {
m.Group("/milestones", func() {
m.Get("/new", repo.NewMilestone)
m.Post("/new", bindIgnErr(auth.CreateMilestoneForm{}), repo.NewMilestonePost)
m.Get("/:index/edit", repo.UpdateMilestone)
m.Get("/:index/edit", repo.MilestoneActions)
m.Post("/:index/edit", bindIgnErr(auth.CreateMilestoneForm{}), repo.UpdateMilestonePost)
m.Get("/:index/:action", repo.UpdateMilestone)
m.Get("/:index/:action", repo.MilestoneActions)
}, reqRepoAdmin)
m.Post("/comment/:action", repo.Comment)
@ -452,7 +452,6 @@ func runWeb(ctx *cli.Context) {
m.Get("/branches", repo.Branches)
m.Get("/archive/*", repo.Download)
m.Get("/pulls2/", repo.PullRequest2)
m.Get("/milestone2/", repo.Milestones2)
m.Head("/hooks/trigger", repo.TriggerHook)
m.Group("", func() {

@ -17,7 +17,7 @@ import (
"github.com/gogits/gogs/modules/setting"
)
const APP_VER = "0.6.3.0803 Beta"
const APP_VER = "0.6.3.0804 Beta"
func init() {
runtime.GOMAXPROCS(runtime.NumCPU())

@ -14,6 +14,7 @@ import (
"time"
"github.com/Unknwon/com"
"github.com/go-xorm/xorm"
"github.com/gogits/gogs/modules/log"
"github.com/gogits/gogs/modules/setting"
@ -184,8 +185,8 @@ func GetIssueById(id int64) (*Issue, error) {
return issue, nil
}
// GetIssues returns a list of issues by given conditions.
func GetIssues(uid, assigneeID, repoID, posterID, milestoneID int64, page int, isClosed, isMention bool, labelIds, sortType string) ([]Issue, error) {
// Issues returns a list of issues by given conditions.
func Issues(uid, assigneeID, repoID, posterID, milestoneID int64, page int, isClosed, isMention bool, labelIds, sortType string) ([]*Issue, error) {
sess := x.Limit(setting.IssuePagingNum, (page-1)*setting.IssuePagingNum)
if repoID > 0 {
@ -237,7 +238,7 @@ func GetIssues(uid, assigneeID, repoID, posterID, milestoneID int64, page int, i
sess.Join("INNER", "issue_user", queryStr)
}
var issues []Issue
issues := make([]*Issue, 0, setting.IssuePagingNum)
return issues, sess.Find(&issues)
}
@ -627,7 +628,7 @@ func DeleteLabel(repoID, labelID int64) error {
// Milestone represents a milestone of repository.
type Milestone struct {
ID int64 `xorm:"pk autoincr"`
RepoId int64 `xorm:"INDEX"`
RepoID int64 `xorm:"INDEX"`
Index int64
Name string
Content string `xorm:"TEXT"`
@ -642,6 +643,17 @@ type Milestone struct {
ClosedDate time.Time
}
func (m *Milestone) BeforeSet(colName string, val xorm.Cell) {
if colName == "deadline" {
t := (*val).(time.Time)
if t.Year() == 9999 {
return
}
m.DeadlineString = t.Format("2006-01-02")
}
}
// CalOpenIssues calculates the open issues of milestone.
func (m *Milestone) CalOpenIssues() {
m.NumOpenIssues = m.NumIssues - m.NumClosedIssues
@ -661,15 +673,15 @@ func NewMilestone(m *Milestone) (err error) {
}
rawSql := "UPDATE `repository` SET num_milestones = num_milestones + 1 WHERE id = ?"
if _, err = sess.Exec(rawSql, m.RepoId); err != nil {
if _, err = sess.Exec(rawSql, m.RepoID); err != nil {
sess.Rollback()
return err
}
return sess.Commit()
}
// GetMilestoneById returns the milestone by given ID.
func GetMilestoneById(id int64) (*Milestone, error) {
// MilestoneById returns the milestone by given ID.
func MilestoneById(id int64) (*Milestone, error) {
m := &Milestone{ID: id}
has, err := x.Get(m)
if err != nil {
@ -682,7 +694,7 @@ func GetMilestoneById(id int64) (*Milestone, error) {
// GetMilestoneByIndex returns the milestone of given repository and index.
func GetMilestoneByIndex(repoId, idx int64) (*Milestone, error) {
m := &Milestone{RepoId: repoId, Index: idx}
m := &Milestone{RepoID: repoId, Index: idx}
has, err := x.Get(m)
if err != nil {
return nil, err
@ -693,9 +705,14 @@ func GetMilestoneByIndex(repoId, idx int64) (*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)
return miles, x.Where("repo_id=? AND is_closed=?", repoID, isClosed).Find(&miles)
func Milestones(repoID int64, page int, isClosed bool) ([]*Milestone, error) {
miles := make([]*Milestone, 0, setting.IssuePagingNum)
sess := x.Where("repo_id=? AND is_closed=?", repoID, isClosed)
if page > 0 {
sess = sess.Limit(setting.IssuePagingNum, (page-1)*setting.IssuePagingNum)
}
return miles, sess.Find(&miles)
}
// UpdateMilestone updates information of given milestone.
@ -704,46 +721,51 @@ func UpdateMilestone(m *Milestone) error {
return err
}
// CountClosedMilestones returns number of closed milestones in given repository.
func CountClosedMilestones(repoID int64) int64 {
closed, _ := x.Where("repo_id=? AND is_closed=?", repoID, true).Count(new(Milestone))
return closed
}
// MilestoneStats returns number of open and closed milestones of given repository.
func MilestoneStats(repoID int64) (open int64, closed int64) {
open, _ = x.Where("repo_id=? AND is_closed=?", repoID, false).Count(new(Milestone))
return open, CountClosedMilestones(repoID)
}
// ChangeMilestoneStatus changes the milestone open/closed status.
func ChangeMilestoneStatus(m *Milestone, isClosed bool) (err error) {
repo, err := GetRepositoryById(m.RepoId)
repo, err := GetRepositoryById(m.RepoID)
if err != nil {
return err
}
sess := x.NewSession()
defer sess.Close()
defer sessionRelease(sess)
if err = sess.Begin(); err != nil {
return err
}
m.IsClosed = isClosed
if _, err = sess.Id(m.ID).AllCols().Update(m); err != nil {
sess.Rollback()
if err = UpdateMilestone(m); err != nil {
return err
}
if isClosed {
repo.NumClosedMilestones++
} else {
repo.NumClosedMilestones--
}
if _, err = sess.Id(repo.Id).Update(repo); err != nil {
sess.Rollback()
repo.NumClosedMilestones = int(CountClosedMilestones(repo.Id))
if _, err = sess.Id(repo.Id).AllCols().Update(repo); err != nil {
return err
}
return sess.Commit()
}
// ChangeMilestoneIssueStats updates the open/closed issues counter and progress for the
// milestone associated witht the given issue.
// ChangeMilestoneIssueStats updates the open/closed issues counter and progress
// for the milestone associated witht the given issue.
func ChangeMilestoneIssueStats(issue *Issue) error {
if issue.MilestoneId == 0 {
return nil
}
m, err := GetMilestoneById(issue.MilestoneId)
m, err := MilestoneById(issue.MilestoneId)
if err != nil {
return err
}
@ -770,7 +792,7 @@ func ChangeMilestoneAssign(oldMid, mid int64, issue *Issue) (err error) {
}
if oldMid > 0 {
m, err := GetMilestoneById(oldMid)
m, err := MilestoneById(oldMid)
if err != nil {
return err
}
@ -798,7 +820,7 @@ func ChangeMilestoneAssign(oldMid, mid int64, issue *Issue) (err error) {
}
if mid > 0 {
m, err := GetMilestoneById(mid)
m, err := MilestoneById(mid)
if err != nil {
return err
}
@ -842,7 +864,7 @@ func DeleteMilestone(m *Milestone) (err error) {
}
rawSql := "UPDATE `repository` SET num_milestones = num_milestones - 1 WHERE id = ?"
if _, err = sess.Exec(rawSql, m.RepoId); err != nil {
if _, err = sess.Exec(rawSql, m.RepoID); err != nil {
sess.Rollback()
return err
}
@ -861,13 +883,6 @@ func DeleteMilestone(m *Milestone) (err error) {
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
}
// _________ __
// \_ ___ \ ____ _____ _____ ____ _____/ |_
// / \ \/ / _ \ / \ / \_/ __ \ / \ __\

@ -867,7 +867,7 @@ func DeleteRepository(uid, repoID int64, userName string) error {
return err
} else if _, err = sess.Delete(&IssueUser{RepoId: repoID}); err != nil {
return err
} else if _, err = sess.Delete(&Milestone{RepoId: repoID}); err != nil {
} else if _, err = sess.Delete(&Milestone{RepoID: repoID}); err != nil {
return err
} else if _, err = sess.Delete(&Release{RepoId: repoID}); err != nil {
return err

File diff suppressed because one or more lines are too long

@ -98,6 +98,9 @@
left: auto!important;
}
.page.buttons {
padding-top: 15px;
}
.issue.list {
clear: both;
list-style: none;
@ -123,9 +126,6 @@
color: #999;
}
}
.page.buttons {
padding-top: 15px;
}
}
.label.list {
@ -153,7 +153,7 @@
.milestone.list {
clear: both;
list-style: none;
.item {
> .item {
padding-top: 10px;
padding-bottom: 10px;
border-bottom: 1px dashed #AAA;

@ -66,8 +66,6 @@ func Issues(ctx *middleware.Context) {
viewType = "all"
}
isShowClosed := ctx.Query("state") == "closed"
// Must sign in to see issues about you.
if viewType != "all" && !ctx.IsSigned {
ctx.SetCookie("redirect_to", "/"+url.QueryEscape(setting.AppSubUrl+ctx.Req.RequestURI), 0, setting.AppSubUrl)
@ -96,6 +94,7 @@ func Issues(ctx *middleware.Context) {
repo := ctx.Repo.Repository
selectLabels := ctx.Query("labels")
milestoneID := ctx.QueryInt64("milestone")
isShowClosed := ctx.Query("state") == "closed"
issueStats := models.GetIssueStats(repo.Id, uid, com.StrTo(selectLabels).MustInt64(), isShowClosed, filterMode)
page := ctx.QueryInt("page")
@ -112,7 +111,7 @@ func Issues(ctx *middleware.Context) {
ctx.Data["Page"] = paginater.New(total, setting.IssuePagingNum, page, 5)
// Get issues.
issues, err := models.GetIssues(uid, assigneeID, repo.Id, posterID, milestoneID,
issues, err := models.Issues(uid, assigneeID, repo.Id, posterID, milestoneID,
page, isShowClosed, filterMode == models.FM_MENTION, selectLabels, ctx.Query("sortType"))
if err != nil {
ctx.Handle(500, "GetIssues: %v", err)
@ -172,22 +171,25 @@ func CreateIssue(ctx *middleware.Context) {
ctx.Data["IsRepoToolbarIssuesList"] = false
ctx.Data["AttachmentsEnabled"] = setting.AttachmentEnabled
var err error
var (
repo = ctx.Repo.Repository
err error
)
// Get all milestones.
ctx.Data["OpenMilestones"], err = models.Milestones(ctx.Repo.Repository.Id, false)
ctx.Data["OpenMilestones"], err = models.Milestones(repo.Id, -1, false)
if err != nil {
ctx.Handle(500, "issue.ViewIssue(GetMilestones.1): %v", err)
ctx.Handle(500, "GetMilestones.1: %v", err)
return
}
ctx.Data["ClosedMilestones"], err = models.Milestones(ctx.Repo.Repository.Id, true)
ctx.Data["ClosedMilestones"], err = models.Milestones(repo.Id, -1, true)
if err != nil {
ctx.Handle(500, "issue.ViewIssue(GetMilestones.2): %v", err)
ctx.Handle(500, "GetMilestones.2: %v", err)
return
}
us, err := ctx.Repo.Repository.GetCollaborators()
us, err := repo.GetCollaborators()
if err != nil {
ctx.Handle(500, "issue.CreateIssue(GetCollaborators)", err)
ctx.Handle(500, "GetCollaborators", err)
return
}
@ -218,12 +220,12 @@ func CreateIssuePost(ctx *middleware.Context, form auth.CreateIssueForm) {
var err error
// Get all milestones.
_, err = models.Milestones(ctx.Repo.Repository.Id, false)
_, err = models.Milestones(ctx.Repo.Repository.Id, -1, false)
if err != nil {
send(500, nil, err)
return
}
_, err = models.Milestones(ctx.Repo.Repository.Id, true)
_, err = models.Milestones(ctx.Repo.Repository.Id, -1, true)
if err != nil {
send(500, nil, err)
return
@ -371,7 +373,7 @@ func ViewIssue(ctx *middleware.Context) {
// Get assigned milestone.
if issue.MilestoneId > 0 {
ctx.Data["Milestone"], err = models.GetMilestoneById(issue.MilestoneId)
ctx.Data["Milestone"], err = models.MilestoneById(issue.MilestoneId)
if err != nil {
if err == models.ErrMilestoneNotExist {
log.Warn("issue.ViewIssue(GetMilestoneById): %v", err)
@ -383,12 +385,12 @@ func ViewIssue(ctx *middleware.Context) {
}
// Get all milestones.
ctx.Data["OpenMilestones"], err = models.Milestones(ctx.Repo.Repository.Id, false)
ctx.Data["OpenMilestones"], err = models.Milestones(ctx.Repo.Repository.Id, -1, false)
if err != nil {
ctx.Handle(500, "issue.ViewIssue(GetMilestones.1): %v", err)
return
}
ctx.Data["ClosedMilestones"], err = models.Milestones(ctx.Repo.Repository.Id, true)
ctx.Data["ClosedMilestones"], err = models.Milestones(ctx.Repo.Repository.Id, -1, true)
if err != nil {
ctx.Handle(500, "issue.ViewIssue(GetMilestones.2): %v", err)
return
@ -969,8 +971,24 @@ func Milestones(ctx *middleware.Context) {
ctx.Data["PageIsMilestones"] = true
isShowClosed := ctx.Query("state") == "closed"
openCount, closedCount := models.MilestoneStats(ctx.Repo.Repository.Id)
ctx.Data["OpenCount"] = openCount
ctx.Data["ClosedCount"] = closedCount
page := ctx.QueryInt("page")
if page <= 1 {
page = 1
}
var total int
if !isShowClosed {
total = int(openCount)
} else {
total = int(closedCount)
}
ctx.Data["Page"] = paginater.New(total, setting.IssuePagingNum, page, 5)
miles, err := models.Milestones(ctx.Repo.Repository.Id, isShowClosed)
miles, err := models.Milestones(ctx.Repo.Repository.Id, page, isShowClosed)
if err != nil {
ctx.Handle(500, "GetMilestones", err)
return
@ -981,10 +999,6 @@ func Milestones(ctx *middleware.Context) {
}
ctx.Data["Milestones"] = miles
openCount, closedCount := models.MilestoneStats(ctx.Repo.Repository.Id)
ctx.Data["OpenCount"] = openCount
ctx.Data["ClosedCount"] = closedCount
if isShowClosed {
ctx.Data["State"] = "closed"
} else {
@ -1024,7 +1038,7 @@ func NewMilestonePost(ctx *middleware.Context, form auth.CreateMilestoneForm) {
}
mile := &models.Milestone{
RepoId: ctx.Repo.Repository.Id,
RepoID: ctx.Repo.Repository.Id,
Index: int64(ctx.Repo.Repository.NumMilestones) + 1,
Name: form.Title,
Content: form.Content,
@ -1038,14 +1052,17 @@ func NewMilestonePost(ctx *middleware.Context, form auth.CreateMilestoneForm) {
ctx.Redirect(ctx.Repo.RepoLink + "/milestones")
}
func UpdateMilestone(ctx *middleware.Context) {
func EditMilestone(ctx *middleware.Context) {}
func EditMilestonePost(ctx *middleware.Context) {}
func MilestoneActions(ctx *middleware.Context) {
ctx.Data["Title"] = "Update Milestone"
ctx.Data["IsRepoToolbarIssues"] = true
ctx.Data["IsRepoToolbarIssuesList"] = true
idx := ctx.ParamsInt64(":index")
if idx == 0 {
ctx.Handle(404, "issue.UpdateMilestone", nil)
ctx.Handle(404, "get milestone index", nil)
return
}
@ -1165,7 +1182,3 @@ func IssueGetAttachment(ctx *middleware.Context) {
func PullRequest2(ctx *middleware.Context) {
ctx.HTML(200, "repo/pr2/list")
}
func Milestones2(ctx *middleware.Context) {
ctx.HTML(200, "repo/milestone2/list")
}

@ -1 +1 @@
0.6.3.0803 Beta
0.6.3.0804 Beta

@ -54,7 +54,7 @@
{{else}}
<ul class="list-unstyled">
{{range .OpenMilestones}}
<li class="milestone-item" data-id="{{.Id}}">
<li class="milestone-item" data-id="{{.ID}}">
<p><strong>{{.Name}}</strong></p>
<!-- <p>due to 3 days later</p> -->
</li>

@ -88,20 +88,20 @@
{{end}}
{{with .Page}}
{{if gt .Total 1}}
{{if gt .TotalPages 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}}>
<a class="{{if not .HasPrevious}}disabled{{end}} item" {{if .HasPrevious}}href="{{$.Link}}?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>
<a class="{{if .IsCurrent}}active{{end}} item" {{if not .IsCurrent}}href="{{$.Link}}?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}}>
<a class="{{if not .HasNext}}disabled{{end}} item" {{if .HasNext}}href="{{$.Link}}?type={{$.ViewType}}&state={{$.State}}&labels={{$.SelectLabels}}&page={{.Next}}"{{end}}>
{{$.i18n.Tr "repo.issues.next"}} <i class="icon right arrow"></i>
</a>
</div>

@ -28,8 +28,8 @@
{{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="ui right blue progress" data-percent="{{.Completeness}}">
<div class="bar" {{if not .Completeness}}style="background-color: transparent"{{end}}>
<div class="progress"></div>
</div>
</div>
@ -63,6 +63,28 @@
{{end}}
</li>
{{end}}
{{with .Page}}
{{if gt .TotalPages 1}}
<div class="center page buttons">
<div class="ui borderless pagination menu">
<a class="{{if not .HasPrevious}}disabled{{end}} item" {{if .HasPrevious}}href="{{$.Link}}?state={{$.State}}&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="{{$.Link}}?state={{$.State}}&page={{.Num}}"{{end}}>{{.Num}}</a>
{{end}}
{{end}}
<a class="{{if not .HasNext}}disabled{{end}} item" {{if .HasNext}}href="{{$.Link}}?state={{$.State}}&page={{.Next}}"{{end}}>
{{$.i18n.Tr "repo.issues.next"}} <i class="icon right arrow"></i>
</a>
</div>
</div>
{{end}}
{{end}}
</div>
</div>
</div>

@ -1,58 +0,0 @@
{{template "ng/base/head" .}}
{{template "ng/base/header" .}}
<div id="repo-wrapper">
{{template "repo/header_old" .}}
<div class="issue-main container repo-wide-wrapper">
<ul id="issue-list-nav" class="menu menu-line">
<li><a href="#">Issue</a></li>
<li><a href="#">Pull Request</a></li>
<li><a href="#">Labels</a></li>
<li class="current"><a href="#">Milestones</a></li>
<li class="right" id="milestone-new"><a href="#"><button id="issue-new-btn" class="btn btn-green text-bold">New Milestone</button></a></li>
</ul>
<div id="issue-list-container">
<div id="issue-list-menu">
<div class="left">
<span class="mark open hover"><a href="#">
<i class="octicon octicon-milestone"></i> 88 Open
</a></span>
<span class="mark close"><a href="">
<i class="octicon octicon-issue-closed"></i> 12 Close
</a></span>
</div>
<div class="clear"></div>
</div>
<ul id="milestone-list" class="list-no-style">
<li class="item" id="milestone-id">
<!--<a class="comment" href="#">
<i class="octicon octicon-comment"></i> 7
</a>-->
<p class="title text-bold">
<i class="octicon octicon-milestone"></i>
<a href="#" class="title-text">Delete account text</a>
</p>
<p class="desc">
<i class="octicon octicon-clock"></i> Updated 3 days ago &nbsp;&nbsp;
<i class="octicon octicon-calendar"></i> Due to Dec 31,2014
</p>
<div class="content">
In this version of release, users are able to register and log in/out on Gogs, setting up SSH keys and do most of Git operations through SSH with public repositories. And Web UI only for view of Git data, no extra features are supported.
</div>
<div class="action">
<p class="status-bar">
<span class="closed">closed 12</span>
<span class="inline-block bar"><span class="inline-block opening"></span></span>
<span class="open">12 open</span>
</p>
<div class="action-bar text-right">
<a href="#">Edit</a>
<a href="#">Delete</a>
<a href="#" class="text-red">Close</a>
</div>
</div>
</li>
</ul>
</div>
</div>
</div>
{{template "ng/base/footer" .}}
Loading…
Cancel
Save