forgejo-federation/routers/web/repo/issue_stopwatch.go
zeripath ae446b13f9
Stop spurious APIFormat stopwatches logs (#20008)
If there are dangling stopwatches with missing issues there will be repeated
logging of Unable to APIFormat stopwatches. These are unhelpful and instead
we should only log if the error is not an issue not exist error.

And we should also prevent an error on missing issue in GetActiveStopwatch too

Signed-off-by: Andrew Thornton <art27@cantab.net>
2022-06-17 22:47:15 +01:00

126 lines
2.8 KiB
Go

// Copyright 2017 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 repo
import (
"net/http"
"strings"
"code.gitea.io/gitea/models/db"
issues_model "code.gitea.io/gitea/models/issues"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/eventsource"
)
// IssueStopwatch creates or stops a stopwatch for the given issue.
func IssueStopwatch(c *context.Context) {
issue := GetActionIssue(c)
if c.Written() {
return
}
var showSuccessMessage bool
if !issues_model.StopwatchExists(c.Doer.ID, issue.ID) {
showSuccessMessage = true
}
if !c.Repo.CanUseTimetracker(issue, c.Doer) {
c.NotFound("CanUseTimetracker", nil)
return
}
if err := issues_model.CreateOrStopIssueStopwatch(c.Doer, issue); err != nil {
c.ServerError("CreateOrStopIssueStopwatch", err)
return
}
if showSuccessMessage {
c.Flash.Success(c.Tr("repo.issues.tracker_auto_close"))
}
url := issue.HTMLURL()
c.Redirect(url, http.StatusSeeOther)
}
// CancelStopwatch cancel the stopwatch
func CancelStopwatch(c *context.Context) {
issue := GetActionIssue(c)
if c.Written() {
return
}
if !c.Repo.CanUseTimetracker(issue, c.Doer) {
c.NotFound("CanUseTimetracker", nil)
return
}
if err := issues_model.CancelStopwatch(c.Doer, issue); err != nil {
c.ServerError("CancelStopwatch", err)
return
}
stopwatches, err := issues_model.GetUserStopwatches(c.Doer.ID, db.ListOptions{})
if err != nil {
c.ServerError("GetUserStopwatches", err)
return
}
if len(stopwatches) == 0 {
eventsource.GetManager().SendMessage(c.Doer.ID, &eventsource.Event{
Name: "stopwatches",
Data: "{}",
})
}
url := issue.HTMLURL()
c.Redirect(url, http.StatusSeeOther)
}
// GetActiveStopwatch is the middleware that sets .ActiveStopwatch on context
func GetActiveStopwatch(ctx *context.Context) {
if strings.HasPrefix(ctx.Req.URL.Path, "/api") {
return
}
if !ctx.IsSigned {
return
}
_, sw, err := issues_model.HasUserStopwatch(ctx, ctx.Doer.ID)
if err != nil {
ctx.ServerError("HasUserStopwatch", err)
return
}
if sw == nil || sw.ID == 0 {
return
}
issue, err := issues_model.GetIssueByID(ctx, sw.IssueID)
if err != nil || issue == nil {
if !issues_model.IsErrIssueNotExist(err) {
ctx.ServerError("GetIssueByID", err)
}
return
}
if err = issue.LoadRepo(ctx); err != nil {
ctx.ServerError("LoadRepo", err)
return
}
ctx.Data["ActiveStopwatch"] = StopwatchTmplInfo{
issue.Link(),
issue.Repo.FullName(),
issue.Index,
sw.Seconds() + 1, // ensure time is never zero in ui
}
}
// StopwatchTmplInfo is a view on a stopwatch specifically for template rendering
type StopwatchTmplInfo struct {
IssueLink string
RepoSlug string
IssueIndex int64
Seconds int64
}