feat(m6): CSV export, Makefile, README, single-binary build
This commit is contained in:
132
README.md
Normal file
132
README.md
Normal file
@@ -0,0 +1,132 @@
|
||||
# Wotra — Working Time Tracker
|
||||
|
||||
A self-hosted working time tracker with a Go backend and a Svelte PWA frontend. Offline-capable, single-binary deploy.
|
||||
|
||||
## Features
|
||||
|
||||
- **Start / Stop** time tracking with an optional note.
|
||||
- **Close days**: merges all entries (worked_ms = sum of durations, breaks excluded).
|
||||
- **Mark days** as holiday, vacation, or sick (auto-credits expected daily hours).
|
||||
- **Close weeks**: computes overtime/undertime against a frozen snapshot of your expected hours.
|
||||
- **Settings history**: change hours/week with an `effective_from` date — past closed weeks are unaffected.
|
||||
- **PWA + offline**: works without a network connection; syncs via IndexedDB outbox when back online.
|
||||
- **CSV export**: entries, days, weeks.
|
||||
- **Midnight guard**: running entries are automatically stopped at 23:59:59 if they cross midnight.
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Development
|
||||
|
||||
```bash
|
||||
# 1. Set your auth token
|
||||
export AUTH_TOKEN=mysecrettoken
|
||||
|
||||
# 2. Start both servers
|
||||
make dev
|
||||
# Go API: http://localhost:8080
|
||||
# Vite UI: http://localhost:5173 (with /api proxy)
|
||||
```
|
||||
|
||||
Open `http://localhost:5173`, go to **Settings**, enter your token.
|
||||
|
||||
### Production (single binary)
|
||||
|
||||
```bash
|
||||
make build # builds web/ then embeds it in the Go binary
|
||||
|
||||
# Run
|
||||
AUTH_TOKEN=mysecrettoken ./wotra
|
||||
# open http://localhost:8080
|
||||
```
|
||||
|
||||
## Configuration (environment variables)
|
||||
|
||||
| Variable | Default | Description |
|
||||
|-------------|-------------|----------------------------------------------|
|
||||
| `AUTH_TOKEN` | **required** | Bearer token for API access |
|
||||
| `PORT` | `8080` | HTTP port |
|
||||
| `DB_PATH` | `wotra.db` | SQLite database file path |
|
||||
| `TZ` | `UTC` | Timezone for day/week key calculation |
|
||||
|
||||
## API Reference
|
||||
|
||||
All API endpoints require `Authorization: Bearer <token>` except `/healthz`.
|
||||
|
||||
### Entries
|
||||
|
||||
| Method | Path | Description |
|
||||
|--------|-----------------------------|--------------------------|
|
||||
| POST | `/api/entries/start` | Start tracking |
|
||||
| POST | `/api/entries/{id}/stop` | Stop a specific entry |
|
||||
| GET | `/api/entries?from=&to=` | List entries by date |
|
||||
| PUT | `/api/entries/{id}` | Edit start/end/note |
|
||||
| DELETE | `/api/entries/{id}` | Soft-delete an entry |
|
||||
|
||||
### Days
|
||||
|
||||
| Method | Path | Description |
|
||||
|--------|-------------------------------|--------------------------------------|
|
||||
| GET | `/api/days?from=&to=` | List closed days |
|
||||
| POST | `/api/days/{day}/close` | Close a day (merge entries) |
|
||||
| POST | `/api/days/{day}/mark` | Mark as holiday/vacation/sick |
|
||||
| DELETE | `/api/days/{day}/close` | Reopen a closed day |
|
||||
|
||||
### Weeks
|
||||
|
||||
| Method | Path | Description |
|
||||
|--------|-------------------------------|--------------------------------------|
|
||||
| GET | `/api/weeks?from=&to=` | List closed weeks |
|
||||
| POST | `/api/weeks/{week}/close` | Close a week (compute overtime) |
|
||||
| DELETE | `/api/weeks/{week}/close` | Reopen a closed week |
|
||||
|
||||
Week key format: `YYYY-Www` (e.g. `2024-W03`).
|
||||
|
||||
### Settings
|
||||
|
||||
| Method | Path | Description |
|
||||
|--------|-------------------------|------------------------------------|
|
||||
| GET | `/api/settings` | Current effective settings |
|
||||
| PUT | `/api/settings` | Add a new settings version |
|
||||
| GET | `/api/settings/history` | All settings history |
|
||||
|
||||
### Export
|
||||
|
||||
| Method | Path | Description |
|
||||
|--------|------------------------------|--------------------------|
|
||||
| GET | `/api/export/entries.csv` | Export entries as CSV |
|
||||
| GET | `/api/export/days.csv` | Export days as CSV |
|
||||
| GET | `/api/export/weeks.csv` | Export weeks as CSV |
|
||||
|
||||
### Sync
|
||||
|
||||
| Method | Path | Description |
|
||||
|--------|-------------------|-------------------------------------|
|
||||
| POST | `/api/sync/pull` | Pull changes since a version |
|
||||
| POST | `/api/sync/push` | Push local changes (advisory) |
|
||||
|
||||
### Health
|
||||
|
||||
| Method | Path | Description |
|
||||
|--------|-------------|--------------------------|
|
||||
| GET | `/healthz` | Unauthenticated health |
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
┌─────────────────────────┐ ┌──────────────────────────┐
|
||||
│ Svelte PWA (client) │ ◄─────► │ Go service (API) │
|
||||
│ - IndexedDB (Dexie) │ HTTPS │ - REST/JSON endpoints │
|
||||
│ - Service Worker │ JSON │ - Business logic │
|
||||
│ - Sync outbox │ │ - SQLite (modernc) │
|
||||
└─────────────────────────┘ └──────────────────────────┘
|
||||
```
|
||||
|
||||
See [PLAN.md](PLAN.md) for the full design document.
|
||||
|
||||
## Development Notes
|
||||
|
||||
- **Go module**: `github.com/wotra/wotra`
|
||||
- **SQLite driver**: `modernc.org/sqlite` (pure Go, no CGO)
|
||||
- **Day boundary**: entries must not cross midnight; the server auto-stops any running entry at 23:59:59 local time.
|
||||
- **Settings history**: `effective_from` lets you change hours/week without rewriting past closed weeks.
|
||||
- **Overtime**: stored as a signed `delta_ms` on each `closed_weeks` row. Frozen at close time.
|
||||
Reference in New Issue
Block a user