Skip to content

Commit 1a97030

Browse files
kolaentelafriks
authored andcommitted
Issue due date (#3794)
* Started adding deadline to ui * Implemented basic issue due date managing * Improved UI for due date managing * Added at least write access to the repo in order to modify issue due dates * Ui improvements * Added issue comments creation when adding/modifying/removing a due date * Show due date in issue list * Added api support for issue due dates * Fixed lint suggestions * Added deadline to sdk * Updated css * Added support for adding/modifiying deadlines for pull requests via api * Fixed comments not created when updating or removing a deadline * update sdk (will do properly once go-gitea/go-sdk#103 is merged) * enhanced updateIssueDeadline * Removed unnessecary Issue.DeadlineString * UI improvements * Small improvments to comment creation + ui & validation improvements * Check if an issue is overdue is now a seperate function * Updated go-sdk with govendor as it was merged * Simplified isOverdue method * removed unessecary deadline to 0 set * Update swagger definitions * Added missing return * Added an explanary comment * Improved updateIssueDeadline method so it'll only update `deadline_unix` * Small changes and improvements * no need to explicitly load the issue when updating a deadline, just use whats already there * small optimisations * Added check if a deadline was modified before updating it * Moved comment creating logic into its own function * Code cleanup for creating deadline comment * locale improvement * When modifying a deadline, the old deadline is saved with the comment * small improvments to xorm session handling when updating an issue deadline + style nitpicks * style nitpicks * Moved checking for if the user has write acces to middleware
1 parent 85d14cc commit 1a97030

File tree

22 files changed

+416
-45
lines changed

22 files changed

+416
-45
lines changed

models/issue.go

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,10 @@ type Issue struct {
4747
Ref string
4848

4949
DeadlineUnix util.TimeStamp `xorm:"INDEX"`
50-
CreatedUnix util.TimeStamp `xorm:"INDEX created"`
51-
UpdatedUnix util.TimeStamp `xorm:"INDEX updated"`
52-
ClosedUnix util.TimeStamp `xorm:"INDEX"`
50+
51+
CreatedUnix util.TimeStamp `xorm:"INDEX created"`
52+
UpdatedUnix util.TimeStamp `xorm:"INDEX updated"`
53+
ClosedUnix util.TimeStamp `xorm:"INDEX"`
5354

5455
Attachments []*Attachment `xorm:"-"`
5556
Comments []*Comment `xorm:"-"`
@@ -79,6 +80,11 @@ func (issue *Issue) loadTotalTimes(e Engine) (err error) {
7980
return nil
8081
}
8182

83+
// IsOverdue checks if the issue is overdue
84+
func (issue *Issue) IsOverdue() bool {
85+
return util.TimeStampNow() >= issue.DeadlineUnix
86+
}
87+
8288
func (issue *Issue) loadRepo(e Engine) (err error) {
8389
if issue.Repo == nil {
8490
issue.Repo, err = getRepositoryByID(e, issue.RepoID)
@@ -348,6 +354,9 @@ func (issue *Issue) APIFormat() *api.Issue {
348354
apiIssue.PullRequest.Merged = issue.PullRequest.MergedUnix.AsTimePtr()
349355
}
350356
}
357+
if issue.DeadlineUnix != 0 {
358+
apiIssue.Deadline = issue.DeadlineUnix.AsTimePtr()
359+
}
351360

352361
return apiIssue
353362
}
@@ -1522,3 +1531,30 @@ func updateIssue(e Engine, issue *Issue) error {
15221531
func UpdateIssue(issue *Issue) error {
15231532
return updateIssue(x, issue)
15241533
}
1534+
1535+
// UpdateIssueDeadline updates an issue deadline and adds comments. Setting a deadline to 0 means deleting it.
1536+
func UpdateIssueDeadline(issue *Issue, deadlineUnix util.TimeStamp, doer *User) (err error) {
1537+
1538+
// if the deadline hasn't changed do nothing
1539+
if issue.DeadlineUnix == deadlineUnix {
1540+
return nil
1541+
}
1542+
1543+
sess := x.NewSession()
1544+
defer sess.Close()
1545+
if err := sess.Begin(); err != nil {
1546+
return err
1547+
}
1548+
1549+
// Update the deadline
1550+
if err = updateIssueCols(sess, &Issue{ID: issue.ID, DeadlineUnix: deadlineUnix}, "deadline_unix"); err != nil {
1551+
return err
1552+
}
1553+
1554+
// Make the comment
1555+
if _, err = createDeadlineComment(sess, doer, issue, deadlineUnix); err != nil {
1556+
return fmt.Errorf("createRemovedDueDateComment: %v", err)
1557+
}
1558+
1559+
return sess.Commit()
1560+
}

models/issue_comment.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,12 @@ const (
6060
CommentTypeAddTimeManual
6161
// Cancel a stopwatch for time tracking
6262
CommentTypeCancelTracking
63+
// Added a due date
64+
CommentTypeAddedDeadline
65+
// Modified the due date
66+
CommentTypeModifiedDeadline
67+
// Removed a due date
68+
CommentTypeRemovedDeadline
6369
)
6470

6571
// CommentTag defines comment tag type
@@ -485,6 +491,34 @@ func createAssigneeComment(e *xorm.Session, doer *User, repo *Repository, issue
485491
})
486492
}
487493

494+
func createDeadlineComment(e *xorm.Session, doer *User, issue *Issue, newDeadlineUnix util.TimeStamp) (*Comment, error) {
495+
496+
var content string
497+
var commentType CommentType
498+
499+
// newDeadline = 0 means deleting
500+
if newDeadlineUnix == 0 {
501+
commentType = CommentTypeRemovedDeadline
502+
content = issue.DeadlineUnix.Format("2006-01-02")
503+
} else if issue.DeadlineUnix == 0 {
504+
// Check if the new date was added or modified
505+
// If the actual deadline is 0 => deadline added
506+
commentType = CommentTypeAddedDeadline
507+
content = newDeadlineUnix.Format("2006-01-02")
508+
} else { // Otherwise modified
509+
commentType = CommentTypeModifiedDeadline
510+
content = newDeadlineUnix.Format("2006-01-02") + "|" + issue.DeadlineUnix.Format("2006-01-02")
511+
}
512+
513+
return createComment(e, &CreateCommentOptions{
514+
Type: commentType,
515+
Doer: doer,
516+
Repo: issue.Repo,
517+
Issue: issue,
518+
Content: content,
519+
})
520+
}
521+
488522
func createChangeTitleComment(e *xorm.Session, doer *User, repo *Repository, issue *Issue, oldTitle, newTitle string) (*Comment, error) {
489523
return createComment(e, &CreateCommentOptions{
490524
Type: CommentTypeChangeTitle,

models/pull.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,7 @@ func (pr *PullRequest) APIFormat() *api.PullRequest {
207207
Base: apiBaseBranchInfo,
208208
Head: apiHeadBranchInfo,
209209
MergeBase: pr.MergeBase,
210+
Deadline: apiIssue.Deadline,
210211
Created: pr.Issue.CreatedUnix.AsTimePtr(),
211212
Updated: pr.Issue.UpdatedUnix.AsTimePtr(),
212213
}

modules/auth/repo_form.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -521,3 +521,13 @@ func (f *AddTimeManuallyForm) Validate(ctx *macaron.Context, errs binding.Errors
521521
type SaveTopicForm struct {
522522
Topics []string `binding:"topics;Required;"`
523523
}
524+
525+
// DeadlineForm hold the validation rules for deadlines
526+
type DeadlineForm struct {
527+
DateString string `form:"date" binding:"Required;Size(10)"`
528+
}
529+
530+
// Validate validates the fields
531+
func (f *DeadlineForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
532+
return validate(errs, ctx.Data, f, ctx.Locale)
533+
}

modules/templates/helper.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,9 @@ func NewFuncMap() []template.FuncMap {
183183
"Printf": fmt.Sprintf,
184184
"Escape": Escape,
185185
"Sec2Time": models.SecToTime,
186+
"ParseDeadline": func(deadline string) []string {
187+
return strings.Split(deadline, "|")
188+
},
186189
}}
187190
}
188191

options/locale/locale_en-US.ini

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -736,8 +736,22 @@ issues.add_time_minutes = Minutes
736736
issues.add_time_sum_to_small = No time was entered.
737737
issues.cancel_tracking = Cancel
738738
issues.cancel_tracking_history = `cancelled time tracking %s`
739+
issues.time_spent_total = Total Time Spent
739740
issues.time_spent_from_all_authors = `Total Time Spent: %s`
740-
741+
issues.due_date = Due date
742+
issues.invalid_due_date_format = "Due date format is invalid, must be 'yyyy-mm-dd'."
743+
issues.error_modifying_due_date = "An error occured while modifying the due date."
744+
issues.error_removing_due_date = "An error occured while remvoing the due date."
745+
issues.due_date_form = "Due date, format yyyy-mm-dd"
746+
issues.due_date_form_add = "Add due date"
747+
issues.due_date_form_update = "Update due date"
748+
issues.due_date_form_remove = "Remove due date"
749+
issues.due_date_not_writer = "You need to have at least write access to this repository in order to update the due date for this issue."
750+
issues.due_date_not_set = "No due date set."
751+
issues.due_date_added = "added the due date %s %s"
752+
issues.due_date_modified = "modified the due date to %s from %s %s"
753+
issues.due_date_remove = "removed the due date %s %s"
754+
issues.due_date_overdue = "Overdue"
741755
742756
pulls.desc = Enable merge requests and code reviews.
743757
pulls.new = New Pull Request

public/css/index.css

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

public/js/index.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2193,4 +2193,15 @@ function initTopicbar() {
21932193
},
21942194
},
21952195
});
2196-
}
2196+
}
2197+
function toggleDuedateForm() {
2198+
$('#add_deadline_form').fadeToggle(150);
2199+
}
2200+
2201+
function deleteDueDate(url) {
2202+
$.post(url, {
2203+
'_csrf': csrf,
2204+
},function( data ) {
2205+
window.location.reload();
2206+
});
2207+
}

