Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ If applicable, add screenshots to help explain your problem.
## Environment
- **OS**: [e.g., Windows 10, macOS 11.0, Ubuntu 20.04]
- **Python Version**: [e.g., 3.9.5]
- **Worklog Manager Version**: [e.g., 1.6.0]
- **Worklog Manager Version**: [e.g., 1.7.0]

## Log Files
Please attach relevant log files from the `logs/` directory.
Expand Down
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ All notable changes to Worklog Manager will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.6.0] - 2025-10-22
## [1.7.0] - 2025-10-22

### Added
- Scroll-enabled main window container so every control stays reachable on compact displays without sacrificing theming.
Expand Down
4 changes: 2 additions & 2 deletions DOCUMENTATION_SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,15 +89,15 @@ Configure these in GitHub:
1. **Description**: Add a clear one-line description
2. **Topics**: Add tags like `time-tracking`, `python`, `tkinter`, `productivity`
3. **Website**: Link to documentation or project page
4. **Releases**: Create your first release (v1.6.0)
4. **Releases**: Create your first release (v1.7.0)
5. **About**: Fill in the About section with description and topics
6. **Discussions**: Enable GitHub Discussions for community
7. **Issues**: Ensure issues are enabled
8. **Projects**: Consider using GitHub Projects for roadmap tracking

### Before Publishing
- [ ] Replace `your-username` in all markdown files with actual GitHub username
- [ ] Create first release (v1.6.0) on GitHub
- [ ] Create first release (v1.7.0) on GitHub
- [ ] Add repository description and topics
- [ ] Enable GitHub Discussions
- [ ] Consider adding a social preview image
Expand Down
4 changes: 2 additions & 2 deletions PROJECT_OVERVIEW.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
Worklog Manager is a comprehensive desktop application for precise work time tracking. Built with Python and Tkinter, it provides professionals and teams with an offline-first solution for monitoring work hours, managing breaks, and generating detailed productivity reports.

### Key Statistics
- **Version**: 1.6.0 (Production Ready)
- **Version**: 1.7.0 (Production Ready)
- **Language**: Python 3.7+
- **License**: MIT
- **Platform**: Cross-platform (Windows, macOS, Linux)
Expand Down Expand Up @@ -114,7 +114,7 @@ worklog-manager/
✅ **Phase 1**: Core time tracking (v1.0.0)
✅ **Phase 2**: Action history and revoke (v1.2.0)
✅ **Phase 3**: Export and reporting (v1.3.0)
✅ **Phase 4**: Advanced features (v1.6.0)
✅ **Phase 4**: Advanced features (v1.7.0)

### Current State
- **Production ready** for professional use
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

