Skip to content

Commit

Permalink
reports
Browse files Browse the repository at this point in the history
  • Loading branch information
mattkasun committed Dec 6, 2023
1 parent 1512011 commit 94b5f38
Show file tree
Hide file tree
Showing 9 changed files with 224 additions and 41 deletions.
7 changes: 3 additions & 4 deletions database/record.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package database

import (
"encoding/json"
"slices"
"time"

"github.com/devilcove/timetraced/models"
Expand Down Expand Up @@ -128,7 +127,7 @@ func GetTodaysRecordsForUser(user string) ([]models.Record, error) {
return records, nil
}

func GetReportRecords(req models.ReportRequest) ([]models.Record, error) {
func GetReportRecords(req models.DatabaseReportRequest) ([]models.Record, error) {
records := []models.Record{}
record := models.Record{}
start := truncateToStart(req.Start)
Expand All @@ -139,8 +138,8 @@ func GetReportRecords(req models.ReportRequest) ([]models.Record, error) {
if err := json.Unmarshal(v, &record); err != nil {
return err
}
if slices.Contains(req.Users, record.User) &&
slices.Contains(req.Projects, record.Project) &&
if (req.User == record.User) &&
(req.Project == record.Project) &&
record.Start.After(start) &&
record.Start.Before(end) {
if record.End.IsZero() {
Expand Down
69 changes: 58 additions & 11 deletions html/report.html
Original file line number Diff line number Diff line change
@@ -1,14 +1,61 @@
{{define "report"}}
<div class="w3-container w3-center" id="content">
<h1>This is the report page</h1>
<p>Report Page 1</p>
<p>Line 1</p>
<p>Line 2</p>
<p>Line 3</p>
<p>Line 4</p>
<p>Line 5</p>
<br>
<br>
<br>
<h1>Reports</h1>
<div class="w3-row">
<div class="w3-third"><br></div>
<div class="w3-third">
<form class="w3-container" hx-post="/reports" hx-target="#content">
<p><label>Start Date</label></p>
<p><input type="date" name="start" value="{{.DefaultDate}}" required></p>
<p><label>End Date</label></p>
<p><input type="date" name="end" value="{{.DefaultDate}}" required></p>
<p><label>Limit to Project</label></p>
<p><select class="w3-select" name="project">
<option value=""></option>
{{range .Projects}}
<option value="{{.}}">{{.}}</option>
{{end}}
</select></p>
<p><button class="w3-button w3-theme-dark w3-padding large" type="button" hx-get="/"
hx-target="#main">Cancel</button>
<button class="w3-button w3-theme-dark w3-padding large" type="submit">Submit</button>
</p>
</form>
</div>
</div>
{{end}}

{{define "results"}}
<h1>TimeTrace Report</h1>
{{range .}}
<h2>Project {{.Project}}</h2>
{{range .Items}}
<button hx-get="/records/{{ .ID }}" hx-target="#content" type="button">
{{.Start.Format "Jan 02, 2006 15:04"}} &nbsp; {{.End.Format "Jan 02, 2006 15:04"}}
</button><br>
{{end}}
<h2>{{.Total}}</h2>
{{end}}
{{end}}

{{define "editRecord"}}
<h1>Edit Record</h1>
<div class="w3-row">
<div class="w3-third"><br></div>
<div class="w3-third">
<form action="/records/{{ .ID }}" method="post">
<input type="hidden" name="ID" value="{{.ID}}">
<label>Start</label>
<input class="w3-input" type="date" name="Start" value='{{.Start.Format "2006-01-02"}}'>
<input class="w3-input" type="time" name="StartTime" value='{{.Start.Format "15:04"}}'>
<label>End</label>
<input class="w3-input" type="date" name="End" value='{{.End.Format "2006-01-02"}}'>
<input class="w3-input" type="time" name="EndTime" value='{{.End.Format "15:04"}}'>

<p><button class="w3-button w3-theme-dark w3-padding-large" type="button" hx-get="/"
hx-target="#main">Cancel</button>
<button class="w3-button w3-theme-dark w3-padding-large" type="submit">Submit</button>
</p>
</form>
</div>
</div>
{{end}}
25 changes: 14 additions & 11 deletions models/page.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,30 @@ package models

import (
"log"
"time"
)

type Page struct {
Page string
Version string
Theme string
Font string
Tracking bool
Projects []string
Status StatusResponse
Page string
Version string
Theme string
Font string
Tracking bool
Projects []string
Status StatusResponse
DefaultDate string
}

// var page Page
var pages map[string]Page

func initialize() Page {
return Page{
Page: "login",
Version: "v0.1.0",
Theme: "indigo",
Font: "Roboto",
Page: "login",
Version: "v0.1.0",
Theme: "indigo",
Font: "Roboto",
DefaultDate: time.Now().Local().Format("2006-01-02"),
}
}
func init() {
Expand Down
8 changes: 8 additions & 0 deletions models/record.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,14 @@ type Record struct {
End time.Time
}

type EditRecord struct {
ID string
Start string
StartTime string
End string
EndTime string
}

type Durations map[string]string

type Duration struct {
Expand Down
23 changes: 17 additions & 6 deletions models/reports.go
Original file line number Diff line number Diff line change
@@ -1,21 +1,32 @@
package models

import "time"
import (
"time"

"github.com/google/uuid"
)

type Report struct {
Project string
Total time.Duration
Total string
Items []ReportRecord
}

type ReportRecord struct {
ID uuid.UUID
Start time.Time
End time.Time
}

type ReportRequest struct {
Start time.Time
End time.Time
Projects []string
Users []string
Start string `form:"start"`
End string `form:"end"`
Project string `form:"project"`
}

type DatabaseReportRequest struct {
Start time.Time
End time.Time
Project string
User string
}
50 changes: 50 additions & 0 deletions records.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
package main

import (
"net/http"
"net/url"
"time"

"github.com/devilcove/timetraced/database"
"github.com/devilcove/timetraced/models"
"github.com/gin-gonic/gin"
"github.com/google/uuid"
)

func getStatus(user string) (models.StatusResponse, error) {
Expand Down Expand Up @@ -41,3 +45,49 @@ func getStatus(user string) (models.StatusResponse, error) {
}
return response, nil
}

func getRecord(c *gin.Context) {
id, err := uuid.Parse(c.Param("id"))
if err != nil {
processError(c, 100, err.Error())
}
record, err := database.GetRecord(id)
if err != nil {
processError(c, 100, err.Error())
}
c.HTML(http.StatusOK, "editRecord", record)
}

func editRecord(c *gin.Context) {
var err error
edit := models.EditRecord{}
if err := c.Bind(&edit); err != nil {
processError(c, 100, err.Error())
return
}
record, err := database.GetRecord(uuid.MustParse(edit.ID))
if err != nil {
processError(c, 200, err.Error())
return
}
if err := c.Bind(&edit); err != nil {
processError(c, 300, err.Error())
return
}
record.End, err = time.Parse("2006-01-0215:04", edit.End+edit.EndTime)
if err != nil {
processError(c, 400, err.Error())
return
}
record.Start, err = time.Parse("2006-01-0215:04", edit.Start+edit.StartTime)
if err != nil {
processError(c, 500, err.Error())
return
}
if err := database.SaveRecord(&record); err != nil {
processError(c, 600, err.Error())
return
}
location := url.URL{Path: "/"}
c.Redirect(http.StatusFound, location.RequestURI())
}
76 changes: 68 additions & 8 deletions reports.go
Original file line number Diff line number Diff line change
@@ -1,32 +1,92 @@
package main

import (
"log/slog"
"net/http"
"sort"
"time"

"github.com/devilcove/timetraced/database"
"github.com/devilcove/timetraced/models"
"github.com/gin-contrib/sessions"
"github.com/gin-gonic/gin"
)

func getReport(c *gin.Context) {
var err error
projectsToQuery := []string{}
session := sessions.Default(c)
dbRequest := models.DatabaseReportRequest{
User: session.Get("user").(string),
}
reportRequest := models.ReportRequest{}
if err := c.BindJSON(&reportRequest); err != nil {
if err := c.Bind(&reportRequest); err != nil {
processError(c, http.StatusBadRequest, "could not decode request")
return
}
reportData, err := database.GetReportRecords(reportRequest)
dbRequest.Start, err = time.Parse("2006-01-02", reportRequest.Start)
if err != nil {
processError(c, http.StatusInternalServerError, err.Error())
return
}
dbRequest.End, err = time.Parse("2006-01-02", reportRequest.End)
if err != nil {
processError(c, http.StatusInternalServerError, err.Error())
return
}
sort.Slice(reportData, func(i, j int) bool {
return reportData[i].Project < reportData[j].Project
})
c.JSON(http.StatusOK, reportData)
if reportRequest.Project == "" {
allProjects, err := database.GetAllProjects()
if err != nil {
processError(c, http.StatusInternalServerError, err.Error())
return
}
for _, project := range allProjects {
projectsToQuery = append(projectsToQuery, project.Name)
}
} else {
projectsToQuery = append(projectsToQuery, reportRequest.Project)
}
displayRecords := []models.Report{}
for _, project := range projectsToQuery {
displayRecord := models.Report{}
reportRecord := models.ReportRecord{}
reportRecords := []models.ReportRecord{}
dbRequest.Project = project
data, err := database.GetReportRecords(dbRequest)
if err != nil {
processError(c, http.StatusInternalServerError, err.Error())
return
}
var total time.Duration
for _, d := range data {
total = d.End.Sub(d.Start)
reportRecord.End = d.End
reportRecord.Start = d.Start
reportRecord.ID = d.ID
reportRecords = append(reportRecords, reportRecord)
}
if total != 0 {
displayRecord.Project = project
displayRecord.Total = models.FmtDuration(total)
displayRecord.Items = reportRecords
displayRecords = append(displayRecords, displayRecord)
}
}
c.HTML(http.StatusOK, "results", displayRecords)

}

func report(c *gin.Context) {
c.HTML(http.StatusOK, "report", "")
session := sessions.Default(c)
user := session.Get("user").(string)
page := models.GetUserPage(user)
populate(&page, user)
projects, err := database.GetAllProjects()
if err != nil {
slog.Error(err.Error())
} else {
for _, project := range projects {
page.Projects = append(page.Projects, project.Name)
}
}
c.HTML(http.StatusOK, "report", page)
}
5 changes: 5 additions & 0 deletions router.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,11 @@ func setupRouter() *gin.Engine {
reports.GET("/", report)
reports.POST("/", getReport)
}
records := router.Group("records", auth)
{
records.GET("/:id", getRecord)
records.POST("/:id", editRecord)
}
return router
}

Expand Down
2 changes: 1 addition & 1 deletion users.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func login(c *gin.Context) {
session.Set("loggedin", true)
session.Set("user", user.Username)
session.Set("admin", user.IsAdmin)
session.Options(sessions.Options{MaxAge: SessionAge, Secure: true, SameSite: http.SameSiteLaxMode})
session.Options(sessions.Options{MaxAge: SessionAge, Secure: false, SameSite: http.SameSiteLaxMode})
session.Save()
user.Password = ""
slog.Info("login", "user", user.Username)
Expand Down

0 comments on commit 94b5f38

Please sign in to comment.