diff options
author | Norwin <noerw@users.noreply.github.com> | 2021-02-19 10:52:11 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-02-19 12:52:11 +0200 |
commit | d38ae597e19f58bcd732717fe09c1ea97ab8bb12 (patch) | |
tree | 839f0b3c92a4b98a7be3b8aa316925615c16c76e | |
parent | 6a696b93b1e7e9dc1e7cc51d4eab2932b072170f (diff) | |
download | gitea-d38ae597e19f58bcd732717fe09c1ea97ab8bb12.tar.gz gitea-d38ae597e19f58bcd732717fe09c1ea97ab8bb12.zip |
Add UI to delete tracked times (#14100)
Co-authored-by: 6543 <6543@obermui.de>
-rw-r--r-- | models/issue_comment.go | 14 | ||||
-rw-r--r-- | models/issue_stopwatch.go | 1 | ||||
-rw-r--r-- | models/issue_tracked_time.go | 1 | ||||
-rw-r--r-- | models/migrations/migrations.go | 2 | ||||
-rw-r--r-- | models/migrations/v173.go | 22 | ||||
-rw-r--r-- | options/locale/locale_en-US.ini | 1 | ||||
-rw-r--r-- | routers/repo/issue.go | 4 | ||||
-rw-r--r-- | routers/repo/issue_timetrack.go | 40 | ||||
-rw-r--r-- | routers/routes/web.go | 1 | ||||
-rw-r--r-- | templates/repo/issue/view_content/comments.tmpl | 2 | ||||
-rw-r--r-- | templates/repo/issue/view_content/comments_delete_time.tmpl | 21 | ||||
-rw-r--r-- | templates/repo/issue/view_content/sidebar.tmpl | 2 | ||||
-rw-r--r-- | web_src/js/index.js | 16 |
13 files changed, 123 insertions, 4 deletions
diff --git a/models/issue_comment.go b/models/issue_comment.go index b15b5169ff..6cc03ba0e8 100644 --- a/models/issue_comment.go +++ b/models/issue_comment.go @@ -136,6 +136,8 @@ type Comment struct { MilestoneID int64 OldMilestone *Milestone `xorm:"-"` Milestone *Milestone `xorm:"-"` + TimeID int64 + Time *TrackedTime `xorm:"-"` AssigneeID int64 RemovedAssignee bool Assignee *User `xorm:"-"` @@ -541,6 +543,16 @@ func (c *Comment) LoadDepIssueDetails() (err error) { return err } +// LoadTime loads the associated time for a CommentTypeAddTimeManual +func (c *Comment) LoadTime() error { + if c.Time != nil || c.TimeID == 0 { + return nil + } + var err error + c.Time, err = GetTrackedTimeByID(c.TimeID) + return err +} + func (c *Comment) loadReactions(e Engine, repo *Repository) (err error) { if c.Reactions != nil { return nil @@ -692,6 +704,7 @@ func createComment(e *xorm.Session, opts *CreateCommentOptions) (_ *Comment, err MilestoneID: opts.MilestoneID, OldProjectID: opts.OldProjectID, ProjectID: opts.ProjectID, + TimeID: opts.TimeID, RemovedAssignee: opts.RemovedAssignee, AssigneeID: opts.AssigneeID, AssigneeTeamID: opts.AssigneeTeamID, @@ -859,6 +872,7 @@ type CreateCommentOptions struct { MilestoneID int64 OldProjectID int64 ProjectID int64 + TimeID int64 AssigneeID int64 AssigneeTeamID int64 RemovedAssignee bool diff --git a/models/issue_stopwatch.go b/models/issue_stopwatch.go index a1c88503d8..19bd4ab2c5 100644 --- a/models/issue_stopwatch.go +++ b/models/issue_stopwatch.go @@ -100,6 +100,7 @@ func CreateOrStopIssueStopwatch(user *User, issue *Issue) error { Repo: issue.Repo, Content: SecToTime(timediff), Type: CommentTypeStopTracking, + TimeID: tt.ID, }); err != nil { return err } diff --git a/models/issue_tracked_time.go b/models/issue_tracked_time.go index 195f3e7850..9717944cbb 100644 --- a/models/issue_tracked_time.go +++ b/models/issue_tracked_time.go @@ -162,6 +162,7 @@ func AddTime(user *User, issue *Issue, amount int64, created time.Time) (*Tracke Doer: user, Content: SecToTime(amount), Type: CommentTypeAddTimeManual, + TimeID: t.ID, }); err != nil { return nil, err } diff --git a/models/migrations/migrations.go b/models/migrations/migrations.go index 740e8cb3ee..4fc737e1bf 100644 --- a/models/migrations/migrations.go +++ b/models/migrations/migrations.go @@ -292,6 +292,8 @@ var migrations = []Migration{ NewMigration("Add Sorting to ProjectBoard table", addSortingColToProjectBoard), // v172 -> v173 NewMigration("Add sessions table for go-chi/session", addSessionTable), + // v173 -> v174 + NewMigration("Add time_id column to Comment", addTimeIDCommentColumn), } // GetCurrentDBVersion returns the current db version diff --git a/models/migrations/v173.go b/models/migrations/v173.go new file mode 100644 index 0000000000..dd4589066d --- /dev/null +++ b/models/migrations/v173.go @@ -0,0 +1,22 @@ +// Copyright 2021 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package migrations + +import ( + "fmt" + + "xorm.io/xorm" +) + +func addTimeIDCommentColumn(x *xorm.Engine) error { + type Comment struct { + TimeID int64 + } + + if err := x.Sync2(new(Comment)); err != nil { + return fmt.Errorf("Sync2: %v", err) + } + return nil +} diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index ec9f82ef03..2690303253 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -1163,6 +1163,7 @@ issues.stop_tracking_history = `stopped working %s` issues.cancel_tracking = Discard issues.cancel_tracking_history = `cancelled time tracking %s` issues.add_time = Manually Add Time +issues.del_time = Delete this time log issues.add_time_short = Add Time issues.add_time_cancel = Cancel issues.add_time_history = `added spent time %s` diff --git a/routers/repo/issue.go b/routers/repo/issue.go index fa1ee99771..a9459a10ed 100644 --- a/routers/repo/issue.go +++ b/routers/repo/issue.go @@ -1416,6 +1416,10 @@ func ViewIssue(ctx *context.Context) { ctx.ServerError("LoadPushCommits", err) return } + } else if comment.Type == models.CommentTypeAddTimeManual || + comment.Type == models.CommentTypeStopTracking { + // drop error since times could be pruned from DB.. + _ = comment.LoadTime() } } diff --git a/routers/repo/issue_timetrack.go b/routers/repo/issue_timetrack.go index 425f215110..3b13770d61 100644 --- a/routers/repo/issue_timetrack.go +++ b/routers/repo/issue_timetrack.go @@ -10,13 +10,13 @@ import ( "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/context" - auth "code.gitea.io/gitea/modules/forms" + "code.gitea.io/gitea/modules/forms" "code.gitea.io/gitea/modules/web" ) // AddTimeManually tracks time manually func AddTimeManually(c *context.Context) { - form := web.GetForm(c).(*auth.AddTimeManuallyForm) + form := web.GetForm(c).(*forms.AddTimeManuallyForm) issue := GetActionIssue(c) if c.Written() { return @@ -48,3 +48,39 @@ func AddTimeManually(c *context.Context) { c.Redirect(url, http.StatusSeeOther) } + +// DeleteTime deletes tracked time +func DeleteTime(c *context.Context) { + issue := GetActionIssue(c) + if c.Written() { + return + } + if !c.Repo.CanUseTimetracker(issue, c.User) { + c.NotFound("CanUseTimetracker", nil) + return + } + + t, err := models.GetTrackedTimeByID(c.ParamsInt64(":timeid")) + if err != nil { + if models.IsErrNotExist(err) { + c.NotFound("time not found", err) + return + } + c.Error(http.StatusInternalServerError, "GetTrackedTimeByID", err.Error()) + return + } + + // only OP or admin may delete + if !c.IsSigned || (!c.IsUserSiteAdmin() && c.User.ID != t.UserID) { + c.Error(http.StatusForbidden, "not allowed") + return + } + + if err = models.DeleteTime(t); err != nil { + c.ServerError("DeleteTime", err) + return + } + + c.Flash.Success(c.Tr("repo.issues.del_time_history", models.SecToTime(t.Time))) + c.Redirect(issue.HTMLURL()) +} diff --git a/routers/routes/web.go b/routers/routes/web.go index b3edd8f713..dd43663e35 100644 --- a/routers/routes/web.go +++ b/routers/routes/web.go @@ -723,6 +723,7 @@ func RegisterRoutes(m *web.Route) { m.Combo("/comments").Post(repo.MustAllowUserComment, bindIgnErr(auth.CreateCommentForm{}), repo.NewComment) m.Group("/times", func() { m.Post("/add", bindIgnErr(auth.AddTimeManuallyForm{}), repo.AddTimeManually) + m.Post("/{timeid}/delete", repo.DeleteTime) m.Group("/stopwatch", func() { m.Post("/toggle", repo.IssueStopwatch) m.Post("/cancel", repo.CancelStopwatch) diff --git a/templates/repo/issue/view_content/comments.tmpl b/templates/repo/issue/view_content/comments.tmpl index b971c6b1ae..cfacde9648 100644 --- a/templates/repo/issue/view_content/comments.tmpl +++ b/templates/repo/issue/view_content/comments.tmpl @@ -276,6 +276,7 @@ <a class="author" href="{{.Poster.HomeLink}}">{{.Poster.GetDisplayName}}</a> {{$.i18n.Tr "repo.issues.stop_tracking_history" $createdStr | Safe}} </span> + {{ template "repo/issue/view_content/comments_delete_time" Dict "ctx" $ "comment" . }} <div class="detail"> {{svg "octicon-clock"}} <span class="text grey">{{.Content}}</span> @@ -291,6 +292,7 @@ <a class="author" href="{{.Poster.HomeLink}}">{{.Poster.GetDisplayName}}</a> {{$.i18n.Tr "repo.issues.add_time_history" $createdStr | Safe}} </span> + {{ template "repo/issue/view_content/comments_delete_time" Dict "ctx" $ "comment" . }} <div class="detail"> {{svg "octicon-clock"}} <span class="text grey">{{.Content}}</span> diff --git a/templates/repo/issue/view_content/comments_delete_time.tmpl b/templates/repo/issue/view_content/comments_delete_time.tmpl new file mode 100644 index 0000000000..a28d222f86 --- /dev/null +++ b/templates/repo/issue/view_content/comments_delete_time.tmpl @@ -0,0 +1,21 @@ +{{ if .comment.Time }} {{/* compatibility with time comments made before v1.14 */}} + {{ if (not .comment.Time.Deleted) }} + {{ if (or .ctx.IsAdmin (and .ctx.IsSigned (eq .ctx.SignedUserID .comment.PosterID))) }} + <span class="ui float right"> + <div class="ui mini modal issue-delete-time-modal" data-id="{{.comment.Time.ID}}"> + <form method="POST" class="delete-time-form" action="{{.ctx.RepoLink}}/issues/{{.ctx.Issue.Index}}/times/{{.comment.TimeID}}/delete"> + {{.ctx.CsrfTokenHtml}} + </form> + <div class="header">{{.ctx.i18n.Tr "repo.issues.del_time"}}</div> + <div class="actions"> + <div class="ui red approve button">{{.ctx.i18n.Tr "repo.issues.context.delete"}}</div> + <div class="ui cancel button">{{.ctx.i18n.Tr "repo.issues.add_time_cancel"}}</div> + </div> + </div> + <button class="ui icon button compact mini issue-delete-time poping up" data-id="{{.comment.Time.ID}}" data-content="{{.ctx.i18n.Tr "repo.issues.del_time"}}" data-position="top right" data-variation="tiny inverted"> + {{svg "octicon-trashcan"}} + </button> + </span> + {{end}} + {{end}} +{{end}} diff --git a/templates/repo/issue/view_content/sidebar.tmpl b/templates/repo/issue/view_content/sidebar.tmpl index 3a21a9271b..9df7d7ed44 100644 --- a/templates/repo/issue/view_content/sidebar.tmpl +++ b/templates/repo/issue/view_content/sidebar.tmpl @@ -348,7 +348,7 @@ {{end}} <div class="ui buttons two fluid"> <button class="ui button poping up issue-start-time" data-content='{{.i18n.Tr "repo.issues.start_tracking"}}' data-position="top center" data-variation="small inverted">{{.i18n.Tr "repo.issues.start_tracking_short"}}</button> - <div class="ui mini modal"> + <div class="ui mini modal issue-start-time-modal"> <div class="header">{{.i18n.Tr "repo.issues.add_time"}}</div> <div class="content"> <form method="POST" id="add_time_manual_form" action="{{$.RepoLink}}/issues/{{.Issue.Index}}/times/add" class="ui action input fluid"> diff --git a/web_src/js/index.js b/web_src/js/index.js index c67b3c809b..848c88bb1f 100644 --- a/web_src/js/index.js +++ b/web_src/js/index.js @@ -3203,12 +3203,17 @@ function initVueApp() { function initIssueTimetracking() { $(document).on('click', '.issue-add-time', () => { - $('.mini.modal').modal({ + $('.issue-start-time-modal').modal({ duration: 200, onApprove() { $('#add_time_manual_form').trigger('submit'); } }).modal('show'); + $('.issue-start-time-modal input').on('keydown', (e) => { + if ((e.keyCode || e.key) === 13) { + $('#add_time_manual_form').trigger('submit'); + } + }); }); $(document).on('click', '.issue-start-time, .issue-stop-time', () => { $('#toggle_stopwatch_form').trigger('submit'); @@ -3216,6 +3221,15 @@ function initIssueTimetracking() { $(document).on('click', '.issue-cancel-time', () => { $('#cancel_stopwatch_form').trigger('submit'); }); + $(document).on('click', 'button.issue-delete-time', function () { + const sel = `.issue-delete-time-modal[data-id="${$(this).data('id')}"]`; + $(sel).modal({ + duration: 200, + onApprove() { + $(`${sel} form`).trigger('submit'); + } + }).modal('show'); + }); } function initFilterBranchTagDropdown(selector) { |