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
This commit is contained in:
Родитель
85d14cc229
Коммит
1a97030017
|
@ -47,9 +47,10 @@ type Issue struct {
|
|||
Ref string
|
||||
|
||||
DeadlineUnix util.TimeStamp `xorm:"INDEX"`
|
||||
CreatedUnix util.TimeStamp `xorm:"INDEX created"`
|
||||
UpdatedUnix util.TimeStamp `xorm:"INDEX updated"`
|
||||
ClosedUnix util.TimeStamp `xorm:"INDEX"`
|
||||
|
||||
CreatedUnix util.TimeStamp `xorm:"INDEX created"`
|
||||
UpdatedUnix util.TimeStamp `xorm:"INDEX updated"`
|
||||
ClosedUnix util.TimeStamp `xorm:"INDEX"`
|
||||
|
||||
Attachments []*Attachment `xorm:"-"`
|
||||
Comments []*Comment `xorm:"-"`
|
||||
|
@ -79,6 +80,11 @@ func (issue *Issue) loadTotalTimes(e Engine) (err error) {
|
|||
return nil
|
||||
}
|
||||
|
||||
// IsOverdue checks if the issue is overdue
|
||||
func (issue *Issue) IsOverdue() bool {
|
||||
return util.TimeStampNow() >= issue.DeadlineUnix
|
||||
}
|
||||
|
||||
func (issue *Issue) loadRepo(e Engine) (err error) {
|
||||
if issue.Repo == nil {
|
||||
issue.Repo, err = getRepositoryByID(e, issue.RepoID)
|
||||
|
@ -348,6 +354,9 @@ func (issue *Issue) APIFormat() *api.Issue {
|
|||
apiIssue.PullRequest.Merged = issue.PullRequest.MergedUnix.AsTimePtr()
|
||||
}
|
||||
}
|
||||
if issue.DeadlineUnix != 0 {
|
||||
apiIssue.Deadline = issue.DeadlineUnix.AsTimePtr()
|
||||
}
|
||||
|
||||
return apiIssue
|
||||
}
|
||||
|
@ -1522,3 +1531,30 @@ func updateIssue(e Engine, issue *Issue) error {
|
|||
func UpdateIssue(issue *Issue) error {
|
||||
return updateIssue(x, issue)
|
||||
}
|
||||
|
||||
// UpdateIssueDeadline updates an issue deadline and adds comments. Setting a deadline to 0 means deleting it.
|
||||
func UpdateIssueDeadline(issue *Issue, deadlineUnix util.TimeStamp, doer *User) (err error) {
|
||||
|
||||
// if the deadline hasn't changed do nothing
|
||||
if issue.DeadlineUnix == deadlineUnix {
|
||||
return nil
|
||||
}
|
||||
|
||||
sess := x.NewSession()
|
||||
defer sess.Close()
|
||||
if err := sess.Begin(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Update the deadline
|
||||
if err = updateIssueCols(sess, &Issue{ID: issue.ID, DeadlineUnix: deadlineUnix}, "deadline_unix"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Make the comment
|
||||
if _, err = createDeadlineComment(sess, doer, issue, deadlineUnix); err != nil {
|
||||
return fmt.Errorf("createRemovedDueDateComment: %v", err)
|
||||
}
|
||||
|
||||
return sess.Commit()
|
||||
}
|
||||
|
|
|
@ -60,6 +60,12 @@ const (
|
|||
CommentTypeAddTimeManual
|
||||
// Cancel a stopwatch for time tracking
|
||||
CommentTypeCancelTracking
|
||||
// Added a due date
|
||||
CommentTypeAddedDeadline
|
||||
// Modified the due date
|
||||
CommentTypeModifiedDeadline
|
||||
// Removed a due date
|
||||
CommentTypeRemovedDeadline
|
||||
)
|
||||
|
||||
// CommentTag defines comment tag type
|
||||
|
@ -485,6 +491,34 @@ func createAssigneeComment(e *xorm.Session, doer *User, repo *Repository, issue
|
|||
})
|
||||
}
|
||||
|
||||
func createDeadlineComment(e *xorm.Session, doer *User, issue *Issue, newDeadlineUnix util.TimeStamp) (*Comment, error) {
|
||||
|
||||
var content string
|
||||
var commentType CommentType
|
||||
|
||||
// newDeadline = 0 means deleting
|
||||
if newDeadlineUnix == 0 {
|
||||
commentType = CommentTypeRemovedDeadline
|
||||
content = issue.DeadlineUnix.Format("2006-01-02")
|
||||
} else if issue.DeadlineUnix == 0 {
|
||||
// Check if the new date was added or modified
|
||||
// If the actual deadline is 0 => deadline added
|
||||
commentType = CommentTypeAddedDeadline
|
||||
content = newDeadlineUnix.Format("2006-01-02")
|
||||
} else { // Otherwise modified
|
||||
commentType = CommentTypeModifiedDeadline
|
||||
content = newDeadlineUnix.Format("2006-01-02") + "|" + issue.DeadlineUnix.Format("2006-01-02")
|
||||
}
|
||||
|
||||
return createComment(e, &CreateCommentOptions{
|
||||
Type: commentType,
|
||||
Doer: doer,
|
||||
Repo: issue.Repo,
|
||||
Issue: issue,
|
||||
Content: content,
|
||||
})
|
||||
}
|
||||
|
||||
func createChangeTitleComment(e *xorm.Session, doer *User, repo *Repository, issue *Issue, oldTitle, newTitle string) (*Comment, error) {
|
||||
return createComment(e, &CreateCommentOptions{
|
||||
Type: CommentTypeChangeTitle,
|
||||
|
|
|
@ -207,6 +207,7 @@ func (pr *PullRequest) APIFormat() *api.PullRequest {
|
|||
Base: apiBaseBranchInfo,
|
||||
Head: apiHeadBranchInfo,
|
||||
MergeBase: pr.MergeBase,
|
||||
Deadline: apiIssue.Deadline,
|
||||
Created: pr.Issue.CreatedUnix.AsTimePtr(),
|
||||
Updated: pr.Issue.UpdatedUnix.AsTimePtr(),
|
||||
}
|
||||
|
|
|
@ -521,3 +521,13 @@ func (f *AddTimeManuallyForm) Validate(ctx *macaron.Context, errs binding.Errors
|
|||
type SaveTopicForm struct {
|
||||
Topics []string `binding:"topics;Required;"`
|
||||
}
|
||||
|
||||
// DeadlineForm hold the validation rules for deadlines
|
||||
type DeadlineForm struct {
|
||||
DateString string `form:"date" binding:"Required;Size(10)"`
|
||||
}
|
||||
|
||||
// Validate validates the fields
|
||||
func (f *DeadlineForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
|
|
@ -183,6 +183,9 @@ func NewFuncMap() []template.FuncMap {
|
|||
"Printf": fmt.Sprintf,
|
||||
"Escape": Escape,
|
||||
"Sec2Time": models.SecToTime,
|
||||
"ParseDeadline": func(deadline string) []string {
|
||||
return strings.Split(deadline, "|")
|
||||
},
|
||||
}}
|
||||
}
|
||||
|
||||
|
|
|
@ -736,8 +736,22 @@ issues.add_time_minutes = Minutes
|
|||
issues.add_time_sum_to_small = No time was entered.
|
||||
issues.cancel_tracking = Cancel
|
||||
issues.cancel_tracking_history = `cancelled time tracking %s`
|
||||
issues.time_spent_total = Total Time Spent
|
||||
issues.time_spent_from_all_authors = `Total Time Spent: %s`
|
||||
|
||||
issues.due_date = Due date
|
||||
issues.invalid_due_date_format = "Due date format is invalid, must be 'yyyy-mm-dd'."
|
||||
issues.error_modifying_due_date = "An error occured while modifying the due date."
|
||||
issues.error_removing_due_date = "An error occured while remvoing the due date."
|
||||
issues.due_date_form = "Due date, format yyyy-mm-dd"
|
||||
issues.due_date_form_add = "Add due date"
|
||||
issues.due_date_form_update = "Update due date"
|
||||
issues.due_date_form_remove = "Remove due date"
|
||||
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."
|
||||
issues.due_date_not_set = "No due date set."
|
||||
issues.due_date_added = "added the due date %s %s"
|
||||
issues.due_date_modified = "modified the due date to %s from %s %s"
|
||||
issues.due_date_remove = "removed the due date %s %s"
|
||||
issues.due_date_overdue = "Overdue"
|
||||
|
||||
pulls.desc = Enable merge requests and code reviews.
|
||||
pulls.new = New Pull Request
|
||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -2193,4 +2193,15 @@ function initTopicbar() {
|
|||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
function toggleDuedateForm() {
|
||||
$('#add_deadline_form').fadeToggle(150);
|
||||
}
|
||||
|
||||
function deleteDueDate(url) {
|
||||
$.post(url, {
|
||||
'_csrf': csrf,
|
||||
},function( data ) {
|
||||
window.location.reload();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1545,6 +1545,9 @@
|
|||
margin-top: -5px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
.overdue{
|
||||
color: red;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5579,6 +5579,13 @@
|
|||
"type": "string",
|
||||
"x-go-name": "Assignee"
|
||||
},
|
||||
"assignees": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"x-go-name": "Assignees"
|
||||
},
|
||||
"body": {
|
||||
"type": "string",
|
||||
"x-go-name": "Body"
|
||||
|
@ -5587,6 +5594,11 @@
|
|||
"type": "boolean",
|
||||
"x-go-name": "Closed"
|
||||
},
|
||||
"due_date": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"x-go-name": "Deadline"
|
||||
},
|
||||
"labels": {
|
||||
"description": "list of label ids",
|
||||
"type": "array",
|
||||
|
@ -5715,6 +5727,13 @@
|
|||
"type": "string",
|
||||
"x-go-name": "Assignee"
|
||||
},
|
||||
"assignees": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"x-go-name": "Assignees"
|
||||
},
|
||||
"base": {
|
||||
"type": "string",
|
||||
"x-go-name": "Base"
|
||||
|
@ -5723,6 +5742,11 @@
|
|||
"type": "string",
|
||||
"x-go-name": "Body"
|
||||
},
|
||||
"due_date": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"x-go-name": "Deadline"
|
||||
},
|
||||
"head": {
|
||||
"type": "string",
|
||||
"x-go-name": "Head"
|
||||
|
@ -6024,10 +6048,22 @@
|
|||
"type": "string",
|
||||
"x-go-name": "Assignee"
|
||||
},
|
||||
"assignees": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"x-go-name": "Assignees"
|
||||
},
|
||||
"body": {
|
||||
"type": "string",
|
||||
"x-go-name": "Body"
|
||||
},
|
||||
"due_date": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"x-go-name": "Deadline"
|
||||
},
|
||||
"milestone": {
|
||||
"type": "integer",
|
||||
"format": "int64",
|
||||
|
@ -6114,10 +6150,22 @@
|
|||
"type": "string",
|
||||
"x-go-name": "Assignee"
|
||||
},
|
||||
"assignees": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"x-go-name": "Assignees"
|
||||
},
|
||||
"body": {
|
||||
"type": "string",
|
||||
"x-go-name": "Body"
|
||||
},
|
||||
"due_date": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"x-go-name": "Deadline"
|
||||
},
|
||||
"labels": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
|
@ -6367,10 +6415,22 @@
|
|||
"assignee": {
|
||||
"$ref": "#/definitions/User"
|
||||
},
|
||||
"assignees": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/User"
|
||||
},
|
||||
"x-go-name": "Assignees"
|
||||
},
|
||||
"body": {
|
||||
"type": "string",
|
||||
"x-go-name": "Body"
|
||||
},
|
||||
"closed_at": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"x-go-name": "Closed"
|
||||
},
|
||||
"comments": {
|
||||
"type": "integer",
|
||||
"format": "int64",
|
||||
|
@ -6381,6 +6441,11 @@
|
|||
"format": "date-time",
|
||||
"x-go-name": "Created"
|
||||
},
|
||||
"due_date": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"x-go-name": "Deadline"
|
||||
},
|
||||
"id": {
|
||||
"type": "integer",
|
||||
"format": "int64",
|
||||
|
@ -6778,6 +6843,13 @@
|
|||
"assignee": {
|
||||
"$ref": "#/definitions/User"
|
||||
},
|
||||
"assignees": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/User"
|
||||
},
|
||||
"x-go-name": "Assignees"
|
||||
},
|
||||
"base": {
|
||||
"$ref": "#/definitions/PRBranchInfo"
|
||||
},
|
||||
|
@ -6785,6 +6857,11 @@
|
|||
"type": "string",
|
||||
"x-go-name": "Body"
|
||||
},
|
||||
"closed_at": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"x-go-name": "Closed"
|
||||
},
|
||||
"comments": {
|
||||
"type": "integer",
|
||||
"format": "int64",
|
||||
|
@ -6799,6 +6876,11 @@
|
|||
"type": "string",
|
||||
"x-go-name": "DiffURL"
|
||||
},
|
||||
"due_date": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"x-go-name": "Deadline"
|
||||
},
|
||||
"head": {
|
||||
"$ref": "#/definitions/PRBranchInfo"
|
||||
},
|
||||
|
|
|
@ -163,12 +163,19 @@ func CreateIssue(ctx *context.APIContext, form api.CreateIssueOption) {
|
|||
// responses:
|
||||
// "201":
|
||||
// "$ref": "#/responses/Issue"
|
||||
|
||||
var deadlineUnix util.TimeStamp
|
||||
if form.Deadline != nil {
|
||||
deadlineUnix = util.TimeStamp(form.Deadline.Unix())
|
||||
}
|
||||
|
||||
issue := &models.Issue{
|
||||
RepoID: ctx.Repo.Repository.ID,
|
||||
Title: form.Title,
|
||||
PosterID: ctx.User.ID,
|
||||
Poster: ctx.User,
|
||||
Content: form.Body,
|
||||
RepoID: ctx.Repo.Repository.ID,
|
||||
Title: form.Title,
|
||||
PosterID: ctx.User.ID,
|
||||
Poster: ctx.User,
|
||||
Content: form.Body,
|
||||
DeadlineUnix: deadlineUnix,
|
||||
}
|
||||
|
||||
if ctx.Repo.IsWriter() {
|
||||
|
@ -265,6 +272,16 @@ func EditIssue(ctx *context.APIContext, form api.EditIssueOption) {
|
|||
issue.Content = *form.Body
|
||||
}
|
||||
|
||||
var deadlineUnix util.TimeStamp
|
||||
if form.Deadline != nil && !form.Deadline.IsZero() {
|
||||
deadlineUnix = util.TimeStamp(form.Deadline.Unix())
|
||||
}
|
||||
|
||||
if err := models.UpdateIssueDeadline(issue, deadlineUnix, ctx.User); err != nil {
|
||||
ctx.Error(500, "UpdateIssueDeadline", err)
|
||||
return
|
||||
}
|
||||
|
||||
if ctx.Repo.IsWriter() && form.Assignee != nil &&
|
||||
(issue.Assignee == nil || issue.Assignee.LowerName != strings.ToLower(*form.Assignee)) {
|
||||
if len(*form.Assignee) == 0 {
|
||||
|
|
|
@ -13,6 +13,7 @@ import (
|
|||
"code.gitea.io/gitea/modules/auth"
|
||||
"code.gitea.io/gitea/modules/context"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
|
||||
api "code.gitea.io/sdk/gitea"
|
||||
)
|
||||
|
@ -236,16 +237,22 @@ func CreatePullRequest(ctx *context.APIContext, form api.CreatePullRequestOption
|
|||
return
|
||||
}
|
||||
|
||||
var deadlineUnix util.TimeStamp
|
||||
if form.Deadline != nil {
|
||||
deadlineUnix = util.TimeStamp(form.Deadline.Unix())
|
||||
}
|
||||
|
||||
prIssue := &models.Issue{
|
||||
RepoID: repo.ID,
|
||||
Index: repo.NextIssueIndex(),
|
||||
Title: form.Title,
|
||||
PosterID: ctx.User.ID,
|
||||
Poster: ctx.User,
|
||||
MilestoneID: milestoneID,
|
||||
AssigneeID: assigneeID,
|
||||
IsPull: true,
|
||||
Content: form.Body,
|
||||
RepoID: repo.ID,
|
||||
Index: repo.NextIssueIndex(),
|
||||
Title: form.Title,
|
||||
PosterID: ctx.User.ID,
|
||||
Poster: ctx.User,
|
||||
MilestoneID: milestoneID,
|
||||
AssigneeID: assigneeID,
|
||||
IsPull: true,
|
||||
Content: form.Body,
|
||||
DeadlineUnix: deadlineUnix,
|
||||
}
|
||||
pr := &models.PullRequest{
|
||||
HeadRepoID: headRepo.ID,
|
||||
|
@ -328,6 +335,16 @@ func EditPullRequest(ctx *context.APIContext, form api.EditPullRequestOption) {
|
|||
issue.Content = form.Body
|
||||
}
|
||||
|
||||
var deadlineUnix util.TimeStamp
|
||||
if form.Deadline != nil && !form.Deadline.IsZero() {
|
||||
deadlineUnix = util.TimeStamp(form.Deadline.Unix())
|
||||
}
|
||||
|
||||
if err := models.UpdateIssueDeadline(issue, deadlineUnix, ctx.User); err != nil {
|
||||
ctx.Error(500, "UpdateIssueDeadline", err)
|
||||
return
|
||||
}
|
||||
|
||||
if ctx.Repo.IsWriter() && len(form.Assignee) > 0 &&
|
||||
(issue.Assignee == nil || issue.Assignee.LowerName != strings.ToLower(form.Assignee)) {
|
||||
if len(form.Assignee) == 0 {
|
||||
|
|
|
@ -1467,3 +1467,51 @@ func ChangeCommentReaction(ctx *context.Context, form auth.ReactionForm) {
|
|||
"html": html,
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateDeadline adds or updates a deadline
|
||||
func UpdateDeadline(ctx *context.Context, form auth.DeadlineForm) {
|
||||
issue := GetActionIssue(ctx)
|
||||
if ctx.Written() {
|
||||
return
|
||||
}
|
||||
|
||||
if ctx.HasError() {
|
||||
ctx.ServerError("ChangeIssueDeadline", errors.New(ctx.GetErrMsg()))
|
||||
return
|
||||
}
|
||||
|
||||
// Make unix of deadline string
|
||||
deadline, err := time.ParseInLocation("2006-01-02", form.DateString, time.Local)
|
||||
if err != nil {
|
||||
ctx.Flash.Error(ctx.Tr("repo.issues.invalid_due_date_format"))
|
||||
ctx.Redirect(fmt.Sprintf("%s/issues/%d", ctx.Repo.RepoLink, issue.Index))
|
||||
return
|
||||
}
|
||||
|
||||
if err = models.UpdateIssueDeadline(issue, util.TimeStamp(deadline.Unix()), ctx.User); err != nil {
|
||||
ctx.Flash.Error(ctx.Tr("repo.issues.error_modifying_due_date"))
|
||||
}
|
||||
|
||||
ctx.Redirect(fmt.Sprintf("%s/issues/%d", ctx.Repo.RepoLink, issue.Index))
|
||||
return
|
||||
}
|
||||
|
||||
// RemoveDeadline removes a deadline
|
||||
func RemoveDeadline(ctx *context.Context) {
|
||||
issue := GetActionIssue(ctx)
|
||||
if ctx.Written() {
|
||||
return
|
||||
}
|
||||
|
||||
if ctx.HasError() {
|
||||
ctx.ServerError("RemoveIssueDeadline", errors.New(ctx.GetErrMsg()))
|
||||
return
|
||||
}
|
||||
|
||||
if err := models.UpdateIssueDeadline(issue, 0, ctx.User); err != nil {
|
||||
ctx.Flash.Error(ctx.Tr("repo.issues.error_removing_due_date"))
|
||||
}
|
||||
|
||||
ctx.Redirect(fmt.Sprintf("%s/issues/%d", ctx.Repo.RepoLink, issue.Index))
|
||||
return
|
||||
}
|
||||
|
|
|
@ -496,6 +496,8 @@ func RegisterRoutes(m *macaron.Macaron) {
|
|||
})
|
||||
})
|
||||
m.Post("/reactions/:action", bindIgnErr(auth.ReactionForm{}), repo.ChangeIssueReaction)
|
||||
m.Post("/deadline/update", reqRepoWriter, bindIgnErr(auth.DeadlineForm{}), repo.UpdateDeadline)
|
||||
m.Post("/deadline/delete", reqRepoWriter, repo.RemoveDeadline)
|
||||
})
|
||||
|
||||
m.Post("/labels", reqRepoWriter, repo.UpdateIssueLabel)
|
||||
|
|
|
@ -216,6 +216,10 @@
|
|||
<span class="octicon octicon-milestone"></span> {{.Milestone.Name}}
|
||||
</a>
|
||||
{{end}}
|
||||
{{if ne .DeadlineUnix 0}}
|
||||
<span class="octicon octicon-calendar"></span>
|
||||
<span{{if .IsOverdue}} class="overdue"{{end}}>{{.DeadlineUnix.FormatShort}}</span>
|
||||
{{end}}
|
||||
{{if .Assignee}}
|
||||
<a class="ui right assignee poping up" href="{{.Assignee.HomeLink}}" data-content="{{.Assignee.Name}}" data-variation="inverted" data-position="left center">
|
||||
<img class="ui avatar image" src="{{.Assignee.RelAvatarLink}}">
|
||||
|
|
|
@ -56,7 +56,7 @@
|
|||
{{else}}
|
||||
<span class="octicon octicon-calendar"></span>
|
||||
{{if .DeadlineString}}
|
||||
<span {{if .IsOverDue}}class="overdue"{{end}}>{{.DeadlineString}}</span>
|
||||
<span {{if .IsOverdue}}class="overdue"{{end}}>{{.DeadlineString}}</span>
|
||||
{{else}}
|
||||
{{$.i18n.Tr "repo.milestones.no_due_date"}}
|
||||
{{end}}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{{range .Issue.Comments}}
|
||||
{{ $createdStr:= TimeSinceUnix .CreatedUnix $.Lang }}
|
||||
|
||||
<!-- 0 = COMMENT, 1 = REOPEN, 2 = CLOSE, 3 = ISSUE_REF, 4 = COMMIT_REF, 5 = COMMENT_REF, 6 = PULL_REF, 7 = COMMENT_LABEL, 12 = START_TRACKING, 13 = STOP_TRACKING, 14 = ADD_TIME_MANUAL -->
|
||||
<!-- 0 = COMMENT, 1 = REOPEN, 2 = CLOSE, 3 = ISSUE_REF, 4 = COMMIT_REF, 5 = COMMENT_REF, 6 = PULL_REF, 7 = COMMENT_LABEL, 12 = START_TRACKING, 13 = STOP_TRACKING, 14 = ADD_TIME_MANUAL, 16 = ADDED_DEADLINE, 17 = MODIFIED_DEADLINE, 18 = REMOVED_DEADLINE -->
|
||||
{{if eq .Type 0}}
|
||||
<div class="comment" id="{{.HashTag}}">
|
||||
<a class="avatar" {{if gt .Poster.ID 0}}href="{{.Poster.HomeLink}}"{{end}}>
|
||||
|
@ -189,5 +189,35 @@
|
|||
</a>
|
||||
<span class="text grey"><a href="{{.Poster.HomeLink}}">{{.Poster.Name}}</a> {{$.i18n.Tr "repo.issues.cancel_tracking_history" $createdStr | Safe}}</span>
|
||||
</div>
|
||||
{{else if eq .Type 16}}
|
||||
<div class="event">
|
||||
<span class="octicon octicon-primitive-dot"></span>
|
||||
<a class="ui avatar image" href="{{.Poster.HomeLink}}">
|
||||
<img src="{{.Poster.RelAvatarLink}}">
|
||||
</a>
|
||||
<span class="text grey"><a href="{{.Poster.HomeLink}}">{{.Poster.Name}}</a>
|
||||
{{$.i18n.Tr "repo.issues.due_date_added" .Content $createdStr | Safe}}
|
||||
</span>
|
||||
</div>
|
||||
{{else if eq .Type 17}}
|
||||
<div class="event">
|
||||
<span class="octicon octicon-primitive-dot"></span>
|
||||
<a class="ui avatar image" href="{{.Poster.HomeLink}}">
|
||||
<img src="{{.Poster.RelAvatarLink}}">
|
||||
</a>
|
||||
<span class="text grey"><a href="{{.Poster.HomeLink}}">{{.Poster.Name}}</a>
|
||||
{{$.i18n.Tr "repo.issues.due_date_modified" (.Content | ParseDeadline) $createdStr | Safe}}
|
||||
</span>
|
||||
</div>
|
||||
{{else if eq .Type 18}}
|
||||
<div class="event">
|
||||
<span class="octicon octicon-primitive-dot"></span>
|
||||
<a class="ui avatar image" href="{{.Poster.HomeLink}}">
|
||||
<img src="{{.Poster.RelAvatarLink}}">
|
||||
</a>
|
||||
<span class="text grey"><a href="{{.Poster.HomeLink}}">{{.Poster.Name}}</a>
|
||||
{{$.i18n.Tr "repo.issues.due_date_remove" .Content $createdStr | Safe}}
|
||||
</span>
|
||||
</div>
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
|
|
@ -191,5 +191,41 @@
|
|||
</div>
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
<div class="ui divider"></div>
|
||||
<span class="text"><strong>{{.i18n.Tr "repo.issues.due_date"}}</strong></span>
|
||||
{{if gt .Issue.DeadlineUnix 0}}
|
||||
<p>
|
||||
<span class="octicon octicon-calendar"></span>
|
||||
{{.Issue.DeadlineUnix.FormatShort}}
|
||||
{{if .Issue.IsOverdue}}
|
||||
<span style="color: red;">{{.i18n.Tr "repo.issues.due_date_overdue"}}</span>
|
||||
{{end}}
|
||||
{{if and .IsSigned .IsRepositoryWriter}}
|
||||
<br/>
|
||||
<a style="cursor:pointer;" onclick="toggleDuedateForm();"><i class="edit icon"></i>Edit</a> -
|
||||
<a style="cursor:pointer;" onclick="deleteDueDate('{{$.RepoLink}}/issues/{{.Issue.Index}}/deadline/delete');"><i class="remove icon"></i>Remove</a>
|
||||
{{end}}
|
||||
</p>
|
||||
{{else}}
|
||||
<p><i>{{.i18n.Tr "repo.issues.due_date_not_set"}}</i></p>
|
||||
{{end}}
|
||||
|
||||
{{if and .IsSigned .IsRepositoryWriter}}
|
||||
<form method="POST"{{if gt .Issue.DeadlineUnix 0}}style="display: none;"{{end}}} id="add_deadline_form" action="{{$.RepoLink}}/issues/{{.Issue.Index}}/deadline/update" class="ui action input fluid">
|
||||
{{$.CsrfTokenHtml}}
|
||||
<div class="ui fluid action input">
|
||||
<input required placeholder="{{.i18n.Tr "repo.issues.due_date_form"}}" {{if gt .Issue.DeadlineUnix 0}}value="{{.Issue.DeadlineUnix.Format "2006-01-02"}}"{{end}} type="date" name="date" style="min-width: 13.9rem;border-radius: 4px 0 0 4px;border-right: 0;white-space: nowrap;">
|
||||
<button class="ui green icon button">
|
||||
{{if gt .Issue.DeadlineUnix 0}}
|
||||
<i class="edit icon"></i>
|
||||
{{else}}
|
||||
<i class="plus icon"></i>
|
||||
{{end}}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
{{end}}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -35,7 +35,7 @@ func (c *Client) ListReleaseAttachments(user, repo string, release int64) ([]*At
|
|||
return attachments, err
|
||||
}
|
||||
|
||||
// ListReleaseAttachments list release's attachments
|
||||
// GetReleaseAttachment returns the requested attachment
|
||||
func (c *Client) GetReleaseAttachment(user, repo string, release int64, id int64) (*Attachment, error) {
|
||||
a := new(Attachment)
|
||||
err := c.getParsedResponse("GET",
|
||||
|
|
|
@ -39,6 +39,7 @@ type Issue struct {
|
|||
Labels []*Label `json:"labels"`
|
||||
Milestone *Milestone `json:"milestone"`
|
||||
Assignee *User `json:"assignee"`
|
||||
Assignees []*User `json:"assignees"`
|
||||
// Whether the issue is open or closed
|
||||
//
|
||||
// type: string
|
||||
|
@ -49,6 +50,10 @@ type Issue struct {
|
|||
Created time.Time `json:"created_at"`
|
||||
// swagger:strfmt date-time
|
||||
Updated time.Time `json:"updated_at"`
|
||||
// swagger:strfmt date-time
|
||||
Closed *time.Time `json:"closed_at"`
|
||||
// swagger:strfmt date-time
|
||||
Deadline *time.Time `json:"due_date"`
|
||||
|
||||
PullRequest *PullRequestMeta `json:"pull_request"`
|
||||
}
|
||||
|
@ -89,7 +94,10 @@ type CreateIssueOption struct {
|
|||
Title string `json:"title" binding:"Required"`
|
||||
Body string `json:"body"`
|
||||
// username of assignee
|
||||
Assignee string `json:"assignee"`
|
||||
Assignee string `json:"assignee"`
|
||||
Assignees []string `json:"assignees"`
|
||||
// swagger:strfmt date-time
|
||||
Deadline *time.Time `json:"due_date"`
|
||||
// milestone id
|
||||
Milestone int64 `json:"milestone"`
|
||||
// list of label ids
|
||||
|
@ -110,11 +118,14 @@ func (c *Client) CreateIssue(owner, repo string, opt CreateIssueOption) (*Issue,
|
|||
|
||||
// EditIssueOption options for editing an issue
|
||||
type EditIssueOption struct {
|
||||
Title string `json:"title"`
|
||||
Body *string `json:"body"`
|
||||
Assignee *string `json:"assignee"`
|
||||
Milestone *int64 `json:"milestone"`
|
||||
State *string `json:"state"`
|
||||
Title string `json:"title"`
|
||||
Body *string `json:"body"`
|
||||
Assignee *string `json:"assignee"`
|
||||
Assignees []string `json:"assignees"`
|
||||
Milestone *int64 `json:"milestone"`
|
||||
State *string `json:"state"`
|
||||
// swagger:strfmt date-time
|
||||
Deadline *time.Time `json:"due_date"`
|
||||
}
|
||||
|
||||
// EditIssue modify an existing issue for a given repository
|
||||
|
|
|
@ -22,6 +22,7 @@ type PullRequest struct {
|
|||
Labels []*Label `json:"labels"`
|
||||
Milestone *Milestone `json:"milestone"`
|
||||
Assignee *User `json:"assignee"`
|
||||
Assignees []*User `json:"assignees"`
|
||||
State StateType `json:"state"`
|
||||
Comments int `json:"comments"`
|
||||
|
||||
|
@ -40,10 +41,15 @@ type PullRequest struct {
|
|||
Head *PRBranchInfo `json:"head"`
|
||||
MergeBase string `json:"merge_base"`
|
||||
|
||||
// swagger:strfmt date-time
|
||||
Deadline *time.Time `json:"due_date"`
|
||||
|
||||
// swagger:strfmt date-time
|
||||
Created *time.Time `json:"created_at"`
|
||||
// swagger:strfmt date-time
|
||||
Updated *time.Time `json:"updated_at"`
|
||||
// swagger:strfmt date-time
|
||||
Closed *time.Time `json:"closed_at"`
|
||||
}
|
||||
|
||||
// PRBranchInfo information about a branch
|
||||
|
@ -79,13 +85,16 @@ func (c *Client) GetPullRequest(owner, repo string, index int64) (*PullRequest,
|
|||
|
||||
// CreatePullRequestOption options when creating a pull request
|
||||
type CreatePullRequestOption struct {
|
||||
Head string `json:"head" binding:"Required"`
|
||||
Base string `json:"base" binding:"Required"`
|
||||
Title string `json:"title" binding:"Required"`
|
||||
Body string `json:"body"`
|
||||
Assignee string `json:"assignee"`
|
||||
Milestone int64 `json:"milestone"`
|
||||
Labels []int64 `json:"labels"`
|
||||
Head string `json:"head" binding:"Required"`
|
||||
Base string `json:"base" binding:"Required"`
|
||||
Title string `json:"title" binding:"Required"`
|
||||
Body string `json:"body"`
|
||||
Assignee string `json:"assignee"`
|
||||
Assignees []string `json:"assignees"`
|
||||
Milestone int64 `json:"milestone"`
|
||||
Labels []int64 `json:"labels"`
|
||||
// swagger:strfmt date-time
|
||||
Deadline *time.Time `json:"due_date"`
|
||||
}
|
||||
|
||||
// CreatePullRequest create pull request with options
|
||||
|
@ -101,12 +110,15 @@ func (c *Client) CreatePullRequest(owner, repo string, opt CreatePullRequestOpti
|
|||
|
||||
// EditPullRequestOption options when modify pull request
|
||||
type EditPullRequestOption struct {
|
||||
Title string `json:"title"`
|
||||
Body string `json:"body"`
|
||||
Assignee string `json:"assignee"`
|
||||
Milestone int64 `json:"milestone"`
|
||||
Labels []int64 `json:"labels"`
|
||||
State *string `json:"state"`
|
||||
Title string `json:"title"`
|
||||
Body string `json:"body"`
|
||||
Assignee string `json:"assignee"`
|
||||
Assignees []string `json:"assignees"`
|
||||
Milestone int64 `json:"milestone"`
|
||||
Labels []int64 `json:"labels"`
|
||||
State *string `json:"state"`
|
||||
// swagger:strfmt date-time
|
||||
Deadline *time.Time `json:"due_date"`
|
||||
}
|
||||
|
||||
// EditPullRequest modify pull request with PR id and options
|
||||
|
|
|
@ -9,10 +9,10 @@
|
|||
"revisionTime": "2018-04-21T01:08:19Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "PWaIU7g1YSkETxka2DIS1EYsPK0=",
|
||||
"checksumSHA1": "xXzi8Xx7HA3M0z3lR/1wr1Vz1fc=",
|
||||
"path": "code.gitea.io/sdk/gitea",
|
||||
"revision": "cdbef997666132599cc92dc22aa94de3db04adeb",
|
||||
"revisionTime": "2018-03-02T14:48:43Z"
|
||||
"revision": "142acef5ce79f78585afcce31748af46c72a3dea",
|
||||
"revisionTime": "2018-04-17T00:54:29Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "bOODD4Gbw3GfcuQPU2dI40crxxk=",
|
||||
|
|
Загрузка…
Ссылка в новой задаче