code.gitea.io/gitea@v1.21.7/routers/web/repo/issue_stopwatch.go (about)

     1  // Copyright 2017 The Gitea Authors. All rights reserved.
     2  // SPDX-License-Identifier: MIT
     3  
     4  package repo
     5  
     6  import (
     7  	"net/http"
     8  	"strings"
     9  
    10  	"code.gitea.io/gitea/models/db"
    11  	issues_model "code.gitea.io/gitea/models/issues"
    12  	"code.gitea.io/gitea/modules/context"
    13  	"code.gitea.io/gitea/modules/eventsource"
    14  )
    15  
    16  // IssueStopwatch creates or stops a stopwatch for the given issue.
    17  func IssueStopwatch(c *context.Context) {
    18  	issue := GetActionIssue(c)
    19  	if c.Written() {
    20  		return
    21  	}
    22  
    23  	var showSuccessMessage bool
    24  
    25  	if !issues_model.StopwatchExists(c, c.Doer.ID, issue.ID) {
    26  		showSuccessMessage = true
    27  	}
    28  
    29  	if !c.Repo.CanUseTimetracker(issue, c.Doer) {
    30  		c.NotFound("CanUseTimetracker", nil)
    31  		return
    32  	}
    33  
    34  	if err := issues_model.CreateOrStopIssueStopwatch(c, c.Doer, issue); err != nil {
    35  		c.ServerError("CreateOrStopIssueStopwatch", err)
    36  		return
    37  	}
    38  
    39  	if showSuccessMessage {
    40  		c.Flash.Success(c.Tr("repo.issues.tracker_auto_close"))
    41  	}
    42  
    43  	url := issue.Link()
    44  	c.Redirect(url, http.StatusSeeOther)
    45  }
    46  
    47  // CancelStopwatch cancel the stopwatch
    48  func CancelStopwatch(c *context.Context) {
    49  	issue := GetActionIssue(c)
    50  	if c.Written() {
    51  		return
    52  	}
    53  	if !c.Repo.CanUseTimetracker(issue, c.Doer) {
    54  		c.NotFound("CanUseTimetracker", nil)
    55  		return
    56  	}
    57  
    58  	if err := issues_model.CancelStopwatch(c, c.Doer, issue); err != nil {
    59  		c.ServerError("CancelStopwatch", err)
    60  		return
    61  	}
    62  
    63  	stopwatches, err := issues_model.GetUserStopwatches(c, c.Doer.ID, db.ListOptions{})
    64  	if err != nil {
    65  		c.ServerError("GetUserStopwatches", err)
    66  		return
    67  	}
    68  	if len(stopwatches) == 0 {
    69  		eventsource.GetManager().SendMessage(c.Doer.ID, &eventsource.Event{
    70  			Name: "stopwatches",
    71  			Data: "{}",
    72  		})
    73  	}
    74  
    75  	url := issue.Link()
    76  	c.Redirect(url, http.StatusSeeOther)
    77  }
    78  
    79  // GetActiveStopwatch is the middleware that sets .ActiveStopwatch on context
    80  func GetActiveStopwatch(ctx *context.Context) {
    81  	if strings.HasPrefix(ctx.Req.URL.Path, "/api") {
    82  		return
    83  	}
    84  
    85  	if !ctx.IsSigned {
    86  		return
    87  	}
    88  
    89  	_, sw, issue, err := issues_model.HasUserStopwatch(ctx, ctx.Doer.ID)
    90  	if err != nil {
    91  		ctx.ServerError("HasUserStopwatch", err)
    92  		return
    93  	}
    94  
    95  	if sw == nil || sw.ID == 0 {
    96  		return
    97  	}
    98  
    99  	ctx.Data["ActiveStopwatch"] = StopwatchTmplInfo{
   100  		issue.Link(),
   101  		issue.Repo.FullName(),
   102  		issue.Index,
   103  		sw.Seconds() + 1, // ensure time is never zero in ui
   104  	}
   105  }
   106  
   107  // StopwatchTmplInfo is a view on a stopwatch specifically for template rendering
   108  type StopwatchTmplInfo struct {
   109  	IssueLink  string
   110  	RepoSlug   string
   111  	IssueIndex int64
   112  	Seconds    int64
   113  }