public/less/_repository.less

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1545,6 +1545,9 @@
15451545
margin-top: -5px;
15461546
margin-right: 5px;
15471547
}
1548+
.overdue{
1549+
color: red;
1550+
}
15481551
}
15491552
}
15501553
}

public/swagger.v1.json

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5579,6 +5579,13 @@
55795579
"type": "string",
55805580
"x-go-name": "Assignee"
55815581
},
5582+
"assignees": {
5583+
"type": "array",
5584+
"items": {
5585+
"type": "string"
5586+
},
5587+
"x-go-name": "Assignees"
5588+
},
55825589
"body": {
55835590
"type": "string",
55845591
"x-go-name": "Body"
@@ -5587,6 +5594,11 @@
55875594
"type": "boolean",
55885595
"x-go-name": "Closed"
55895596
},
5597+
"due_date": {
5598+
"type": "string",
5599+
"format": "date-time",
5600+
"x-go-name": "Deadline"
5601+
},
55905602
"labels": {
55915603
"description": "list of label ids",
55925604
"type": "array",
@@ -5715,6 +5727,13 @@
57155727
"type": "string",
57165728
"x-go-name": "Assignee"
57175729
},
5730+
"assignees": {
5731+
"type": "array",
5732+
"items": {
5733+
"type": "string"
5734+
},
5735+
"x-go-name": "Assignees"
5736+
},
57185737
"base": {
57195738
"type": "string",
57205739
"x-go-name": "Base"
@@ -5723,6 +5742,11 @@
57235742
"type": "string",
57245743
"x-go-name": "Body"
57255744
},
5745+
"due_date": {
5746+
"type": "string",
5747+
"format": "date-time",
5748+
"x-go-name": "Deadline"
5749+
},
57265750
"head": {
57275751
"type": "string",
57285752
"x-go-name": "Head"
@@ -6024,10 +6048,22 @@
60246048
"type": "string",
60256049
"x-go-name": "Assignee"
60266050
},
6051+
"assignees": {
6052+
"type": "array",
6053+
"items": {
6054+
"type": "string"
6055+
},
6056+
"x-go-name": "Assignees"
6057+
},
60276058
"body": {
60286059
"type": "string",
60296060
"x-go-name": "Body"
60306061
},
6062+
"due_date": {
6063+
"type": "string",
6064+
"format": "date-time",
6065+
"x-go-name": "Deadline"
6066+
},
60316067
"milestone": {
60326068
"type": "integer",
60336069
"format": "int64",
@@ -6114,10 +6150,22 @@
61146150
"type": "string",
61156151
"x-go-name": "Assignee"
61166152
},
6153+
"assignees": {
6154+
"type": "array",
6155+
"items": {
6156+
"type": "string"
6157+
},
6158+
"x-go-name": "Assignees"
6159+
},
61176160
"body": {
61186161
"type": "string",
61196162
"x-go-name": "Body"
61206163
},
6164+
"due_date": {
6165+
"type": "string",
6166+
"format": "date-time",
6167+
"x-go-name": "Deadline"
6168+
},
61216169
"labels": {
61226170
"type": "array",
61236171
"items": {
@@ -6367,10 +6415,22 @@
63676415
"assignee": {
63686416
"$ref": "#/definitions/User"
63696417
},
6418+
"assignees": {
6419+
"type": "array",
6420+
"items": {
6421+
"$ref": "#/definitions/User"
6422+
},
6423+
"x-go-name": "Assignees"
6424+
},
63706425
"body": {
63716426
"type": "string",
63726427
"x-go-name": "Body"
63736428
},
6429+
"closed_at": {
6430+
"type": "string",
6431+
"format": "date-time",
6432+
"x-go-name": "Closed"
6433+
},
63746434
"comments": {
63756435
"type": "integer",
63766436
"format": "int64",
@@ -6381,6 +6441,11 @@
63816441
"format": "date-time",
63826442
"x-go-name": "Created"
63836443
},
6444+
"due_date": {
6445+
"type": "string",
6446+
"format": "date-time",
6447+
"x-go-name": "Deadline"
6448+
},
63846449
"id": {
63856450
"type": "integer",
63866451
"format": "int64",
@@ -6778,13 +6843,25 @@
67786843
"assignee": {
67796844
"$ref": "#/definitions/User"
67806845
},
6846+
"assignees": {
6847+
"type": "array",
6848+
"items": {
6849+
"$ref": "#/definitions/User"
6850+
},
6851+
"x-go-name": "Assignees"
6852+
},
67816853
"base": {
67826854
"$ref": "#/definitions/PRBranchInfo"
67836855
},
67846856
"body": {
67856857
"type": "string",
67866858
"x-go-name": "Body"
67876859
},
6860+
"closed_at": {
6861+
"type": "string",
6862+
"format": "date-time",
6863+
"x-go-name": "Closed"
6864+
},
67886865
"comments": {
67896866
"type": "integer",
67906867
"format": "int64",
@@ -6799,6 +6876,11 @@
67996876
"type": "string",
68006877
"x-go-name": "DiffURL"
68016878
},
6879+
"due_date": {
6880+
"type": "string",
6881+
"format": "date-time",
6882+
"x-go-name": "Deadline"
6883+
},
68026884
"head": {
68036885
"$ref": "#/definitions/PRBranchInfo"
68046886
},

0 commit comments

Comments
 (0)