first commit
This commit is contained in:
@@ -0,0 +1,312 @@
|
||||
# ZynkTime
|
||||
|
||||
A time reporting application for the Kleer API with both FastAPI web interface and CLI.
|
||||
|
||||
## Features
|
||||
|
||||
- 🎨 **Modern Web UI**: Beautiful, responsive web interface with drag-and-drop file upload
|
||||
- 📊 **CSV Processing**: Parse and extract work time from CSV files
|
||||
- 🌐 **REST API**: FastAPI endpoints for time reporting
|
||||
- 💻 **CLI Interface**: Interactive command-line time reporting
|
||||
- ✅ **Input Validation**: Pydantic models for data validation
|
||||
- 🧪 **Tested**: Unit tests with pytest
|
||||
- 📝 **Well-Documented**: Comprehensive docstrings and type hints
|
||||
|
||||
## Quick Start
|
||||
|
||||
### 🐳 Docker (Recommended)
|
||||
|
||||
The easiest way to run ZynkTime is with Docker:
|
||||
|
||||
```bash
|
||||
# 1. Clone the repository
|
||||
cd zynktime
|
||||
|
||||
# 2. Copy environment file
|
||||
cp .env.example .env
|
||||
|
||||
# 3. Edit .env and add your API key
|
||||
nano .env # or use your favorite editor
|
||||
|
||||
# 4. Start with Docker Compose
|
||||
docker-compose up -d
|
||||
|
||||
# 5. Open your browser
|
||||
# Navigate to: http://localhost:8000
|
||||
```
|
||||
|
||||
**Docker Commands:**
|
||||
```bash
|
||||
# Start the application
|
||||
docker-compose up -d
|
||||
|
||||
# View logs
|
||||
docker-compose logs -f
|
||||
|
||||
# Stop the application
|
||||
docker-compose down
|
||||
|
||||
# Rebuild after code changes
|
||||
docker-compose up -d --build
|
||||
|
||||
# Access container shell
|
||||
docker-compose exec zynktime bash
|
||||
```
|
||||
|
||||
### 🐍 Manual Installation
|
||||
|
||||
If you prefer to run without Docker:
|
||||
|
||||
```bash
|
||||
# Clone the repository
|
||||
cd zynktime
|
||||
|
||||
# Create virtual environment
|
||||
python -m venv venv
|
||||
source venv/bin/activate # On Windows: venv\Scripts\activate
|
||||
|
||||
# Install dependencies
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
### Configuration
|
||||
|
||||
**Option 1: Environment File (Recommended)**
|
||||
```bash
|
||||
# Copy example file
|
||||
cp .env.example .env
|
||||
|
||||
# Edit with your values
|
||||
nano .env
|
||||
```
|
||||
|
||||
**Option 2: Export Variables**
|
||||
```bash
|
||||
export KLEER_API_KEY="your_api_key_here"
|
||||
export KLEER_USERNAME="Your Name" # Optional, defaults to "Christopher Juhlin"
|
||||
export KLEER_COMPANY_ID="1336" # Optional, defaults to "1336"
|
||||
```
|
||||
|
||||
### Running the Application
|
||||
|
||||
**Web UI Mode (Recommended):**
|
||||
```bash
|
||||
python main.py
|
||||
# Open your browser and navigate to: http://localhost:8000
|
||||
```
|
||||
|
||||
**CLI Mode:**
|
||||
```bash
|
||||
python main.py cli
|
||||
# Interactive CLI for processing CSV files
|
||||
```
|
||||
|
||||
### Using the Web UI
|
||||
|
||||
1. **Open your browser** to `http://localhost:8000`
|
||||
2. **Upload your CSV file** by dragging and dropping or clicking to browse
|
||||
3. **Select a project** from the dropdown
|
||||
4. **Click "Report Time"** to submit
|
||||
5. View the **results summary** with total hours and days reported
|
||||
|
||||
The web interface features:
|
||||
- 🎯 Drag-and-drop file upload
|
||||
- 📋 Real-time project list
|
||||
- 💫 Smooth animations and transitions
|
||||
- 📱 Fully responsive design
|
||||
- 🔔 Toast notifications for feedback
|
||||
- ✅ Connection status indicator
|
||||
|
||||
## API Endpoints
|
||||
|
||||
### GET /
|
||||
Serves the modern web UI interface.
|
||||
|
||||
### GET /api
|
||||
Returns API information and available endpoints.
|
||||
|
||||
### GET /health
|
||||
Health check endpoint - verifies API key configuration.
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"status": "healthy",
|
||||
"api_key_configured": true
|
||||
}
|
||||
```
|
||||
|
||||
### GET /projects
|
||||
Lists all active projects for the configured user.
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"Project Name": {
|
||||
"id": 123,
|
||||
"activity": {"id": 456}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### POST /report-time
|
||||
Upload a CSV file and report time to a specific project.
|
||||
|
||||
**Parameters:**
|
||||
- `project_name` (query): Name of the project
|
||||
- `file` (form): CSV file with time entries
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"message": "Time reported successfully.",
|
||||
"reported_days": 5,
|
||||
"total_hours": 40.0,
|
||||
"project_name": "Project Name",
|
||||
"user_name": "Your Name"
|
||||
}
|
||||
```
|
||||
|
||||
### GET /docs
|
||||
Interactive API documentation (Swagger UI).
|
||||
|
||||
## CSV Format
|
||||
|
||||
The application **automatically detects** the CSV delimiter (comma or semicolon) and column structure.
|
||||
|
||||
### Supported Formats
|
||||
|
||||
**Format 1: Comma-separated with headers**
|
||||
```csv
|
||||
reg_period,xreg_period,T,Time code,Time code (T),Vouch.date,Project Activity,Project Activity (T),Work package,Work package (T),Hours,Workflow status,Text
|
||||
202544,,A,0,Standard Time,10/27/2025,,,,,2.00,N,
|
||||
202544,,A,0,Standard Time,10/28/2025,,,,,4.00,N,
|
||||
```
|
||||
|
||||
**Format 2: Semicolon-separated**
|
||||
```csv
|
||||
...;...;...;...;...;01/15/2024;...;...;...;...;8.5;...
|
||||
...;...;...;...;...;01/16/2024;...;...;...;...;7,5;...
|
||||
```
|
||||
|
||||
### Column Detection
|
||||
|
||||
- **Date column**: Automatically detected by searching for columns containing "date" or "vouch" in the header
|
||||
- **Hours column**: Automatically detected by searching for columns containing "hour" in the header
|
||||
- **Date formats**: Supports both `MM/DD/YYYY` and `YYYY-MM-DD`
|
||||
- **Hours format**: Supports decimal hours with comma (`,`) or dot (`.`) as separator
|
||||
- **Whitespace**: Automatically trimmed from values
|
||||
|
||||
## Development
|
||||
|
||||
### Project Structure
|
||||
|
||||
```
|
||||
zynktime/
|
||||
├── static/
|
||||
│ ├── index.html # Modern web UI
|
||||
│ ├── css/
|
||||
│ │ └── style.css # Responsive styling
|
||||
│ └── js/
|
||||
│ └── app.js # Frontend logic
|
||||
├── main.py # FastAPI application entry point
|
||||
├── cli.py # CLI interface
|
||||
├── config.py # Configuration management
|
||||
├── models.py # Pydantic models
|
||||
├── api_client.py # Kleer API client
|
||||
├── services.py # Business logic
|
||||
├── test_main.py # Unit tests
|
||||
├── requirements.txt # Python dependencies
|
||||
├── AGENTS.md # Guidelines for AI agents
|
||||
└── README.md # This file
|
||||
```
|
||||
|
||||
### Running Tests
|
||||
|
||||
```bash
|
||||
# Run all tests
|
||||
pytest
|
||||
|
||||
# Run with verbose output
|
||||
pytest -v
|
||||
|
||||
# Run specific test
|
||||
pytest test_main.py::TestServices::test_validate_date_valid -v
|
||||
|
||||
# Run with coverage
|
||||
pytest --cov=. --cov-report=html
|
||||
```
|
||||
|
||||
### Code Quality
|
||||
|
||||
The codebase follows:
|
||||
- **Type hints**: Full typing support
|
||||
- **Error handling**: Specific exceptions with proper logging
|
||||
- **Separation of concerns**: Modular architecture
|
||||
- **Documentation**: Comprehensive docstrings
|
||||
- **Testing**: Unit tests for core functionality
|
||||
|
||||
## Environment Variables
|
||||
|
||||
| Variable | Required | Default | Description |
|
||||
|----------|----------|---------|-------------|
|
||||
| `KLEER_API_KEY` | Yes | - | API key for Kleer API |
|
||||
| `KLEER_USERNAME` | No | Christopher Juhlin | Username for API requests |
|
||||
| `KLEER_COMPANY_ID` | No | 1336 | Company ID for API requests |
|
||||
|
||||
## Docker Deployment
|
||||
|
||||
### Production Deployment
|
||||
|
||||
For production, you can customize the docker-compose.yml:
|
||||
|
||||
```yaml
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
zynktime:
|
||||
image: zynktime:latest
|
||||
restart: always
|
||||
ports:
|
||||
- "80:8000" # Expose on port 80
|
||||
environment:
|
||||
- KLEER_API_KEY=${KLEER_API_KEY}
|
||||
- KLEER_USERNAME=${KLEER_USERNAME}
|
||||
- KLEER_COMPANY_ID=${KLEER_COMPANY_ID}
|
||||
env_file:
|
||||
- .env
|
||||
```
|
||||
|
||||
### Behind a Reverse Proxy
|
||||
|
||||
If deploying behind nginx or traefik:
|
||||
|
||||
```yaml
|
||||
# docker-compose.yml
|
||||
services:
|
||||
zynktime:
|
||||
image: zynktime:latest
|
||||
networks:
|
||||
- proxy
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.zynktime.rule=Host(`time.example.com`)"
|
||||
```
|
||||
|
||||
### Health Checks
|
||||
|
||||
The Docker container includes health checks:
|
||||
- **Endpoint**: `/health`
|
||||
- **Interval**: 30 seconds
|
||||
- **Timeout**: 10 seconds
|
||||
- **Retries**: 3
|
||||
|
||||
Monitor with:
|
||||
```bash
|
||||
docker-compose ps
|
||||
docker inspect zynktime | grep Health
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
This project is for internal use with the Kleer API.
|
||||
Reference in New Issue
Block a user