diff --git a/models/actions/schedule_spec_test.go b/models/actions/schedule_spec_test.go index 0c26fce4b2c5e..57221461dfec5 100644 --- a/models/actions/schedule_spec_test.go +++ b/models/actions/schedule_spec_test.go @@ -7,19 +7,17 @@ import ( "testing" "time" + "code.gitea.io/gitea/modules/test" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func TestActionScheduleSpec_Parse(t *testing.T) { // Mock the local timezone is not UTC - local := time.Local tz, err := time.LoadLocation("Asia/Shanghai") require.NoError(t, err) - defer func() { - time.Local = local - }() - time.Local = tz + defer test.MockVariableValue(&time.Local, tz)() now, err := time.Parse(time.RFC3339, "2024-07-31T15:47:55+08:00") require.NoError(t, err) diff --git a/routers/api/v1/repo/issue.go b/routers/api/v1/repo/issue.go index e86fb3ccb1c52..aee6ef937a625 100644 --- a/routers/api/v1/repo/issue.go +++ b/routers/api/v1/repo/issue.go @@ -26,6 +26,7 @@ import ( "code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/api/v1/utils" + "code.gitea.io/gitea/routers/common" "code.gitea.io/gitea/services/context" "code.gitea.io/gitea/services/convert" issue_service "code.gitea.io/gitea/services/issue" @@ -1046,14 +1047,7 @@ func UpdateIssueDeadline(ctx *context.APIContext) { return } - var deadlineUnix timeutil.TimeStamp - var deadline time.Time - if form.Deadline != nil && !form.Deadline.IsZero() { - deadline = time.Date(form.Deadline.Year(), form.Deadline.Month(), form.Deadline.Day(), - 23, 59, 59, 0, time.Local) - deadlineUnix = timeutil.TimeStamp(deadline.Unix()) - } - + deadlineUnix := common.ParseAPIDeadlineToEndOfDay(form.Deadline) if err := issues_model.UpdateIssueDeadline(ctx, issue, deadlineUnix, ctx.Doer); err != nil { ctx.Error(http.StatusInternalServerError, "UpdateIssueDeadline", err) return diff --git a/routers/api/v1/repo/milestone.go b/routers/api/v1/repo/milestone.go index 67e3ed829efee..78907c85a5847 100644 --- a/routers/api/v1/repo/milestone.go +++ b/routers/api/v1/repo/milestone.go @@ -15,6 +15,7 @@ import ( "code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/api/v1/utils" + "code.gitea.io/gitea/routers/common" "code.gitea.io/gitea/services/context" "code.gitea.io/gitea/services/convert" ) @@ -224,9 +225,7 @@ func EditMilestone(ctx *context.APIContext) { if form.Description != nil { milestone.Content = *form.Description } - if form.Deadline != nil && !form.Deadline.IsZero() { - milestone.DeadlineUnix = timeutil.TimeStamp(form.Deadline.Unix()) - } + milestone.DeadlineUnix, _ = common.ParseAPIDeadlineToEndOfDay(form.Deadline) oldIsClosed := milestone.IsClosed if form.State != nil { diff --git a/routers/common/deadline.go b/routers/common/deadline.go new file mode 100644 index 0000000000000..152e94597bc6a --- /dev/null +++ b/routers/common/deadline.go @@ -0,0 +1,31 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package common + +import ( + "time" + + "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/timeutil" +) + +func ParseDeadlineDateToEndOfDay(date string) (timeutil.TimeStamp, error) { + if date == "" { + return 0, nil + } + deadline, err := time.ParseInLocation("2006-01-02", date, setting.DefaultUILocation) + if err != nil { + return 0, err + } + deadline = time.Date(deadline.Year(), deadline.Month(), deadline.Day(), 23, 59, 59, 0, deadline.Location()) + return timeutil.TimeStamp(deadline.Unix()), nil +} + +func ParseAPIDeadlineToEndOfDay(t *time.Time) (timeutil.TimeStamp, error) { + if t == nil || t.IsZero() || t.Unix() == 0 { + return 0, nil + } + deadline := time.Date(t.Year(), t.Month(), t.Day(), 23, 59, 59, 0, setting.DefaultUILocation) + return timeutil.TimeStamp(deadline.Unix()), nil +} diff --git a/routers/web/repo/issue.go b/routers/web/repo/issue.go index 507b5af9d904a..21eb71e9f3393 100644 --- a/routers/web/repo/issue.go +++ b/routers/web/repo/issue.go @@ -17,7 +17,6 @@ import ( "sort" "strconv" "strings" - "time" activities_model "code.gitea.io/gitea/models/activities" "code.gitea.io/gitea/models/db" @@ -45,9 +44,9 @@ import ( api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/templates" "code.gitea.io/gitea/modules/templates/vars" - "code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/web" + "code.gitea.io/gitea/routers/common" "code.gitea.io/gitea/routers/utils" shared_user "code.gitea.io/gitea/routers/web/shared/user" asymkey_service "code.gitea.io/gitea/services/asymkey" @@ -2329,7 +2328,6 @@ func UpdateIssueContent(ctx *context.Context) { // UpdateIssueDeadline updates an issue deadline func UpdateIssueDeadline(ctx *context.Context) { - form := web.GetForm(ctx).(*api.EditDeadlineOption) issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.PathParamInt64(":index")) if err != nil { if issues_model.IsErrIssueNotExist(err) { @@ -2345,20 +2343,13 @@ func UpdateIssueDeadline(ctx *context.Context) { return } - var deadlineUnix timeutil.TimeStamp - var deadline time.Time - if form.Deadline != nil && !form.Deadline.IsZero() { - deadline = time.Date(form.Deadline.Year(), form.Deadline.Month(), form.Deadline.Day(), - 23, 59, 59, 0, time.Local) - deadlineUnix = timeutil.TimeStamp(deadline.Unix()) - } - + deadlineUnix, _ := common.ParseDeadlineDateToEndOfDay(ctx.FormString("deadline")) if err := issues_model.UpdateIssueDeadline(ctx, issue, deadlineUnix, ctx.Doer); err != nil { ctx.Error(http.StatusInternalServerError, "UpdateIssueDeadline", err.Error()) return } - ctx.JSON(http.StatusCreated, api.IssueDeadline{Deadline: &deadline}) + ctx.JSONRedirect("") } // UpdateIssueMilestone change issue's milestone diff --git a/routers/web/repo/milestone.go b/routers/web/repo/milestone.go index a6d0df919c4d7..af394a822d411 100644 --- a/routers/web/repo/milestone.go +++ b/routers/web/repo/milestone.go @@ -7,7 +7,6 @@ import ( "fmt" "net/http" "net/url" - "time" "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" @@ -18,6 +17,7 @@ import ( "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/web" + "code.gitea.io/gitea/routers/common" "code.gitea.io/gitea/services/context" "code.gitea.io/gitea/services/forms" "code.gitea.io/gitea/services/issue" @@ -134,24 +134,18 @@ func NewMilestonePost(ctx *context.Context) { return } - var deadlineUnix int64 - if len(form.Deadline) > 0 { - deadline, err := time.ParseInLocation("2006-01-02", form.Deadline, time.Local) - if err != nil { - ctx.Data["Err_Deadline"] = true - ctx.RenderWithErr(ctx.Tr("repo.milestones.invalid_due_date_format"), tplMilestoneNew, &form) - return - } - - deadline = time.Date(deadline.Year(), deadline.Month(), deadline.Day(), 23, 59, 59, 0, deadline.Location()) - deadlineUnix = deadline.Unix() + deadlineUnix, err := common.ParseDeadlineDateToEndOfDay(form.Deadline) + if err != nil { + ctx.Data["Err_Deadline"] = true + ctx.RenderWithErr(ctx.Tr("repo.milestones.invalid_due_date_format"), tplMilestoneNew, &form) + return } if err := issues_model.NewMilestone(ctx, &issues_model.Milestone{ RepoID: ctx.Repo.Repository.ID, Name: form.Title, Content: form.Content, - DeadlineUnix: timeutil.TimeStamp(deadlineUnix), + DeadlineUnix: deadlineUnix, }); err != nil { ctx.ServerError("NewMilestone", err) return @@ -196,17 +190,11 @@ func EditMilestonePost(ctx *context.Context) { return } - var deadlineUnix int64 - if len(form.Deadline) > 0 { - deadline, err := time.ParseInLocation("2006-01-02", form.Deadline, time.Local) - if err != nil { - ctx.Data["Err_Deadline"] = true - ctx.RenderWithErr(ctx.Tr("repo.milestones.invalid_due_date_format"), tplMilestoneNew, &form) - return - } - - deadline = time.Date(deadline.Year(), deadline.Month(), deadline.Day(), 23, 59, 59, 0, deadline.Location()) - deadlineUnix = deadline.Unix() + deadlineUnix, err := common.ParseDeadlineDateToEndOfDay(form.Deadline) + if err != nil { + ctx.Data["Err_Deadline"] = true + ctx.RenderWithErr(ctx.Tr("repo.milestones.invalid_due_date_format"), tplMilestoneNew, &form) + return } m, err := issues_model.GetMilestoneByRepoID(ctx, ctx.Repo.Repository.ID, ctx.PathParamInt64(":id")) diff --git a/routers/web/web.go b/routers/web/web.go index 83d116babd769..ebedea73f1907 100644 --- a/routers/web/web.go +++ b/routers/web/web.go @@ -1208,7 +1208,7 @@ func registerRoutes(m *web.Router) { m.Group("/{index}", func() { m.Post("/title", repo.UpdateIssueTitle) m.Post("/content", repo.UpdateIssueContent) - m.Post("/deadline", web.Bind(structs.EditDeadlineOption{}), repo.UpdateIssueDeadline) + m.Post("/deadline", repo.UpdateIssueDeadline) m.Post("/watch", repo.IssueWatch) m.Post("/ref", repo.UpdateIssueRef) m.Post("/pin", reqRepoAdmin, repo.IssuePinOrUnpin) diff --git a/templates/repo/issue/milestone_new.tmpl b/templates/repo/issue/milestone_new.tmpl index 9f32df00e39f0..736a75d73a1b3 100644 --- a/templates/repo/issue/milestone_new.tmpl +++ b/templates/repo/issue/milestone_new.tmpl @@ -30,9 +30,9 @@
-
{{ctx.Locale.Tr "repo.issues.due_date_not_set"}}
+ {{ctx.Locale.Tr "repo.issues.due_date_not_set"}} {{end}} {{if and .HasIssuesOrPullsWritePermission (not .Repository.IsArchived)}} -