"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)
// this object.
func (m *Milestone) AfterLoad() {
m.NumOpenIssues = m.NumIssues - m.NumClosedIssues
- if m.DeadlineUnix.Year() == 9999 {
+ if m.DeadlineUnix == 0 {
return
}
-
m.DeadlineString = m.DeadlineUnix.FormatDate()
if m.IsClosed {
m.IsOverdue = m.ClosedDateUnix >= m.DeadlineUnix
newMigration(304, "Add index for release sha1", v1_23.AddIndexForReleaseSha1),
newMigration(305, "Add Repository Licenses", v1_23.AddRepositoryLicenses),
newMigration(306, "Add BlockAdminMergeOverride to ProtectedBranch", v1_23.AddBlockAdminMergeOverrideBranchProtection),
+ newMigration(307, "Fix milestone deadline_unix when there is no due date", v1_23.FixMilestoneNoDueDate),
}
return preparedMigrations
}
--- /dev/null
+// Copyright 2024 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package v1_23 //nolint
+
+import (
+ "code.gitea.io/gitea/modules/timeutil"
+
+ "xorm.io/xorm"
+)
+
+func FixMilestoneNoDueDate(x *xorm.Engine) error {
+ type Milestone struct {
+ DeadlineUnix timeutil.TimeStamp
+ }
+ // Wednesday, December 1, 9999 12:00:00 AM GMT+00:00
+ _, err := x.Table("milestone").Where("deadline_unix > 253399622400").
+ Cols("deadline_unix").
+ Update(&Milestone{DeadlineUnix: 0})
+ return err
+}
graphCmd.AddArguments("--all")
}
- graphCmd.AddArguments("-C", "-M", "--date=iso").
+ graphCmd.AddArguments("-C", "-M", "--date=iso-strict").
AddOptionFormat("-n %d", setting.UI.GraphMaxCommitNum*page).
AddOptionFormat("--pretty=format:%s", format)
"context"
"fmt"
"strings"
+ "time"
asymkey_model "code.gitea.io/gitea/models/asymkey"
"code.gitea.io/gitea/models/db"
Row: -1,
}
+func parseGitTime(timeStr string) time.Time {
+ t, err := time.Parse(time.RFC3339, timeStr)
+ if err != nil {
+ return time.Unix(0, 0)
+ }
+ return t
+}
+
// NewCommit creates a new commit from a provided line
func NewCommit(row, column int, line []byte) (*Commit, error) {
data := bytes.SplitN(line, []byte("|"), 5)
// 1 matches git log --pretty=format:%H => commit hash
Rev: string(data[1]),
// 2 matches git log --pretty=format:%ad => author date (format respects --date= option)
- Date: string(data[2]),
+ Date: parseGitTime(string(data[2])),
// 3 matches git log --pretty=format:%h => abbreviated commit hash
ShortRev: string(data[3]),
// 4 matches git log --pretty=format:%s => subject
Column int
Refs []git.Reference
Rev string
- Date string
+ Date time.Time
ShortRev string
Subject string
}
// AbsoluteLong renders in "January 01, 2006" format
func (du *DateUtils) AbsoluteLong(time any) template.HTML {
- return dateTimeFormat("short", time)
+ return dateTimeFormat("long", time)
}
// FullTime renders in "Jan 01, 2006 20:33:44" format
"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"
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()})
}
import (
"net/http"
"strconv"
- "time"
"code.gitea.io/gitea/models/db"
issues_model "code.gitea.io/gitea/models/issues"
"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"
)
// "$ref": "#/responses/notFound"
form := web.GetForm(ctx).(*api.CreateMilestoneOption)
- if form.Deadline == nil {
- defaultDeadline, _ := time.ParseInLocation("2006-01-02", "9999-12-31", time.Local)
- form.Deadline = &defaultDeadline
+ var deadlineUnix int64
+ if form.Deadline != nil {
+ deadlineUnix = form.Deadline.Unix()
}
milestone := &issues_model.Milestone{
RepoID: ctx.Repo.Repository.ID,
Name: form.Title,
Content: form.Description,
- DeadlineUnix: timeutil.TimeStamp(form.Deadline.Unix()),
+ DeadlineUnix: timeutil.TimeStamp(deadlineUnix),
}
if form.State == "closed" {
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 {
--- /dev/null
+// 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
+}
"sort"
"strconv"
"strings"
- "time"
activities_model "code.gitea.io/gitea/models/activities"
"code.gitea.io/gitea/models/db"
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"
// 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) {
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
"fmt"
"net/http"
"net/url"
- "time"
"code.gitea.io/gitea/models/db"
issues_model "code.gitea.io/gitea/models/issues"
"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"
return
}
- if len(form.Deadline) == 0 {
- form.Deadline = "9999-12-31"
- }
- deadline, err := time.ParseInLocation("2006-01-02", form.Deadline, time.Local)
+ 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
}
- deadline = time.Date(deadline.Year(), deadline.Month(), deadline.Day(), 23, 59, 59, 0, deadline.Location())
- if err = issues_model.NewMilestone(ctx, &issues_model.Milestone{
+ if err := issues_model.NewMilestone(ctx, &issues_model.Milestone{
RepoID: ctx.Repo.Repository.ID,
Name: form.Title,
Content: form.Content,
- DeadlineUnix: timeutil.TimeStamp(deadline.Unix()),
+ DeadlineUnix: deadlineUnix,
}); err != nil {
ctx.ServerError("NewMilestone", err)
return
return
}
- if len(form.Deadline) == 0 {
- form.Deadline = "9999-12-31"
- }
- deadline, err := time.ParseInLocation("2006-01-02", form.Deadline, time.Local)
+ 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
}
- deadline = time.Date(deadline.Year(), deadline.Month(), deadline.Day(), 23, 59, 59, 0, deadline.Location())
m, err := issues_model.GetMilestoneByRepoID(ctx, ctx.Repo.Repository.ID, ctx.PathParamInt64(":id"))
if err != nil {
if issues_model.IsErrMilestoneNotExist(err) {
}
m.Name = form.Title
m.Content = form.Content
- m.DeadlineUnix = timeutil.TimeStamp(deadline.Unix())
+ m.DeadlineUnix = deadlineUnix
if err = issues_model.UpdateMilestone(ctx, m, m.IsClosed); err != nil {
ctx.ServerError("UpdateMilestone", err)
return
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)
if m.IsClosed {
apiMilestone.Closed = m.ClosedDateUnix.AsTimePtr()
}
- if m.DeadlineUnix.Year() < 9999 {
+ if m.DeadlineUnix > 0 {
apiMilestone.Deadline = m.DeadlineUnix.AsTimePtr()
}
return apiMilestone
{{end}}
{{end}}
</span>
- <span class="author tw-flex tw-items-center tw-mr-2 tw-gap-[1px]">
+ <span class="author tw-flex tw-items-center tw-mr-2 tw-gap-1">
{{$userName := $commit.Commit.Author.Name}}
{{if $commit.User}}
{{if and $commit.User.FullName DefaultShowFullName}}
<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>
<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>
DecodeJSON(t, resp, &apiMilestone)
assert.Equal(t, "wow", apiMilestone.Title)
assert.Equal(t, structs.StateClosed, apiMilestone.State)
+ 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")).
resp = MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, resp, &apiMilestones)
assert.Len(t, apiMilestones, 4)
+ 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)
repoBefore := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: issueBefore.RepoID})
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repoBefore.OwnerID})
assert.NoError(t, issueBefore.LoadAttributes(db.DefaultContext))
- assert.Equal(t, int64(1019307200), int64(issueBefore.DeadlineUnix))
+ assert.Equal(t, "2002-04-20", issueBefore.DeadlineUnix.FormatDate())
assert.Equal(t, api.StateOpen, issueBefore.State())
session := loginUser(t, owner.Name)
+ urlStr := fmt.Sprintf("%s/%s/issues/%d/deadline?_csrf=%s", owner.Name, repoBefore.Name, issueBefore.Index, GetUserCSRFToken(t, session))
- issueURL := fmt.Sprintf("%s/%s/issues/%d", owner.Name, repoBefore.Name, issueBefore.Index)
- req := NewRequest(t, "GET", issueURL)
- resp := session.MakeRequest(t, req, http.StatusOK)
- htmlDoc := NewHTMLParser(t, resp.Body)
-
- urlStr := issueURL + "/deadline?_csrf=" + htmlDoc.GetCSRF()
- req = NewRequestWithJSON(t, "POST", urlStr, map[string]string{
- "due_date": "2022-04-06T00:00:00.000Z",
- })
-
- resp = session.MakeRequest(t, req, http.StatusCreated)
- var apiIssue api.IssueDeadline
- DecodeJSON(t, resp, &apiIssue)
+ req := NewRequestWithValues(t, "POST", urlStr, map[string]string{"deadline": "2022-04-06"})
+ session.MakeRequest(t, req, http.StatusOK)
+ issueAfter := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 10})
+ assert.EqualValues(t, "2022-04-06", issueAfter.DeadlineUnix.FormatDate())
- assert.EqualValues(t, "2022-04-06", apiIssue.Deadline.Format("2006-01-02"))
+ req = NewRequestWithValues(t, "POST", urlStr, map[string]string{"deadline": ""})
+ session.MakeRequest(t, req, http.StatusOK)
+ issueAfter = unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 10})
+ assert.True(t, issueAfter.DeadlineUnix.IsZero())
}
func TestIssueReferenceURL(t *testing.T) {
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() {
});
}
+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');
});
}
-async function updateDeadline(deadlineString) {
- hideElem('#deadline-err-invalid-date');
- document.querySelector('#deadline-loader')?.classList.add('is-loading');
-
- let realDeadline = null;
- if (deadlineString !== '') {
- const newDate = Date.parse(deadlineString);
-
- if (Number.isNaN(newDate)) {
- document.querySelector('#deadline-loader')?.classList.remove('is-loading');
- showElem('#deadline-err-invalid-date');
- return false;
- }
- realDeadline = new Date(newDate);
- }
-
- try {
- const response = await POST(document.querySelector('#update-issue-deadline-form').getAttribute('action'), {
- data: {due_date: realDeadline},
- });
-
- if (response.ok) {
- window.location.reload();
- } else {
- throw new Error('Invalid response');
- }
- } catch (error) {
- console.error(error);
- document.querySelector('#deadline-loader').classList.remove('is-loading');
- showElem('#deadline-err-invalid-date');
- }
-}
-
-export function initRepoIssueDue() {
- $(document).on('click', '.issue-due-edit', () => {
- toggleElem('#deadlineForm');
- });
- $(document).on('click', '.issue-due-remove', () => {
- updateDeadline('');
- });
- $(document).on('submit', '.issue-due-form', () => {
- updateDeadline($('#deadlineDate').val());
- return false;
- });
-}
-
/**
* @param {HTMLElement} item
*/
-import $ from 'jquery';
-
export function initRepoMilestone() {
- // Milestones
- if ($('.repository.new.milestone').length > 0) {
- $('#clear-date').on('click', () => {
- $('#deadline').val('');
- return false;
- });
- }
+ const page = document.querySelector('.repository.new.milestone');
+ if (!page) return;
+
+ const deadline = page.querySelector<HTMLInputElement>('form input[name=deadline]');
+ document.querySelector('#milestone-clear-deadline').addEventListener('click', () => {
+ deadline.value = '';
+ });
}
import {initUserAuthOauth2, initUserCheckAppUrl} from './features/user-auth.ts';
import {
- initRepoIssueDue,
initRepoIssueReferenceRepositorySearch,
initRepoIssueTimeTracking,
initRepoIssueWipTitle,
initRepoEditor,
initRepoGraphGit,
initRepoIssueContentHistory,
- initRepoIssueDue,
initRepoIssueList,
initRepoIssueSidebarList,
initArchivedLabelHandler,