Compare commits
3 Commits
1.1.3
...
dd8a29acc2
| Author | SHA1 | Date | |
|---|---|---|---|
| dd8a29acc2 | |||
| 8cb63d3342 | |||
| 62c12cceba |
@@ -26,10 +26,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
# Disabling shallow clone is recommended for improving relevancy of reporting
|
# Disabling shallow clone is recommended for improving relevancy of reporting
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- name: Setup go
|
|
||||||
uses: actions/setup-go@v5
|
|
||||||
with:
|
|
||||||
go-version-file: Backend/go.mod
|
|
||||||
- uses: https://gitea.com/actions/go-hashfiles@v0.0.1
|
- uses: https://gitea.com/actions/go-hashfiles@v0.0.1
|
||||||
id: hash-go
|
id: hash-go
|
||||||
with:
|
with:
|
||||||
@@ -46,6 +43,10 @@ jobs:
|
|||||||
key: arbeitszeitmessung-${{ steps.hash-go.outputs.hash }}
|
key: arbeitszeitmessung-${{ steps.hash-go.outputs.hash }}
|
||||||
restore-keys: |-
|
restore-keys: |-
|
||||||
arbeitszeitmessung-
|
arbeitszeitmessung-
|
||||||
|
- name: Setup go
|
||||||
|
uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version-file: Backend/go.mod
|
||||||
- name: Run Go Tests
|
- name: Run Go Tests
|
||||||
run: cd Backend && mkdir .test && go test ./... -coverprofile=.test/coverage.out -json > .test/report.json
|
run: cd Backend && mkdir .test && go test ./... -coverprofile=.test/coverage.out -json > .test/report.json
|
||||||
- name: Verify coverage report exists
|
- name: Verify coverage report exists
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ func renderPDF(days []typstDay, metadata typstMetadata) (bytes.Buffer, error) {
|
|||||||
// Import the template and invoke the template function with the custom data.
|
// Import the template and invoke the template function with the custom data.
|
||||||
// Show is used to replace the current document with whatever content the template function in `template.typ` returns.
|
// Show is used to replace the current document with whatever content the template function in `template.typ` returns.
|
||||||
markup.WriteString(`
|
markup.WriteString(`
|
||||||
#import "templates/abrechnung.typ": abrechnung
|
#import "template.typ": abrechnung
|
||||||
#show: doc => abrechnung(meta, days)
|
#show: doc => abrechnung(meta, days)
|
||||||
`)
|
`)
|
||||||
|
|
||||||
@@ -84,10 +84,7 @@ func renderPDF(days []typstDay, metadata typstMetadata) (bytes.Buffer, error) {
|
|||||||
// defer f.Close()
|
// defer f.Close()
|
||||||
//
|
//
|
||||||
|
|
||||||
// typstCLI := typst.CLI{}
|
typstCLI := typst.CLI{}
|
||||||
typstCLI := typst.DockerExec{
|
|
||||||
ContainerName: helper.GetEnv("TYPST_CONTAINER", "arbeitszeitmessung-doc-creator"),
|
|
||||||
}
|
|
||||||
if err := typstCLI.Compile(&markup, &output, nil); err != nil {
|
if err := typstCLI.Compile(&markup, &output, nil); err != nil {
|
||||||
return output, err
|
return output, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ require github.com/a-h/templ v0.3.943
|
|||||||
require github.com/alexedwards/scs/v2 v2.8.0
|
require github.com/alexedwards/scs/v2 v2.8.0
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/Dadido3/go-typst v0.8.0
|
github.com/Dadido3/go-typst v0.3.0
|
||||||
github.com/golang-migrate/migrate/v4 v4.18.3
|
github.com/golang-migrate/migrate/v4 v4.18.3
|
||||||
github.com/joho/godotenv v1.5.1
|
github.com/joho/godotenv v1.5.1
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0=
|
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0=
|
||||||
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
|
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
|
||||||
github.com/Dadido3/go-typst v0.8.0 h1:uTLYprhkrBjwsCXRRuyYUFL0fpYHa2kIYoOB/CGqVNs=
|
github.com/Dadido3/go-typst v0.3.0 h1:Itix2FtQgBiOuHUNqgGUAK11Oo2WMlZGGGpCiQNK1IA=
|
||||||
github.com/Dadido3/go-typst v0.8.0/go.mod h1:QYis9sT70u65kn1SkFfyPRmHsPxgoxWbAixwfPReOZA=
|
github.com/Dadido3/go-typst v0.3.0/go.mod h1:QYis9sT70u65kn1SkFfyPRmHsPxgoxWbAixwfPReOZA=
|
||||||
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
|
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
|
||||||
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
|
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
|
||||||
github.com/a-h/templ v0.3.943 h1:o+mT/4yqhZ33F3ootBiHwaY4HM5EVaOJfIshvd5UNTY=
|
github.com/a-h/templ v0.3.943 h1:o+mT/4yqhZ33F3ootBiHwaY4HM5EVaOJfIshvd5UNTY=
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ func FormatDuration(d time.Duration) string {
|
|||||||
|
|
||||||
// Converts duration to string
|
// Converts duration to string
|
||||||
func FormatDurationFill(d time.Duration, fill bool) string {
|
func FormatDurationFill(d time.Duration, fill bool) string {
|
||||||
|
return fmt.Sprintf("%.1f", d.Hours())
|
||||||
hours := int(d.Abs().Hours())
|
hours := int(d.Abs().Hours())
|
||||||
minutes := int(d.Abs().Minutes()) % 60
|
minutes := int(d.Abs().Minutes()) % 60
|
||||||
sign := ""
|
sign := ""
|
||||||
@@ -68,10 +69,3 @@ func GetWorkingDays(startDate, endDate time.Time) int {
|
|||||||
}
|
}
|
||||||
return count
|
return count
|
||||||
}
|
}
|
||||||
|
|
||||||
func FormatGermanDayOfWeek(t time.Time) string {
|
|
||||||
return days[t.Weekday()][:2]
|
|
||||||
}
|
|
||||||
|
|
||||||
var days = [...]string{
|
|
||||||
"Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"}
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ func TestGetMonday(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestFormatDuration(t *testing.T) {
|
func TestFormatDuration(t *testing.T) {
|
||||||
testCases := []struct {
|
durations := []struct {
|
||||||
name string
|
name string
|
||||||
duration time.Duration
|
duration time.Duration
|
||||||
}{
|
}{
|
||||||
@@ -28,9 +28,9 @@ func TestFormatDuration(t *testing.T) {
|
|||||||
{"-1h 30min", time.Duration(-90 * time.Minute)},
|
{"-1h 30min", time.Duration(-90 * time.Minute)},
|
||||||
{"", 0},
|
{"", 0},
|
||||||
}
|
}
|
||||||
for _, tc := range testCases {
|
for _, d := range durations {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(d.name, func(t *testing.T) {
|
||||||
if FormatDuration(tc.duration) != tc.name {
|
if FormatDuration(d.duration) != d.name {
|
||||||
t.Error("Format missmatch in Formatduration.")
|
t.Error("Format missmatch in Formatduration.")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -58,27 +58,3 @@ func TestGetWorkingDays(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFormatGermanDayOfWeek(t *testing.T) {
|
|
||||||
testCases := []struct {
|
|
||||||
date string
|
|
||||||
result string
|
|
||||||
}{
|
|
||||||
{"2025-12-01", "Mo"},
|
|
||||||
{"2025-12-02", "Di"},
|
|
||||||
{"2025-12-03", "Mi"},
|
|
||||||
{"2025-12-04", "Do"},
|
|
||||||
{"2025-12-05", "Fr"},
|
|
||||||
{"2025-12-06", "Sa"},
|
|
||||||
{"2025-12-07", "So"},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tc := range testCases {
|
|
||||||
t.Run(fmt.Sprintf("FormatWeekDayTest: %s date", tc.date), func(t *testing.T) {
|
|
||||||
date, _ := time.Parse(time.DateOnly, tc.date)
|
|
||||||
if FormatGermanDayOfWeek(date) != tc.result {
|
|
||||||
t.Error("Formatted workday did not match!")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ templ defaultWeekDayComponent(u models.User, day models.IWorkDay) {
|
|||||||
<div class="flex flex-row gap-2">
|
<div class="flex flex-row gap-2">
|
||||||
@timeGaugeComponent(day.GetDayProgress(u), false)
|
@timeGaugeComponent(day.GetDayProgress(u), false)
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<p class=""><span class="font-bold uppercase hidden md:inline">{ helper.FormatGermanDayOfWeek(day.Date()) }:</span> { day.Date().Format("02.01.2006") }</p>
|
<p class=""><span class="font-bold uppercase hidden md:inline">{ day.Date().Format("Mon") }:</span> { day.Date().Format("02.01.2006") }</p>
|
||||||
if day.IsWorkDay() {
|
if day.IsWorkDay() {
|
||||||
{{
|
{{
|
||||||
workDay, _ := day.(*models.WorkDay)
|
workDay, _ := day.(*models.WorkDay)
|
||||||
|
|||||||
@@ -151,9 +151,9 @@ func defaultWeekDayComponent(u models.User, day models.IWorkDay) templ.Component
|
|||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var7 string
|
var templ_7745c5c3_Var7 string
|
||||||
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(helper.FormatGermanDayOfWeek(day.Date()))
|
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(day.Date().Format("Mon"))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/teamComponents.templ`, Line: 35, Col: 108}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/teamComponents.templ`, Line: 35, Col: 92}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@@ -166,7 +166,7 @@ func defaultWeekDayComponent(u models.User, day models.IWorkDay) templ.Component
|
|||||||
var templ_7745c5c3_Var8 string
|
var templ_7745c5c3_Var8 string
|
||||||
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(day.Date().Format("02.01.2006"))
|
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(day.Date().Format("02.01.2006"))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/teamComponents.templ`, Line: 35, Col: 152}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/teamComponents.templ`, Line: 35, Col: 136}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ templ defaultDayComponent(day models.IWorkDay) {
|
|||||||
@timeGaugeComponent(day.GetDayProgress(user), day.Date().Equal(time.Now().Truncate(24*time.Hour)))
|
@timeGaugeComponent(day.GetDayProgress(user), day.Date().Equal(time.Now().Truncate(24*time.Hour)))
|
||||||
<div>
|
<div>
|
||||||
<p>
|
<p>
|
||||||
<span class="font-bold uppercase hidden md:inline">{ helper.FormatGermanDayOfWeek(day.Date()) }:</span> { day.Date().Format("02.01.2006") }
|
<span class="font-bold uppercase hidden md:inline">{ day.Date().Format("Mon") }:</span> { day.Date().Format("02.01.2006") }
|
||||||
</p>
|
</p>
|
||||||
if day.IsWorkDay() {
|
if day.IsWorkDay() {
|
||||||
{{
|
{{
|
||||||
|
|||||||
@@ -269,9 +269,9 @@ func defaultDayComponent(day models.IWorkDay) templ.Component {
|
|||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var12 string
|
var templ_7745c5c3_Var12 string
|
||||||
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(helper.FormatGermanDayOfWeek(day.Date()))
|
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(day.Date().Format("Mon"))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timePage.templ`, Line: 101, Col: 98}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timePage.templ`, Line: 101, Col: 82}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@@ -284,7 +284,7 @@ func defaultDayComponent(day models.IWorkDay) templ.Component {
|
|||||||
var templ_7745c5c3_Var13 string
|
var templ_7745c5c3_Var13 string
|
||||||
templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(day.Date().Format("02.01.2006"))
|
templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(day.Date().Format("02.01.2006"))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timePage.templ`, Line: 101, Col: 142}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/timePage.templ`, Line: 101, Col: 126}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
|
|||||||
@@ -1,6 +1,12 @@
|
|||||||
name: arbeitszeitmessung-dev
|
name: arbeitszeitmessung-dev
|
||||||
services:
|
services:
|
||||||
db:
|
db:
|
||||||
|
image: postgres:16
|
||||||
|
restart: unless-stopped
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
|
environment:
|
||||||
|
PGDATA: /var/lib/postgresql/data/pg_data
|
||||||
volumes:
|
volumes:
|
||||||
- ${POSTGRES_PATH}:/var/lib/postgresql/data
|
- ${POSTGRES_PATH}:/var/lib/postgresql/data
|
||||||
# - ${POSTGRES_PATH}/initdb:/docker-entrypoint-initdb.d
|
# - ${POSTGRES_PATH}/initdb:/docker-entrypoint-initdb.d
|
||||||
@@ -13,8 +19,21 @@ services:
|
|||||||
ports:
|
ports:
|
||||||
- 8001:8080
|
- 8001:8080
|
||||||
backend:
|
backend:
|
||||||
|
image: git.letsstein.de/tom/arbeitszeitmessung
|
||||||
|
restart: unless-stopped
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
environment:
|
environment:
|
||||||
|
POSTGRES_HOST: db
|
||||||
|
POSTGRES_DB: ${POSTGRES_DB}
|
||||||
|
EXPOSED_PORT: ${EXPOSED_PORT}
|
||||||
NO_CORS: true
|
NO_CORS: true
|
||||||
|
ports:
|
||||||
|
- ${EXPOSED_PORT}:8080
|
||||||
|
volumes:
|
||||||
|
- ../logs:/app/Backend/logs
|
||||||
|
depends_on:
|
||||||
|
- db
|
||||||
|
|
||||||
swagger:
|
swagger:
|
||||||
image: swaggerapi/swagger-ui
|
image: swaggerapi/swagger-ui
|
||||||
|
|||||||
@@ -12,25 +12,20 @@ services:
|
|||||||
- ${POSTGRES_PATH}:/var/lib/postgresql/data
|
- ${POSTGRES_PATH}:/var/lib/postgresql/data
|
||||||
- ${POSTGRES_PATH}/initdb:/docker-entrypoint-initdb.d
|
- ${POSTGRES_PATH}/initdb:/docker-entrypoint-initdb.d
|
||||||
ports:
|
ports:
|
||||||
- ${POSTGRES_PORT}:5432
|
- 5432:5432
|
||||||
|
|
||||||
backend:
|
backend:
|
||||||
image: git.letsstein.de/tom/arbeitszeitmessung-webserver
|
image: git.letsstein.de/tom/arbeitszeitmessung
|
||||||
env_file:
|
env_file:
|
||||||
- .env
|
- .env
|
||||||
environment:
|
environment:
|
||||||
POSTGRES_HOST: db
|
POSTGRES_HOST: db
|
||||||
POSTGRES_DB: ${POSTGRES_DB}
|
POSTGRES_DB: ${POSTGRES_DB}
|
||||||
|
EXPOSED_PORT: ${EXPOSED_PORT}
|
||||||
ports:
|
ports:
|
||||||
- ${WEB_PORT}:8080
|
- ${EXPOSED_PORT}:8080
|
||||||
depends_on:
|
depends_on:
|
||||||
- db
|
- db
|
||||||
- document-creator
|
|
||||||
volumes:
|
volumes:
|
||||||
- ../logs:/app/Backend/logs
|
- ../logs:/app/Backend/logs
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|
||||||
document-creator:
|
|
||||||
image: git.letsstein.de/tom/arbeitszeitmessung-doc-creator
|
|
||||||
container_name: ${TYPST_CONTAINER}
|
|
||||||
restart: unless-stopped
|
|
||||||
|
|||||||
@@ -4,9 +4,7 @@ POSTGRES_API_USER=api_nutzer # Postgres API Nutzername (f
|
|||||||
POSTGRES_API_PASS=password # Postgres API Passwort (für Arbeitszeitmessung)
|
POSTGRES_API_PASS=password # Postgres API Passwort (für Arbeitszeitmessung)
|
||||||
POSTGRES_PATH=../DB # Datebank Pfad (relativ zu Docker Ordner oder absoluter pfad mit /...)
|
POSTGRES_PATH=../DB # Datebank Pfad (relativ zu Docker Ordner oder absoluter pfad mit /...)
|
||||||
POSTGRES_DB=arbeitszeitmessung # Postgres Datenbank Name
|
POSTGRES_DB=arbeitszeitmessung # Postgres Datenbank Name
|
||||||
POSTGRES_PORT=127.0.0.1:5432 # Postgres Port will not be exposed by default.
|
EXPOSED_PORT=8000 # Port auf welchem Arbeitszeitmessung läuft regex:^[0-9]{1,5}$
|
||||||
TZ=Europe/Berlin # Zeitzone
|
TZ=Europe/Berlin # Zeitzone
|
||||||
PGTZ=Europe/Berlin # Zeitzone
|
PGTZ=Europe/Berlin # Zeitzone
|
||||||
API_TOKEN=dont_access # API Token für ESP Endpoints
|
API_TOKEN=dont_access # API Token für ESP Endpoints
|
||||||
WEB_PORT=8000 # Port from which Arbeitszeitmessung should be accessable regex:^[0-9]{1,5}$
|
|
||||||
TYPST_CONTAINER=arbeitszeitmessung-doc-creator # Name of the pdf compiler container
|
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
FROM ghcr.io/typst/typst:0.14.0
|
|
||||||
|
|
||||||
COPY ./templates ./templates
|
|
||||||
COPY ./static ./static
|
|
||||||
|
|
||||||
ENTRYPOINT ["sh", "-c", "while true; do sleep 3600; done"]
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 17 KiB |
@@ -1,92 +0,0 @@
|
|||||||
#let table-header(..headers) = {
|
|
||||||
table.header(
|
|
||||||
..headers.pos().map(h => strong(h))
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#let abrechnung(meta, days) = {
|
|
||||||
set page(paper: "a4", margin: (x:1.5cm, y:2.25cm),
|
|
||||||
footer:[#grid(
|
|
||||||
columns: (3fr, .65fr),
|
|
||||||
align: left + horizon,
|
|
||||||
inset: .5em,
|
|
||||||
[#meta.EmployeeName -- #meta.TimeRange], grid.cell(rowspan: 2)[#image("static/logo.png")],
|
|
||||||
[Arbeitszeitrechnung maschinell erstellt am #meta.CurrentTimestamp],
|
|
||||||
)
|
|
||||||
])
|
|
||||||
set text(font: "Noto Sans", size:10pt, fill: luma(10%))
|
|
||||||
set table(
|
|
||||||
stroke: 0.5pt + luma(10%),
|
|
||||||
inset: .5em,
|
|
||||||
align: center + horizon,
|
|
||||||
)
|
|
||||||
show text: it => {
|
|
||||||
if it.text == "0min"{
|
|
||||||
text(oklch(70.8%, 0, 0deg))[#it]
|
|
||||||
}else if it.text.starts-with("-"){
|
|
||||||
text(red)[#it]
|
|
||||||
}else{
|
|
||||||
it
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
[= Abrechnung Arbeitszeit -- #meta.EmployeeName]
|
|
||||||
|
|
||||||
[Zeitraum: #meta.TimeRange]
|
|
||||||
|
|
||||||
table(
|
|
||||||
columns: (1fr, 1fr, 1fr, 1fr, 1fr, 1fr, 1.25fr),
|
|
||||||
fill: (x, y) =>
|
|
||||||
if y == 0 { oklch(87%, 0, 0deg) },
|
|
||||||
table-header(
|
|
||||||
[Datum], [Kommen], [Gehen], [Arbeitsart], [Stunden], [Pause], [Überstunden]
|
|
||||||
),
|
|
||||||
.. for day in days {
|
|
||||||
(
|
|
||||||
[#day.Date],
|
|
||||||
if day.DayParts.len() == 0{
|
|
||||||
table.cell(colspan: 3)[Keine Buchungen]
|
|
||||||
}else if not day.DayParts.first().IsWorkDay{
|
|
||||||
table.cell(colspan: 3)[#day.DayParts.first().WorkType]
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
|
|
||||||
table.cell(colspan: 3, inset: 0em)[
|
|
||||||
|
|
||||||
#table(
|
|
||||||
columns: (1fr, 1fr, 1fr),
|
|
||||||
.. for Zeit in day.DayParts {
|
|
||||||
(
|
|
||||||
[#Zeit.BookingFrom],
|
|
||||||
[#Zeit.BookingTo],
|
|
||||||
[#Zeit.WorkType],
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
]
|
|
||||||
},
|
|
||||||
[#day.Worktime],
|
|
||||||
[#day.Pausetime],
|
|
||||||
[#day.Overtime],
|
|
||||||
)
|
|
||||||
if day.IsFriday {
|
|
||||||
( table.cell(colspan: 7, fill: oklch(87%, 0, 0deg))[Wochenende], ) // note the trailing comma
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
table(
|
|
||||||
columns: (3fr, 1fr),
|
|
||||||
align: right,
|
|
||||||
inset: (x: .25em, y:.75em),
|
|
||||||
stroke: none,
|
|
||||||
table.hline(start: 0, end: 2, stroke: stroke(dash:"dashed", thickness:.5pt)),
|
|
||||||
[Arbeitszeit :], table.cell(align: left)[#meta.WorkTime],
|
|
||||||
[Überstunden :], table.cell(align: left)[#meta.Overtime],
|
|
||||||
[Überstunden :],table.cell(align: left)[#meta.OvertimeTotal],
|
|
||||||
table.hline(start: 0, end: 2),
|
|
||||||
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -100,7 +100,6 @@ echo "Start containers with docker compose up -d? [y/N]"
|
|||||||
read -r start_containers
|
read -r start_containers
|
||||||
if [[ "$start_containers" =~ ^[Yy]$ ]]; then
|
if [[ "$start_containers" =~ ^[Yy]$ ]]; then
|
||||||
cd Docker
|
cd Docker
|
||||||
mkdir ../logs
|
|
||||||
docker compose up -d
|
docker compose up -d
|
||||||
echo "Containers started."
|
echo "Containers started."
|
||||||
else
|
else
|
||||||
|
|||||||
Reference in New Issue
Block a user