Skip to content

Commit ee611d8

Browse files
committed
first version
1 parent 73eb549 commit ee611d8

28 files changed

+542
-15
lines changed

.github/workflows/go.yml

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# This workflow will build a golang project
2+
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-go
3+
4+
name: Go
5+
6+
on:
7+
push:
8+
tags:
9+
- 'v*' # z.B. v1.2.3
10+
11+
jobs:
12+
13+
build:
14+
permissions:
15+
contents: write
16+
runs-on: ubuntu-latest
17+
steps:
18+
- uses: actions/checkout@v4
19+
20+
- name: Set up Go
21+
uses: actions/setup-go@v4
22+
with:
23+
go-version: '1.24'
24+
25+
- name: Extract version info
26+
id: vars
27+
run: |
28+
VERSION=${GITHUB_REF#refs/tags/}
29+
COMMIT=$(git rev-parse --short HEAD)
30+
BUILD_TIME=$(date -u +%Y-%m-%dT%H:%M:%SZ)
31+
echo "version=$VERSION" >> $GITHUB_OUTPUT
32+
echo "commit=$COMMIT" >> $GITHUB_OUTPUT
33+
echo "build_time=$BUILD_TIME" >> $GITHUB_OUTPUT
34+
35+
- name: Build
36+
run: |
37+
mkdir -p dist
38+
GOOS=windows GOARCH=amd64 go build \
39+
-ldflags="-s -w \
40+
-X github.com/LReg/time-tracker/internal/version.Version=${{ steps.vars.outputs.version }} \
41+
-X github.com/LReg/time-tracker/internal/version.Commit=${{ steps.vars.outputs.commit }} \
42+
-X github.com/LReg/time-tracker/internal/version.Date=${{ steps.vars.outputs.build_time }}" \
43+
-o dist/tt.exe ./cmd/time-tracker
44+
45+
- name: Create GitHub Release
46+
uses: softprops/action-gh-release@v2
47+
with:
48+
name: "Release ${{ steps.vars.outputs.version }}"
49+
tag_name: ${{ steps.vars.outputs.version }}
50+
files: |
51+
dist/tt.exe

build/build.sh

Lines changed: 0 additions & 1 deletion
This file was deleted.

build/buildARM64.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export GOOS=darwin
2+
export GOARCH=arm64
3+
go build -ldflags="-X 'github.com/LReg/time-tracker/version.Version=0.0.1' -X '../cmd/time-tracker/main.go/version.Commit=$(git rev-parse HEAD)' -X 'main.Date=$(date -u +%Y-%m-%dT%H:%M:%SZ)'" -o ../tt-arm ../cmd/time-tracker/main.go

build/buildWindows.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export GOOS=windows
2+
export GOARCH=amd64
3+
go build -ldflags="-s -w -X 'github.com/LReg/time-tracker/version.Version=0.0.1' -X '../cmd/time-tracker/main.go/version.Commit=$(git rev-parse HEAD)' -X 'main.Date=$(date -u +%Y-%m-%dT%H:%M:%SZ)'" -o ../tt.exe ../cmd/time-tracker/main.go

cmd/time-tracker/main.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,17 @@
11
package main
22

3-
import "github.com/LReg/time-tracker/internal/parse"
3+
import (
4+
"github.com/LReg/time-tracker/internal/parse"
5+
"github.com/LReg/time-tracker/internal/stormdb"
6+
)
7+
8+
var (
9+
Version = "dev"
10+
Commit = "none"
11+
Date = "unknown"
12+
)
413

514
func main() {
15+
stormdb.ConnectToDB()
616
parse.ParseArgsAndHandle()
717
}

go.mod

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
11
module github.com/LReg/time-tracker
22

33
go 1.24.3
4+
5+
require (
6+
github.com/asdine/storm/v3 v3.2.1 // indirect
7+
github.com/sirupsen/logrus v1.9.3 // indirect
8+
go.etcd.io/bbolt v1.4.1 // indirect
9+
golang.org/x/sys v0.33.0 // indirect
10+
)

go.sum

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
github.com/DataDog/zstd v1.4.1/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
2+
github.com/Sereal/Sereal v0.0.0-20190618215532-0b8ac451a863/go.mod h1:D0JMgToj/WdxCgd30Kc1UcA9E+WdZoJqeVOuYW7iTBM=
3+
github.com/asdine/storm/v3 v3.2.1 h1:I5AqhkPK6nBZ/qJXySdI7ot5BlXSZ7qvDY1zAn5ZJac=
4+
github.com/asdine/storm/v3 v3.2.1/go.mod h1:LEpXwGt4pIqrE/XcTvCnZHT5MgZCV6Ub9q7yQzOFWr0=
5+
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
6+
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
7+
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
8+
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
9+
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
10+
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
11+
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
12+
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
13+
github.com/mattn/go-sqlite3 v1.14.28 h1:ThEiQrnbtumT+QMknw63Befp/ce/nUPgBPMlRFEum7A=
14+
github.com/mattn/go-sqlite3 v1.14.28/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
15+
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
16+
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
17+
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
18+
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
19+
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
20+
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
21+
github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
22+
go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
23+
go.etcd.io/bbolt v1.4.1 h1:5mOV+HWjIPLEAlUGMsveaUvK2+byZMFOzojoi7bh7uI=
24+
go.etcd.io/bbolt v1.4.1/go.mod h1:c8zu2BnXWTu2XM4XcICtbGSl9cFwsXtcf9zLt2OncM8=
25+
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
26+
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
27+
golang.org/x/net v0.0.0-20191105084925-a882066a44e0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
28+
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
29+
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
30+
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
31+
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
32+
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
33+
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
34+
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
35+
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
36+
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
37+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
38+
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
39+
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

internal/api/api-webserver.go

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
package api
2+
3+
import (
4+
"encoding/json"
5+
"github.com/LReg/time-tracker/internal/timeslot"
6+
"github.com/LReg/time-tracker/internal/ui"
7+
"github.com/LReg/time-tracker/internal/util"
8+
log "github.com/sirupsen/logrus"
9+
"net/http"
10+
"os"
11+
"strconv"
12+
"time"
13+
)
14+
15+
func setCorsHeaders(writer http.ResponseWriter) {
16+
writer.Header().Set("Access-Control-Allow-Origin", ui.WebserverUrl)
17+
writer.Header().Set("Access-Control-Allow-Methods", "GET, OPTIONS")
18+
writer.Header().Set("Access-Control-Allow-Headers", "Content-Type")
19+
}
20+
21+
func notFound(writer http.ResponseWriter) {
22+
writer.Header().Set("Content-Type", "text/plain; charset=utf-8")
23+
writer.WriteHeader(http.StatusNotFound)
24+
writer.Write([]byte("Not Found"))
25+
}
26+
27+
func internalServerError(writer http.ResponseWriter) {
28+
writer.Header().Set("Content-Type", "text/plain; charset=utf-8")
29+
writer.WriteHeader(http.StatusInternalServerError)
30+
writer.Write([]byte("Error converting timeslot to json"))
31+
}
32+
33+
func writeJson(writer http.ResponseWriter, err error, jsonTimeslots []byte) error {
34+
writer.Header().Set("Content-Type", "application/json; charset=utf-8")
35+
_, err = writer.Write(jsonTimeslots)
36+
return err
37+
}
38+
39+
func StartTimeSlotApi() {
40+
mux := http.NewServeMux()
41+
42+
mux.HandleFunc("/quit", func(writer http.ResponseWriter, request *http.Request) {
43+
setCorsHeaders(writer)
44+
writer.Header().Set("Content-Type", "text/plain; charset=utf-8")
45+
writer.WriteHeader(http.StatusOK)
46+
_, err := writer.Write([]byte("OK"))
47+
if err != nil {
48+
log.Error("Error writing response", err)
49+
}
50+
go func() {
51+
time.Sleep(1 * time.Second)
52+
os.Exit(0)
53+
}()
54+
})
55+
56+
mux.HandleFunc("/tt/{ms}", func(writer http.ResponseWriter, request *http.Request) {
57+
from, to := parseMS(request)
58+
timeslots := timeslot.GetTimeSlotsFromTo(from, to)
59+
60+
setCorsHeaders(writer)
61+
62+
if len(timeslots) == 0 {
63+
notFound(writer)
64+
return
65+
}
66+
67+
jsonTimeslots, err := json.Marshal(timeslots)
68+
if err != nil {
69+
log.Error("Error converting timeslot to json", err)
70+
internalServerError(writer)
71+
return
72+
}
73+
74+
err = writeJson(writer, err, jsonTimeslots)
75+
if err != nil {
76+
log.Error("Error writing response", err)
77+
}
78+
})
79+
err := http.ListenAndServe(":8888", mux)
80+
if err != nil {
81+
log.Fatal("Could not start the webserver", err)
82+
}
83+
}
84+
85+
func parseMS(request *http.Request) (time.Time, time.Time) {
86+
ms := request.PathValue("ms")
87+
millis, err := strconv.ParseInt(ms, 10, 64)
88+
if err != nil {
89+
log.Error("Error converting ms to int", err)
90+
}
91+
92+
date := time.UnixMilli(millis)
93+
from := util.GetLastMidnightFrom(date)
94+
to := util.GetLastMidnightFrom(date.Add(24 * time.Hour))
95+
return from, to
96+
}

internal/history/history.go

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,28 @@
11
package history
22

33
import (
4-
"fmt"
4+
"github.com/LReg/time-tracker/internal/api"
5+
"github.com/LReg/time-tracker/internal/models"
6+
"github.com/LReg/time-tracker/internal/timeslot"
7+
"github.com/LReg/time-tracker/internal/ui"
8+
"github.com/LReg/time-tracker/internal/util"
59
"os"
10+
"time"
611
)
712

8-
func ShowHistory() {
9-
fmt.Println("Not implemented yet")
13+
func ShowHistoryAndListen() {
14+
go api.StartTimeSlotApi()
15+
ui.StartStaticWebServer()
1016
os.Exit(1)
1117
}
18+
19+
func ShowHistoryConsoleAndExit() {
20+
for _, ts := range getHistoryForTime(time.Now()) {
21+
ts.Print()
22+
}
23+
os.Exit(0)
24+
}
25+
26+
func getHistoryForTime(time time.Time) []models.TimeSlot {
27+
return timeslot.GetTimeSlotsFromTo(util.GetLastMidnightFrom(time), time)
28+
}

internal/models/timeslot.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package models
2+
3+
import (
4+
"fmt"
5+
"time"
6+
)
7+
8+
type TimeSlot struct {
9+
ID int `storm:"id,increment"`
10+
Text string
11+
MetaJson string
12+
Start time.Time `storm:"index"`
13+
End time.Time `storm:"index"`
14+
}
15+
16+
func (ts TimeSlot) Print() {
17+
const layout = "15:04:05" // Go's reference time layout
18+
19+
fmt.Println("──── TimeSlot ─────────────────────────")
20+
fmt.Printf("Text : %s\n", ts.Text)
21+
fmt.Printf("Start : %s\n", ts.Start.Format(layout))
22+
fmt.Printf("End : %s\n", ts.End.Format(layout))
23+
fmt.Println("──────────────────────────────────────")
24+
}

0 commit comments

Comments
 (0)