Compare commits
55 commits
feature/ui
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 0bc6b81c8c | |||
| a50bc46701 | |||
| 0f3e436464 | |||
| 8ca87f58d3 | |||
| e943de0425 | |||
| 2b8bfa6c93 | |||
| 75e1d5f03a | |||
| 1a2ef19c59 | |||
| 53eb6001a5 | |||
| 09966039b6 | |||
| 438f8bfcf0 | |||
| 84c39e3519 | |||
| 8ca4b1bc43 | |||
| 9a904bd48f | |||
| c7c194e5a5 | |||
| 489be8de02 | |||
| 4c6aca38f2 | |||
| 074de69878 | |||
| 47af533d9f | |||
| a32b8b2a5c | |||
| 7e65e7012e | |||
| bc4efc49b8 | |||
| b72c4de2a6 | |||
| 09227bd266 | |||
| d218f8bbe8 | |||
| 3d817cf737 | |||
| 692f41c5fb | |||
| ccda5dcc01 | |||
| eb80082733 | |||
| d0339fee45 | |||
| 2a0316008a | |||
| f3af9cb5a7 | |||
| 6f7ff56a80 | |||
| bc5aa1e45c | |||
| c9d9c0b0e7 | |||
| b7b725753f | |||
| 9fa12746ca | |||
| 390faa088b | |||
| ea03051cdc | |||
| d540272153 | |||
| 4386eef415 | |||
| 08385977cc | |||
| 8faa251b5e | |||
| a216a792ff | |||
| 24621d48fd | |||
| 9347134276 | |||
| 168cfafa93 | |||
| 907a7505a8 | |||
|
|
432e5ab9f2 | ||
|
|
760d906be9 | ||
|
|
239fe92bff | ||
|
|
edc5fb9641 | ||
|
|
80c4c07682 | ||
|
|
27711692bf | ||
|
|
d2ff1bcc80 |
20 changed files with 299 additions and 51 deletions
78
.forgejo/workflows/debian.yml
Normal file
78
.forgejo/workflows/debian.yml
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
name: Create the timetracker DEB
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
|
||||
jobs:
|
||||
Create_Packages:
|
||||
name: Create Package
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Go
|
||||
uses: https://code.forgejo.org/actions/setup-go@v5
|
||||
with:
|
||||
go-version: '1.18'
|
||||
|
||||
- name: Tidy dependencies
|
||||
run: go mod tidy
|
||||
|
||||
- name: Build
|
||||
run: go build -o timetracker cmd/main.go
|
||||
|
||||
- name: Copy necessary files
|
||||
run: |
|
||||
mkdir -p PKG_SOURCE/usr/local/bin
|
||||
mkdir -p PKG_SOURCE/var/lib/timetracker
|
||||
mkdir -p PKG_SOURCE/lib/systemd/system
|
||||
cp -Rf ./DEBIAN PKG_SOURCE/
|
||||
cp -Rf ./timetracker PKG_SOURCE/var/lib/timetracker/
|
||||
cp -Rf ./scripts/* PKG_SOURCE/var/lib/timetracker/
|
||||
cp -Rf ./systemd/* PKG_SOURCE/lib/systemd/system/
|
||||
|
||||
- name: Create Deb package
|
||||
run: |
|
||||
dpkg-deb --build PKG_SOURCE timetracker_${{github.ref_name}}.deb
|
||||
- name: Create Release
|
||||
id: create_release
|
||||
uses: actions/create-release@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.test }}
|
||||
with:
|
||||
tag_name: ${{ github.ref }}
|
||||
release_name: Release ${{ github.ref }}
|
||||
draft: false
|
||||
prerelease: false
|
||||
- name: Upload Release Asset
|
||||
id: upload-release-asset
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.test }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps
|
||||
asset_path: timetracker_${{github.ref_name}}.deb
|
||||
asset_name: timetracker_${{github.ref_name}}.deb
|
||||
asset_content_type: application/zip
|
||||
- name: Upload Artifact (für CI-Artefakt)
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: timetracker_${{github.ref_name}}.deb
|
||||
path: timetracker_${{github.ref_name}}.deb
|
||||
retention-days: 5
|
||||
token: ${{ secrets.test }}
|
||||
- name: Upload Package
|
||||
run: |
|
||||
FILE="timetracker_${{github.ref_name}}.deb"
|
||||
ORG="Ronny.Friedland"
|
||||
REPO="timetracker"
|
||||
VERSION=${{github.ref_name}}
|
||||
curl -v --header "Authorization: Bearer ${{ secrets.TEST }}" \
|
||||
--upload-file $FILE \
|
||||
"https://edp.buildth.ing/api/packages/${ORG}/generic/${REPO}/${VERSION}/${FILE}"
|
||||
23
.forgejo/workflows/openbao.yml
Normal file
23
.forgejo/workflows/openbao.yml
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
name: openbao
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "main" ]
|
||||
pull_request:
|
||||
branches: [ "main" ]
|
||||
|
||||
jobs:
|
||||
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Read Openbao secrets
|
||||
id: read-openbao-secrets
|
||||
uses: hashicorp/vault-action@v2
|
||||
with:
|
||||
url: https://vault-test.mms-at-work.de:8200
|
||||
token: ${{ secrets.VAULT_TEST_TOKEN }}
|
||||
secrets: |
|
||||
testproject/test/testproject foo | FOO
|
||||
- name: Echo secret value from Openbao
|
||||
run: echo "$FOO"
|
||||
38
.github/workflows/debian.yml
vendored
38
.github/workflows/debian.yml
vendored
|
|
@ -1,38 +0,0 @@
|
|||
name: Create the timetracker DEB
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
|
||||
jobs:
|
||||
Create_Packages:
|
||||
name: Create Package
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Build
|
||||
run: go build -o timetracker cmd/main.go
|
||||
|
||||
- name: Copy necessary files
|
||||
run: |
|
||||
mkdir -p PKG_SOURCE/usr/local/bin
|
||||
mkdir -p PKG_SOURCE/var/lib/timetracker
|
||||
mkdir -p PKG_SOURCE/lib/systemd/system
|
||||
cp -Rf ./DEBIAN PKG_SOURCE/
|
||||
cp -Rf ./timetracker PKG_SOURCE/usr/local/bin/
|
||||
cp -Rf ./systemd/* PKG_SOURCE/lib/systemd/system/
|
||||
|
||||
- name: Create Deb package
|
||||
run: |
|
||||
dpkg-deb --build PKG_SOURCE timetracker_${{github.ref_name}}.deb
|
||||
|
||||
- name: Release the Deb package
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
files: timetracker_${{github.ref_name}}.deb
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
Package: timetracker
|
||||
Version: 1.0.2
|
||||
Version: 1.2.0
|
||||
Section: misc
|
||||
Priority: optional
|
||||
Architecture: all
|
||||
|
|
|
|||
|
|
@ -5,6 +5,11 @@ set -e
|
|||
case "$1" in
|
||||
configure)
|
||||
chown -R timetracker:timetracker /var/lib/timetracker
|
||||
|
||||
chmod u+x /var/lib/timetracker/timetracker*.sh
|
||||
|
||||
update-alternatives --install /usr/local/bin/timetracker timetracker /var/lib/timetracker/timetracker-archive.sh 100
|
||||
update-alternatives --install /usr/local/bin/timetracker timetracker /var/lib/timetracker/timetracker.sh 1000
|
||||
;;
|
||||
|
||||
abort-upgrade|abort-remove|abort-deconfigure)
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ case "$1" in
|
|||
if getent group timetracker >/dev/null; then
|
||||
delgroup --system timetracker
|
||||
fi
|
||||
|
||||
update-alternatives --remove-all timetracker
|
||||
;;
|
||||
|
||||
upgrade)
|
||||
|
|
|
|||
|
|
@ -11,12 +11,21 @@ The timetracker application provides the following arguments which can be passed
|
|||
|
||||
| Property | Description |
|
||||
|---------------|----------------------------------------------------------------------------|
|
||||
| archivedata | Enables archiving timetracker status to excel archive file, default: false |
|
||||
| configpath | Defines the location of the necessary files, default: /var/lib/timetracker |
|
||||
|
||||
## Execution
|
||||
|
||||
The application is triggered by a systemd timer which triggers the application via systemd unit.
|
||||
|
||||
*Note:* Running timetracker with systemd unit uses the default property values. To change it you have use the appropriate alternative.
|
||||
|
||||
### Switch alternative
|
||||
|
||||
```shell
|
||||
update-alternatives --config timetracker
|
||||
```
|
||||
|
||||
To enable the timer you have to (requires root privileges):
|
||||
|
||||
### enable the timer
|
||||
|
|
|
|||
11
cmd/main.go
11
cmd/main.go
|
|
@ -7,27 +7,28 @@ import (
|
|||
)
|
||||
|
||||
func main() {
|
||||
mode, configPath := parseArguments()
|
||||
mode, configPath, archiveData := parseArguments()
|
||||
if mode == "" {
|
||||
os.Exit(0)
|
||||
} else if mode == "cli" {
|
||||
cli.Run(&configPath)
|
||||
cli.Run(&configPath, &archiveData)
|
||||
os.Exit(0)
|
||||
} else {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func parseArguments() (string, string) {
|
||||
func parseArguments() (string, string, bool) {
|
||||
mode := flag.String("mode", "cli", "the application mode, available: cli")
|
||||
configPath := flag.String("configpath", "/var/lib/timetracker", "the config path")
|
||||
archiveData := flag.Bool("archivedata", false, "flag to enable data archiving")
|
||||
help := flag.Bool("help", false, "print this help message")
|
||||
flag.Parse()
|
||||
|
||||
if *help {
|
||||
flag.PrintDefaults()
|
||||
return "", ""
|
||||
return "", "", false
|
||||
} else {
|
||||
return *mode, *configPath
|
||||
return *mode, *configPath, *archiveData
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,18 +11,21 @@ func TestParameter(t *testing.T) {
|
|||
oldArgs := os.Args
|
||||
defer func() { os.Args = oldArgs }()
|
||||
|
||||
params := []string{"-configpath", "/foo", "-mode", "testmode"}
|
||||
params := []string{"-mode", "testmode", "-configpath", "/foo", "-archivedata", "true"}
|
||||
|
||||
flag.CommandLine = flag.NewFlagSet("test", flag.ContinueOnError)
|
||||
os.Args = append([]string{"params"}, params...)
|
||||
|
||||
mode, configPath := parseArguments()
|
||||
mode, configPath, archiveData := parseArguments()
|
||||
if mode != "testmode" {
|
||||
log.Fatalf("Got unexpected mode result, got %s, expected %s", "testmode", mode)
|
||||
}
|
||||
if configPath != "/foo" {
|
||||
log.Fatalf("Got unexpected config path result, got %s, expected %s", "/foo", configPath)
|
||||
}
|
||||
if !archiveData {
|
||||
log.Fatalf("Got unexpected archive data flag result, got %t, expected %t", true, archiveData)
|
||||
}
|
||||
}
|
||||
|
||||
func TestParameterDefaults(t *testing.T) {
|
||||
|
|
@ -34,13 +37,16 @@ func TestParameterDefaults(t *testing.T) {
|
|||
flag.CommandLine = flag.NewFlagSet("test", flag.ContinueOnError)
|
||||
os.Args = append([]string{"defaults"}, params...)
|
||||
|
||||
mode, configPath := parseArguments()
|
||||
mode, configPath, archiveData := parseArguments()
|
||||
if mode != "cli" {
|
||||
log.Fatalf("Got unexpected mode result, got %s, expected %s", "cli", mode)
|
||||
}
|
||||
if configPath != "/var/lib/timetracker" {
|
||||
log.Fatalf("Got unexpected config path result, got %s, expected %s", "/var/lib/timetracker", configPath)
|
||||
}
|
||||
if archiveData {
|
||||
log.Fatalf("Got unexpected archive data flag result, got %t, expected %t", false, archiveData)
|
||||
}
|
||||
}
|
||||
|
||||
func TestParameterHelp(t *testing.T) {
|
||||
|
|
@ -52,11 +58,14 @@ func TestParameterHelp(t *testing.T) {
|
|||
flag.CommandLine = flag.NewFlagSet("test", flag.ContinueOnError)
|
||||
os.Args = append([]string{"help"}, params...)
|
||||
|
||||
mode, configPath := parseArguments()
|
||||
mode, configPath, archiveData := parseArguments()
|
||||
if mode != "" {
|
||||
log.Fatalf("Got unexpected mode result, got %s, expected %s", "", mode)
|
||||
}
|
||||
if configPath != "" {
|
||||
log.Fatalf("Got unexpected config path result, got %s, expected %s", "", configPath)
|
||||
}
|
||||
if archiveData {
|
||||
log.Fatalf("Got unexpected archive data flag result, got %t, expected %t", false, archiveData)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
13
go.mod
13
go.mod
|
|
@ -1,3 +1,16 @@
|
|||
module ronnyfriedland/timetracker/v2
|
||||
|
||||
go 1.18
|
||||
|
||||
require github.com/xuri/excelize/v2 v2.9.0
|
||||
|
||||
require (
|
||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
|
||||
github.com/richardlehane/mscfb v1.0.4 // indirect
|
||||
github.com/richardlehane/msoleps v1.0.4 // indirect
|
||||
github.com/xuri/efp v0.0.0-20250227110027-3491fafc2b79 // indirect
|
||||
github.com/xuri/nfp v0.0.0-20250226145837-86d5fc24b2ba // indirect
|
||||
golang.org/x/crypto v0.36.0 // indirect
|
||||
golang.org/x/net v0.37.0 // indirect
|
||||
golang.org/x/text v0.23.0 // indirect
|
||||
)
|
||||
|
|
|
|||
24
go.sum
24
go.sum
|
|
@ -0,0 +1,24 @@
|
|||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
|
||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/richardlehane/mscfb v1.0.4 h1:WULscsljNPConisD5hR0+OyZjwK46Pfyr6mPu5ZawpM=
|
||||
github.com/richardlehane/mscfb v1.0.4/go.mod h1:YzVpcZg9czvAuhk9T+a3avCpcFPMUWm7gK3DypaEsUk=
|
||||
github.com/richardlehane/msoleps v1.0.1/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
|
||||
github.com/richardlehane/msoleps v1.0.4 h1:WuESlvhX3gH2IHcd8UqyCuFY5yiq/GR/yqaSM/9/g00=
|
||||
github.com/richardlehane/msoleps v1.0.4/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/xuri/efp v0.0.0-20250227110027-3491fafc2b79 h1:78nKszZqigiBRBVcoe/AuPzyLTWW5B+ltBaUX1rlIXA=
|
||||
github.com/xuri/efp v0.0.0-20250227110027-3491fafc2b79/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI=
|
||||
github.com/xuri/excelize/v2 v2.9.0 h1:1tgOaEq92IOEumR1/JfYS/eR0KHOCsRv/rYXXh6YJQE=
|
||||
github.com/xuri/excelize/v2 v2.9.0/go.mod h1:uqey4QBZ9gdMeWApPLdhm9x+9o2lq4iVmjiLfBS5hdE=
|
||||
github.com/xuri/nfp v0.0.0-20250226145837-86d5fc24b2ba h1:DhIu6n3qU0joqG9f4IO6a/Gkerd+flXrmlJ+0yX2W8U=
|
||||
github.com/xuri/nfp v0.0.0-20250226145837-86d5fc24b2ba/go.mod h1:WwHg+CVyzlv/TX9xqBFXEZAuxOPxn2k1GNHwG41IIUQ=
|
||||
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
|
||||
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
|
||||
golang.org/x/image v0.18.0 h1:jGzIakQa/ZXI1I0Fxvaa9W7yP25TqT6cHIHn+6CqvSQ=
|
||||
golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c=
|
||||
golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
|
||||
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
|
||||
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
|
|
@ -2,14 +2,17 @@ package cli
|
|||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"ronnyfriedland/timetracker/v2/internal/excel"
|
||||
"ronnyfriedland/timetracker/v2/internal/logic"
|
||||
)
|
||||
|
||||
const dateLayout = "02.01.2006"
|
||||
const timeLayout = "15:04:05"
|
||||
|
||||
func Run(configPath *string) {
|
||||
func Run(configPath *string, archiveData *bool) {
|
||||
duration := logic.Execute(configPath)
|
||||
|
||||
if duration.Complete {
|
||||
log.Printf("[%s] - Work duration: %2.2fh",
|
||||
duration.Date.Format(dateLayout),
|
||||
|
|
@ -20,5 +23,8 @@ func Run(configPath *string) {
|
|||
duration.StartTime.Format(timeLayout),
|
||||
duration.EndTime.Format(timeLayout))
|
||||
|
||||
if *archiveData {
|
||||
excel.Export(configPath, duration)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,8 +16,9 @@ func TestRunNotComplete(t *testing.T) {
|
|||
log.SetOutput(&logContent)
|
||||
|
||||
directory, _ := createStatusFile()
|
||||
archiveData := false
|
||||
|
||||
Run(&directory)
|
||||
Run(&directory, &archiveData)
|
||||
|
||||
if logContent.String() != "" {
|
||||
log.Fatalf("Expected empty logmessage")
|
||||
|
|
@ -31,10 +32,11 @@ func TestRunComplete(t *testing.T) {
|
|||
log.SetOutput(&logContent)
|
||||
|
||||
directory, fileName := createStatusFile()
|
||||
archiveData := false
|
||||
|
||||
setModificationDate(fileName, "28.02.2022")
|
||||
|
||||
Run(&directory)
|
||||
Run(&directory, &archiveData)
|
||||
|
||||
if logContent.String() == "" {
|
||||
log.Fatalf("Expected logmessage")
|
||||
|
|
|
|||
61
internal/excel/excel.go
Normal file
61
internal/excel/excel.go
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
package excel
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/xuri/excelize/v2"
|
||||
|
||||
"ronnyfriedland/timetracker/v2/internal/logic"
|
||||
)
|
||||
|
||||
var SheetName = time.Now().Format("2006")
|
||||
var Headers = []string{"Date", "From", "To", "Duration"}
|
||||
|
||||
const dateLayout = "02.01.2006"
|
||||
const timeLayout = "15:04:05"
|
||||
|
||||
func Export(configPath *string, duration logic.Duration) string {
|
||||
archiveDataFile := *configPath + "/timetracker.xlsx"
|
||||
|
||||
file, err := excelize.OpenFile(archiveDataFile)
|
||||
if err != nil {
|
||||
file = excelize.NewFile()
|
||||
}
|
||||
defer func() {
|
||||
err := file.Close()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}()
|
||||
|
||||
_, err = file.NewSheet(SheetName)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to ensure sheet created: %v", err)
|
||||
}
|
||||
file.DeleteSheet("Sheet1")
|
||||
|
||||
for i, header := range Headers {
|
||||
file.SetCellValue(SheetName, fmt.Sprintf("%s%d", string(rune(65+i)), 1), header)
|
||||
}
|
||||
|
||||
rows, err := file.GetRows(SheetName)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to get rows from sheet: %v", err)
|
||||
}
|
||||
|
||||
next := len(rows) + 1
|
||||
|
||||
file.SetCellValue(SheetName, fmt.Sprintf("A%d", next), duration.Date.Format(dateLayout))
|
||||
file.SetCellValue(SheetName, fmt.Sprintf("B%d", next), duration.StartTime.Format(timeLayout))
|
||||
file.SetCellValue(SheetName, fmt.Sprintf("C%d", next), duration.EndTime.Format(timeLayout))
|
||||
file.SetCellValue(SheetName, fmt.Sprintf("D%d", next), fmt.Sprintf("%2.2f", duration.Duration.Hours()))
|
||||
|
||||
if err := file.SaveAs(archiveDataFile);
|
||||
err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
return archiveDataFile
|
||||
}
|
||||
47
internal/excel/excel_test.go
Normal file
47
internal/excel/excel_test.go
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
package excel
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"ronnyfriedland/timetracker/v2/internal/logic"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/xuri/excelize/v2"
|
||||
)
|
||||
|
||||
func TestExport(t *testing.T) {
|
||||
|
||||
testData := logic.Duration{
|
||||
Date: time.Now(),
|
||||
StartTime: time.Now(),
|
||||
EndTime: time.Now(),
|
||||
Duration: time.Duration(1000),
|
||||
}
|
||||
|
||||
excelDirectory := os.TempDir()
|
||||
excelFile := Export(&excelDirectory, testData)
|
||||
|
||||
file, err := excelize.OpenFile(excelFile)
|
||||
if err != nil {
|
||||
log.Fatalf("Expected excel file")
|
||||
}
|
||||
|
||||
rows, err := file.GetRows(SheetName)
|
||||
if err != nil {
|
||||
log.Fatalf("Expected no error getting rows")
|
||||
}
|
||||
|
||||
if len(rows) != 2 {
|
||||
log.Fatalf("Unexpected line count - expected 2, got %d", len(rows))
|
||||
}
|
||||
|
||||
headers := rows[0]
|
||||
for i := 0; i < len(headers); i++ {
|
||||
if headers[i] != Headers[i] {
|
||||
log.Fatalf("Unexpected header value - expected %s, got %s", Headers[i], headers[i])
|
||||
}
|
||||
}
|
||||
|
||||
defer os.Remove(excelFile)
|
||||
}
|
||||
3
scripts/timetracker-archive.sh
Normal file
3
scripts/timetracker-archive.sh
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
/var/lib/timetracker/timetracker -archivedata=true
|
||||
3
scripts/timetracker.sh
Normal file
3
scripts/timetracker.sh
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
/var/lib/timetracker/timetracker
|
||||
Loading…
Add table
Add a link
Reference in a new issue