[![Python Version](https://img.shields.io/badge/python-3.7%2B-blue.svg)](https://www.python.org/downloads/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
[![Version](https://img.shields.io/badge/version-1.6.0-green.svg)](CHANGELOG.md)
[![Version](https://img.shields.io/badge/version-1.7.0-green.svg)](CHANGELOG.md)
[![Platform](https://img.shields.io/badge/platform-Windows%20%7C%20macOS%20%7C%20Linux-lightgrey.svg)](INSTALL.md)
[![Code Style](https://img.shields.io/badge/code%20style-PEP8-orange.svg)](https://www.python.org/dev/peps/pep-0008/)

Expand Down Expand Up @@ -144,7 +144,7 @@ Daily logs stored in `logs/` directory with format `worklog_YYYYMMDD.log`. Inclu

## Development Status

**Current Version: 1.6.0** - All phases completed
**Current Version: 1.7.0** - All phases completed
- ✅ Phase 1: Core time tracking and break management
- ✅ Phase 2: Action history and revoke system
- ✅ Phase 3: Export and reporting (CSV/JSON/PDF)
Expand Down
12 changes: 6 additions & 6 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Future development plans and feature ideas for Worklog Manager.

## Version 1.6.0 - CURRENT ✅
## Version 1.7.0 - CURRENT ✅

Latest highlights:
- ✅ Appearance settings for window size and maximized state
Expand All @@ -11,7 +11,7 @@ Latest highlights:
- ✅ Geometry preservation when hiding to system tray
- ✅ Stability fixes for shutdown and tray lifecycle

## Version 1.6.0 - Data Management (Planned)
## Version 1.7.0 - Data Management (Planned)

**Focus**: Enhanced data capabilities and historical analysis

Expand All @@ -32,7 +32,7 @@ Latest highlights:

**Target Release**: Q1 2026

## Version 1.7.0 - Collaboration Features (Under Consideration)
## Version 1.8.0 - Collaboration Features (Under Consideration)

**Focus**: Team and multi-user capabilities

Expand All @@ -46,7 +46,7 @@ Latest highlights:

**Target Release**: Q2 2026

## Version 1.8.0 - Integration & Automation (Future)
## Version 1.9.0 - Integration & Automation (Future)

**Focus**: External integrations and automation

Expand Down Expand Up @@ -80,8 +80,8 @@ Latest highlights:

Features requested by users (in order of popularity):

1. **Edit Historical Data** - High demand, planned for v1.6.0
2. **Project Tracking** - Under consideration for v1.7.0
1. **Edit Historical Data** - High demand, planned for v1.7.0
2. **Project Tracking** - Under consideration for v1.8.0
3. **Calendar Integration** - Investigating feasibility
4. **Mobile App** - Long-term goal (v2.0.0)
5. **Multi-language Support** - Medium priority
Expand Down
5 changes: 3 additions & 2 deletions core/action_history.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from dataclasses import dataclass, asdict

from data.models import WorklogState, ActionType, BreakType
from utils.datetime_compat import datetime_fromisoformat


@dataclass
Expand Down Expand Up @@ -278,9 +279,9 @@ def import_history(self, history_data: List[Dict[str, Any]]):
data['state_after'] = WorklogState(data['state_after'])

# Convert timestamp strings back to datetime
data['timestamp'] = datetime.fromisoformat(data['timestamp'])
data['timestamp'] = datetime_fromisoformat(data['timestamp'])
if data.get('revoke_timestamp'):
data['revoke_timestamp'] = datetime.fromisoformat(data['revoke_timestamp'])
data['revoke_timestamp'] = datetime_fromisoformat(data['revoke_timestamp'])

action = ActionSnapshot(**data)
imported_actions.append(action)
Expand Down
7 changes: 4 additions & 3 deletions core/data_aggregator.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from data.database import Database
from data.models import WorkSession, BreakPeriod, ActionLog, BreakType
from core.export_models import DailyStats, WeeklyStats, ExportData, ExportOptions, DateRange
from utils.datetime_compat import datetime_fromisoformat


class DataAggregator:
Expand Down Expand Up @@ -130,7 +131,7 @@ def _calculate_daily_stats(self, sessions: List[WorkSession],
# Group sessions by date
sessions_by_date = defaultdict(list)
for session in sessions:
session_date = datetime.fromisoformat(session.date).date()
session_date = datetime_fromisoformat(session.date).date()
sessions_by_date[session_date].append(session)

# Group breaks by session
Expand Down Expand Up @@ -159,8 +160,8 @@ def _calculate_daily_stats(self, sessions: List[WorkSession],
lunch_breaks=len([b for b in session_breaks if b.break_type == BreakType.LUNCH]),
general_breaks=len([b for b in session_breaks if b.break_type == BreakType.GENERAL]),
sessions_count=len(day_sessions),
first_start=datetime.fromisoformat(main_session.start_time) if main_session.start_time else None,
last_end=datetime.fromisoformat(main_session.end_time) if main_session.end_time else None
first_start=datetime_fromisoformat(main_session.start_time) if main_session.start_time else None,
last_end=datetime_fromisoformat(main_session.end_time) if main_session.end_time else None
)
else:
# No session for this day - create empty stats
Expand Down
4 changes: 3 additions & 1 deletion core/simple_backup_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
from typing import List, Dict, Optional
from pathlib import Path

from utils.datetime_compat import datetime_fromisoformat

class BackupManager:
"""Simple backup manager using only built-in Python libraries."""

Expand Down Expand Up @@ -233,7 +235,7 @@ def get_backup_list(self) -> List[Dict]:
info_created = info_data.get('created')
if info_created:
try:
entry['created'] = datetime.fromisoformat(info_created)
entry['created'] = datetime_fromisoformat(info_created)
except ValueError:
pass
except Exception as info_error:
Expand Down
3 changes: 2 additions & 1 deletion core/time_calculator.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import logging

from data.models import ActionLog, BreakPeriod, TimeCalculation, ActionType, WorklogState
from utils.datetime_compat import datetime_fromisoformat


class TimeCalculator:
Expand Down Expand Up @@ -36,7 +37,7 @@ def parse_time(time_str: str) -> datetime:
Returns:
datetime object
"""
return datetime.fromisoformat(time_str)
return datetime_fromisoformat(time_str)

@staticmethod
def format_time(dt: datetime) -> str:
Expand Down
9 changes: 5 additions & 4 deletions data/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from contextlib import contextmanager

from data.models import WorkSession, ActionLog, BreakPeriod, WorklogState, ActionType, BreakType
from utils.datetime_compat import datetime_fromisoformat


class Database:
Expand Down Expand Up @@ -151,8 +152,8 @@ def get_session_by_date(self, date: str) -> Optional[WorkSession]:
productive_minutes=row['productive_minutes'],
overtime_minutes=row['overtime_minutes'],
status=WorklogState(row['status']),
created_at=datetime.fromisoformat(row['created_at']) if row['created_at'] else None,
updated_at=datetime.fromisoformat(row['updated_at']) if row['updated_at'] else None
created_at=datetime_fromisoformat(row['created_at']) if row['created_at'] else None,
updated_at=datetime_fromisoformat(row['updated_at']) if row['updated_at'] else None
)
return None

Expand Down Expand Up @@ -236,7 +237,7 @@ def get_session_actions(self, session_id: int) -> List[ActionLog]:
break_type=BreakType(row['break_type']) if row['break_type'] else None,
notes=row['notes'],
revoked=bool(row['revoked']),
created_at=datetime.fromisoformat(row['created_at']) if row['created_at'] else None
created_at=datetime_fromisoformat(row['created_at']) if row['created_at'] else None
))
return actions

Expand Down Expand Up @@ -346,7 +347,7 @@ def get_session_breaks(self, session_id: int) -> List[BreakPeriod]:
start_time=row['start_time'],
end_time=row['end_time'],
duration_minutes=row['duration_minutes'],
created_at=datetime.fromisoformat(row['created_at']) if row['created_at'] else None
created_at=datetime_fromisoformat(row['created_at']) if row['created_at'] else None
))
return breaks

Expand Down
8 changes: 4 additions & 4 deletions docs/COMPLETION_SUMMARY.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Worklog Manager v1.6.0 - Application Completed!
# Worklog Manager v1.7.0 - Application Completed!

🎉 **CONGRATULATIONS!** Your comprehensive Worklog Manager application is now complete and ready to use!

Expand Down Expand Up @@ -60,7 +60,7 @@ Your complete application includes:

```
worklog-manager/
├── 🎯 main.py # Integrated application entry point (v1.6.0)
├── 🎯 main.py # Integrated application entry point (v1.7.0)
├── 🚀 start_worklog.py # Smart startup script with dependency checking
├── 🪟 start_worklog.bat # Windows batch file
├── 🐧 start_worklog.sh # Linux/Mac shell script
Expand Down Expand Up @@ -154,11 +154,11 @@ The application has been successfully tested and shows:

## 📞 Next Steps

Your Worklog Manager v1.6.0 is **COMPLETE AND READY TO USE!**
Your Worklog Manager v1.7.0 is **COMPLETE AND READY TO USE!**

Simply run the application and start tracking your work time with all the advanced features you requested. The application will grow with you as you use it, and all the Phase 4 foundations are in place for future enhancements.

**Enjoy your new professional work time tracking system!** 🎉

---
*Worklog Manager v1.6.0 - Built with ❤️ by GitHub Copilot*
*Worklog Manager v1.7.0 - Built with ❤️ by GitHub Copilot*
2 changes: 1 addition & 1 deletion docs/TECHNICAL_SPECIFICATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@

#### Window Properties
- **Size**: 700x500 pixels (resizable)
- **Title**: "Worklog Manager v1.6.0"
- **Title**: "Worklog Manager v1.7.0"
- **Icon**: Custom work timer icon
- **Position**: Center screen on startup

Expand Down
5 changes: 3 additions & 2 deletions exporters/csv_exporter.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

from core.export_models import ExportData, ExportResult, ReportType
from core.data_aggregator import DataAggregator
from utils.datetime_compat import datetime_fromisoformat


class CSVExporter:
Expand Down Expand Up @@ -224,7 +225,7 @@ def _generate_detailed_log_csv(self, export_data: ExportData) -> str:
session_date = session.date
break

timestamp = datetime.fromisoformat(action.timestamp)
timestamp = datetime_fromisoformat(action.timestamp)
row = [
session_date,
timestamp.strftime('%H:%M:%S'),
Expand Down Expand Up @@ -289,7 +290,7 @@ def _generate_break_analysis_csv(self, export_data: ExportData) -> str:

start_time = ''
if break_period.start_time:
start_time = datetime.fromisoformat(break_period.start_time).strftime('%H:%M:%S')
start_time = datetime_fromisoformat(break_period.start_time).strftime('%H:%M:%S')

row = [
session_date,
Expand Down
20 changes: 10 additions & 10 deletions gui/components/break_tracker.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ def _create_summary_grid(self, parent):
lunch_frame.grid(row=1, column=0, columnspan=3, sticky="ew", pady=1)
lunch_frame.columnconfigure(2, weight=1)

tk.Label(lunch_frame, text="🍽️ Lunch", bg="#FFE4B5").grid(row=0, column=0, sticky="w", padx=5, pady=2)
tk.Label(lunch_frame, text="[L] Lunch", bg="#FFE4B5").grid(row=0, column=0, sticky="w", padx=5, pady=2)
tk.Label(lunch_frame, textvariable=self.lunch_count_var, bg="#FFE4B5").grid(row=0, column=1, padx=20, pady=2)
tk.Label(lunch_frame, textvariable=self.lunch_time_var, bg="#FFE4B5").grid(row=0, column=2, sticky="e", padx=5, pady=2)

Expand All @@ -77,7 +77,7 @@ def _create_summary_grid(self, parent):
coffee_frame.grid(row=2, column=0, columnspan=3, sticky="ew", pady=1)
coffee_frame.columnconfigure(2, weight=1)

tk.Label(coffee_frame, text=" Coffee", bg="#D2B48C").grid(row=0, column=0, sticky="w", padx=5, pady=2)
tk.Label(coffee_frame, text="[C] Coffee", bg="#D2B48C").grid(row=0, column=0, sticky="w", padx=5, pady=2)
tk.Label(coffee_frame, textvariable=self.coffee_count_var, bg="#D2B48C").grid(row=0, column=1, padx=20, pady=2)
tk.Label(coffee_frame, textvariable=self.coffee_time_var, bg="#D2B48C").grid(row=0, column=2, sticky="e", padx=5, pady=2)

Expand All @@ -86,7 +86,7 @@ def _create_summary_grid(self, parent):
general_frame.grid(row=3, column=0, columnspan=3, sticky="ew", pady=1)
general_frame.columnconfigure(2, weight=1)

tk.Label(general_frame, text="⏱️ General", bg="#F0F0F0").grid(row=0, column=0, sticky="w", padx=5, pady=2)
tk.Label(general_frame, text="[B] General", bg="#F0F0F0").grid(row=0, column=0, sticky="w", padx=5, pady=2)
tk.Label(general_frame, textvariable=self.general_count_var, bg="#F0F0F0").grid(row=0, column=1, padx=20, pady=2)
tk.Label(general_frame, textvariable=self.general_time_var, bg="#F0F0F0").grid(row=0, column=2, sticky="e", padx=5, pady=2)

Expand Down Expand Up @@ -166,14 +166,14 @@ def _update_recent_list(self):
else:
status = f"{start_time}-ongoing"

# Add emoji based on break type
emoji = {
BreakType.LUNCH: "🍽️",
BreakType.COFFEE: "",
BreakType.GENERAL: "⏱️"
}.get(break_period.break_type, "⏱️")
# Add ASCII symbol based on break type for broad interpreter support
symbol = {
BreakType.LUNCH: "[L]",
BreakType.COFFEE: "[C]",
BreakType.GENERAL: "[B]"
}.get(break_period.break_type, "[B]")

break_text = f"{emoji} {break_period.break_type.value.title()}: {status}"
break_text = f"{symbol} {break_period.break_type.value.title()}: {status}"
self.breaks_listbox.insert(tk.END, break_text)

def _break_duration_seconds(self, break_period: BreakPeriod) -> int:
Expand Down
Loading
Loading