Skip to content

Commit

Permalink
fix
Browse files Browse the repository at this point in the history
  • Loading branch information
wxiaoguang committed Nov 5, 2024
1 parent ef86f4e commit 4d7d005
Show file tree
Hide file tree
Showing 14 changed files with 102 additions and 151 deletions.
8 changes: 3 additions & 5 deletions models/actions/schedule_spec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
12 changes: 3 additions & 9 deletions routers/api/v1/repo/issue.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -1046,18 +1047,11 @@ 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
}

ctx.JSON(http.StatusCreated, api.IssueDeadline{Deadline: &deadline})
ctx.JSON(http.StatusCreated, api.IssueDeadline{Deadline: deadlineUnix.AsTimePtr()})
}
5 changes: 2 additions & 3 deletions routers/api/v1/repo/milestone.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)
Expand Down Expand Up @@ -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 {
Expand Down
31 changes: 31 additions & 0 deletions routers/common/deadline.go
Original file line number Diff line number Diff line change
@@ -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
}
15 changes: 3 additions & 12 deletions routers/web/repo/issue.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import (
"sort"
"strconv"
"strings"
"time"

activities_model "code.gitea.io/gitea/models/activities"
"code.gitea.io/gitea/models/db"
Expand Down Expand Up @@ -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"
Expand Down Expand Up @@ -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) {
Expand All @@ -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
Expand Down
39 changes: 13 additions & 26 deletions routers/web/repo/milestone.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -16,8 +15,8 @@ import (
"code.gitea.io/gitea/modules/markup/markdown"
"code.gitea.io/gitea/modules/optional"
"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"
Expand Down Expand Up @@ -134,24 +133,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
Expand Down Expand Up @@ -196,17 +189,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"))
Expand All @@ -220,7 +207,7 @@ func EditMilestonePost(ctx *context.Context) {
}
m.Name = form.Title
m.Content = form.Content
m.DeadlineUnix = timeutil.TimeStamp(deadlineUnix)
m.DeadlineUnix = deadlineUnix
if err = issues_model.UpdateMilestone(ctx, m, m.IsClosed); err != nil {
ctx.ServerError("UpdateMilestone", err)
return
Expand Down
2 changes: 1 addition & 1 deletion routers/web/web.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions templates/repo/issue/milestone_new.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@
<div class="field {{if .Err_Deadline}}error{{end}}">
<label>
{{ctx.Locale.Tr "repo.milestones.due_date"}}
<a id="clear-date">{{ctx.Locale.Tr "repo.milestones.clear"}}</a>
<a id="milestone-clear-deadline">{{ctx.Locale.Tr "repo.milestones.clear"}}</a>
</label>
<input type="date" id="deadline" name="deadline" value="{{.deadline}}" placeholder="{{ctx.Locale.Tr "repo.issues.due_date_form"}}">
<input type="date" name="deadline" class="tw-w-auto" value="{{.deadline}}" placeholder="{{ctx.Locale.Tr "repo.issues.due_date_form"}}">
</div>
<div class="field">
<label>{{ctx.Locale.Tr "repo.milestones.desc"}}</label>
Expand Down
53 changes: 20 additions & 33 deletions templates/repo/issue/view_content/sidebar.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -358,44 +358,31 @@

<div class="divider"></div>
<span class="text"><strong>{{ctx.Locale.Tr "repo.issues.due_date"}}</strong></span>
<div class="ui form" id="deadline-loader">
<div class="ui negative message tw-hidden" id="deadline-err-invalid-date">
{{svg "octicon-x" 16 "close icon"}}
{{ctx.Locale.Tr "repo.issues.due_date_invalid"}}
</div>
{{if ne .Issue.DeadlineUnix 0}}
<p>
<div class="tw-flex tw-justify-between tw-items-center">
<div class="due-date {{if .Issue.IsOverdue}}text red{{end}}" {{if .Issue.IsOverdue}}data-tooltip-content="{{ctx.Locale.Tr "repo.issues.due_date_overdue"}}"{{end}}>
{{svg "octicon-calendar" 16 "tw-mr-2"}}
{{DateUtils.AbsoluteLong .Issue.DeadlineUnix}}
</div>
<div>
{{if and .HasIssuesOrPullsWritePermission (not .Repository.IsArchived)}}
<a class="issue-due-edit muted" data-tooltip-content="{{ctx.Locale.Tr "repo.issues.due_date_form_edit"}}">{{svg "octicon-pencil" 16 "tw-mr-1"}}</a>
<a class="issue-due-remove muted" data-tooltip-content="{{ctx.Locale.Tr "repo.issues.due_date_form_remove"}}">{{svg "octicon-trash"}}</a>
{{end}}
</div>
<div class="ui form tw-mt-2">
{{if .Issue.DeadlineUnix}}
<div class="tw-flex tw-justify-between tw-items-center tw-gap-2">
<div class="due-date {{if .Issue.IsOverdue}}text red{{end}}" {{if .Issue.IsOverdue}}data-tooltip-content="{{ctx.Locale.Tr "repo.issues.due_date_overdue"}}"{{end}}>
{{svg "octicon-calendar"}} {{DateUtils.AbsoluteLong .Issue.DeadlineUnix}}
</div>
<div class="flex-text-block">
{{if and .HasIssuesOrPullsWritePermission (not .Repository.IsArchived)}}
<a class="issue-due-edit muted" data-tooltip-content="{{ctx.Locale.Tr "repo.issues.due_date_form_edit"}}">{{svg "octicon-pencil"}}</a>
<a class="issue-due-remove muted" data-tooltip-content="{{ctx.Locale.Tr "repo.issues.due_date_form_remove"}}">{{svg "octicon-trash"}}</a>
{{end}}
</div>
</p>
</div>
{{else}}
<p>{{ctx.Locale.Tr "repo.issues.due_date_not_set"}}</p>
{{ctx.Locale.Tr "repo.issues.due_date_not_set"}}
{{end}}

{{if and .HasIssuesOrPullsWritePermission (not .Repository.IsArchived)}}
<div {{if ne .Issue.DeadlineUnix 0}} class="tw-hidden"{{end}} id="deadlineForm">
<form class="ui fluid action input issue-due-form" action="{{AppSubUrl}}/{{PathEscape .Repository.Owner.Name}}/{{PathEscape .Repository.Name}}/issues/{{.Issue.Index}}/deadline" method="post" id="update-issue-deadline-form">
{{$.CsrfTokenHtml}}
<input required placeholder="{{ctx.Locale.Tr "repo.issues.due_date_form"}}" {{if gt .Issue.DeadlineUnix 0}}value="{{.Issue.DeadlineUnix.FormatDate}}"{{end}} type="date" name="deadlineDate" id="deadlineDate">
<button class="ui icon button">
{{if ne .Issue.DeadlineUnix 0}}
{{svg "octicon-pencil"}}
{{else}}
{{svg "octicon-plus"}}
{{end}}
</button>
</form>
</div>
<form class="ui fluid action input issue-due-form form-fetch-action tw-mt-2 {{if .Issue.DeadlineUnix}}tw-hidden{{end}}"
method="post" action="{{AppSubUrl}}/{{PathEscape .Repository.Owner.Name}}/{{PathEscape .Repository.Name}}/issues/{{.Issue.Index}}/deadline"
>
{{$.CsrfTokenHtml}}
<input required type="date" name="deadline" placeholder="{{ctx.Locale.Tr "repo.issues.due_date_form"}}" {{if .Issue.DeadlineUnix}}value="{{.Issue.DeadlineUnix.FormatDate}}"{{end}}>
<button class="ui icon button">{{Iif .Issue.DeadlineUnix (svg "octicon-pencil") (svg "octicon-plus")}}</button>
</form>
{{end}}
</div>

Expand Down
5 changes: 2 additions & 3 deletions tests/integration/api_issue_milestone_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"fmt"
"net/http"
"testing"
"time"

auth_model "code.gitea.io/gitea/models/auth"
issues_model "code.gitea.io/gitea/models/issues"
Expand Down Expand Up @@ -60,15 +59,15 @@ func TestAPIIssuesMilestone(t *testing.T) {
DecodeJSON(t, resp, &apiMilestone)
assert.Equal(t, "wow", apiMilestone.Title)
assert.Equal(t, structs.StateClosed, apiMilestone.State)
assert.Equal(t, (*time.Time)(nil), apiMilestone.Deadline)
assert.Nil(t, apiMilestone.Deadline)

var apiMilestones []structs.Milestone
req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/repos/%s/%s/milestones?state=%s", owner.Name, repo.Name, "all")).
AddTokenAuth(token)
resp = MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, resp, &apiMilestones)
assert.Len(t, apiMilestones, 4)
assert.Equal(t, (*time.Time)(nil), apiMilestones[0].Deadline)
assert.Nil(t, apiMilestones[0].Deadline)

req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/repos/%s/%s/milestones/%s", owner.Name, repo.Name, apiMilestones[2].Title)).
AddTokenAuth(token)
Expand Down
15 changes: 15 additions & 0 deletions web_src/js/features/repo-issue-sidebar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {POST} from '../modules/fetch.ts';
import {updateIssuesMeta} from './repo-common.ts';
import {svg} from '../svg.ts';
import {htmlEscape} from 'escape-goat';
import {toggleElem} from '../utils/dom.ts';

// if there are draft comments, confirm before reloading, to avoid losing comments
function reloadConfirmDraftComment() {
Expand Down Expand Up @@ -258,8 +259,22 @@ function selectItem(select_id, input_id) {
});
}

function initRepoIssueDue() {
const form = document.querySelector<HTMLFormElement>('.issue-due-form');
if (!form) return;
const deadline = form.querySelector<HTMLInputElement>('input[name=deadline]');
document.querySelector('.issue-due-edit')?.addEventListener('click', () => {
toggleElem(form);
});
document.querySelector('.issue-due-remove')?.addEventListener('click', () => {
deadline.value = '';
form.dispatchEvent(new Event('submit', {cancelable: true, bubbles: true}));
});
}

export function initRepoIssueSidebar() {
initBranchSelector();
initRepoIssueDue();

// Init labels and assignees
initListSubmits('select-label', 'labels');
Expand Down
Loading

0 comments on commit 4d7d005

Please sign in to comment.