diff --git a/API.md b/API.md index abfdeebc..b44003b3 100644 --- a/API.md +++ b/API.md @@ -72,5 +72,6 @@ Replace `your-domain.com` with your TimeTracker host and `YOUR_API_TOKEN` with y ## Full Documentation - **[REST API reference](docs/api/REST_API.md)** — All endpoints, request/response formats, pagination, errors +- **[API Consistency Audit](docs/api/API_CONSISTENCY_AUDIT.md)** — Response contracts, error format, pagination - **[API Token Scopes](docs/api/API_TOKEN_SCOPES.md)** — Scopes and permissions - **[API Versioning](docs/api/API_VERSIONING.md)** — Versioning policy and usage diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index df24fffe..2fe68d3d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -12,6 +12,7 @@ Thank you for your interest in contributing to TimeTracker. This page gives you For development setup, coding standards, testing, pull request process, and commit conventions, see: +- **[Contributor Guide](docs/development/CONTRIBUTOR_GUIDE.md)** — Architecture, local dev, testing, how to add routes/services/templates, versioning - **[Contributing guidelines (full)](docs/development/CONTRIBUTING.md)** — Development setup, coding standards, testing, PR process - **[Code of Conduct](docs/development/CODE_OF_CONDUCT.md)** — Community standards and expected behavior - **[CHANGELOG.md](CHANGELOG.md)** — How we track changes; update the *Unreleased* section for user-facing changes diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index 4f968b06..ac35c68b 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -1,6 +1,6 @@ # TimeTracker Development Guide -Quick reference for running the project locally, running tests, and contributing. For full guidelines, see [Contributing](CONTRIBUTING.md) and the [developer documentation](docs/development/CONTRIBUTING.md). +Quick reference for running the project locally, running tests, and contributing. For a single-page contributor overview (workflows, adding routes/services/templates), see [Contributor Guide](docs/development/CONTRIBUTOR_GUIDE.md). For full guidelines, see [Contributing](CONTRIBUTING.md) and the [developer documentation](docs/development/CONTRIBUTING.md). ## Running Locally diff --git a/README.md b/README.md index 482f6703..38c3650a 100644 --- a/README.md +++ b/README.md @@ -76,7 +76,7 @@ TimeTracker is built with modern, reliable technologies: ## 🖥️ UI overview -The web app uses a **single main layout** with a sidebar and top header. Content is centered with a max width for readability. **Getting around:** **Dashboard** — overview, today’s stats, and the main **Timer** widget (start/stop, quick start, repeat last). **Timer** and **Time entries** are first-class in the sidebar for fast access. **Time entries** is the place to filter, review, and export all logged time. **Reports**, **Projects**, **Finance**, and **Settings** are available from the sidebar and navigation. For design and component conventions, see [UI Guidelines](docs/UI_GUIDELINES.md). +The web app uses a **single main layout** with a sidebar and top header. Content is centered with a max width for readability. **Getting around:** **Dashboard** — overview, today’s stats, and the main **Timer** widget (start/stop, quick start, repeat last). **Timer** and **Time entries** are first-class in the sidebar for fast access. **Time entries** is the place to filter, review, and export all logged time. **Reports** (time, project, finance) are available from the sidebar (top-level **Reports** link or **Finance & Expenses → Reports** for Report Builder, Saved Views, Scheduled Reports), and from the bottom bar on mobile. **Projects**, **Finance**, and **Settings** are available from the sidebar and navigation. For design and component conventions, see [UI Guidelines](docs/UI_GUIDELINES.md). --- @@ -86,20 +86,12 @@ TimeTracker has been continuously enhanced with powerful new features! Here's wh > **📋 For complete release history, see [CHANGELOG.md](CHANGELOG.md)** -**Current version** is defined in `setup.py` (single source of truth). See [CHANGELOG.md](CHANGELOG.md) for release history. +**Current version** is defined in `setup.py` (single source of truth). See [CHANGELOG.md](CHANGELOG.md) for versioned release history. - 📱 **Native Mobile & Desktop Apps** — Flutter mobile app (iOS/Android) and Electron desktop app with time tracking, offline support, and API integration ([Build Guide](BUILD.md), [Docs](docs/mobile-desktop-apps/README.md)) - 📋 **Project Analysis & Documentation** — Comprehensive project analysis and documentation updates - 🔧 **Version Consistency** — Fixed version inconsistencies across documentation files -**Previous Releases:** -- **v4.14.0** (January 2025) — Documentation and technology stack updates -- **v4.6.0** (December 2025) — Comprehensive Issue/Bug Tracking System - -**Recent Releases:** -- **v4.5.1** — Performance optimizations and version management improvements -- **v4.5.0** — Advanced Report Builder, quick task creation, Kanban enhancements, and PWA improvements -- **v4.4.1** — Dashboard cache fixes and custom reports enhancements -- **v4.4.0** — Project custom fields, file attachments, and salesman-based report splitting +See [CHANGELOG.md](CHANGELOG.md) for all release notes and version history. ### 🎯 **Major Feature Additions** @@ -437,7 +429,7 @@ docker-compose up -d # Click "Advanced" → "Proceed to localhost" to continue ``` -**First login creates the admin account** — just enter your username! +**First login creates the admin account** — just enter your username! For setup problems, see [INSTALLATION.md](INSTALLATION.md). **📖 See the complete setup guide:** [`docs/admin/configuration/DOCKER_COMPOSE_SETUP.md`](docs/admin/configuration/DOCKER_COMPOSE_SETUP.md) diff --git a/docs/ARCHITECTURE_AUDIT.md b/docs/ARCHITECTURE_AUDIT.md new file mode 100644 index 00000000..cccfbd9e --- /dev/null +++ b/docs/ARCHITECTURE_AUDIT.md @@ -0,0 +1,64 @@ +# Architecture Audit + +This document captures a concise architecture audit of the TimeTracker repository (Flask app with server-rendered templates, REST API, and desktop/mobile clients). It is used to drive incremental refactors toward thin routes, reusable services, and a predictable repository layer. + +--- + +## Current strengths + +- **Clear intended layering**: Routes → services → repositories/models is documented in [ARCHITECTURE.md](../ARCHITECTURE.md) and [Architecture Migration Guide](implementation-notes/ARCHITECTURE_MIGRATION_GUIDE.md). +- **Existing repository layer**: `app/repositories/` provides `BaseRepository` and dedicated repos for TimeEntry, Project, Task, Client, Invoice, Expense, Payment, User, Comment with sensible methods (e.g. `TimeEntryRepository.get_active_timer`, `get_by_date_range`, `get_total_duration`). +- **Central API response helpers**: `app/utils/api_responses.py` defines `success_response`, `error_response`, `validation_error_response`, `paginated_response`, etc.; error handlers in `app/utils/error_handlers.py` use them for JSON/API. +- **Blueprint registry**: Single registration point in `app/blueprint_registry.py` keeps app init clean. +- **Refactor examples**: The migration guide gives a clear "after" pattern. (Historical note: previously unregistered modules `timer_refactored.py`, `projects_refactored_example.py`, `invoices_refactored.py` have been merged or removed.) +- **Validation and schemas**: Marshmallow used for time-entry API v1; `app/utils/validation.py` and `app/utils/time_entry_validation.py` exist; `app/schemas/` has schemas for several resources (underused in routes). + +--- + +## Main architectural risks + +1. **Business logic in routes**: Heavy logic in `app/routes/reports.py` (comparison, project_report, unpaid_hours), `app/routes/invoices.py` (many direct queries), `app/routes/recurring_invoices.py`, `app/routes/expenses.py`, `app/routes/deals.py`, `app/routes/gantt.py`, `app/routes/comments.py`, `app/routes/client_notes.py`, `app/routes/audit_logs.py`, and others. +2. **Duplicated query patterns**: "User's distinct project IDs" from TimeEntry appears in budget_alerts, reports, data_export, gantt, timer, api with no shared repo method. Same for "user project IDs + accessible client IDs" in issues.py (4 blocks). Sum(TimeEntry.duration_seconds) repeated in analytics, reports, reporting_service, models, and utils despite `TimeEntryRepository.get_total_duration`. +3. **Inconsistent API contract**: Most api_v1 resource routes return resource-keyed payloads (`{"invoices": [...]}`, `{"invoice": {...}}`) and ad-hoc errors instead of the standard envelope (`success`, `data`, `error`, `error_code`) from `api_responses`. +4. **Validation inconsistency**: Only time-entry API v1 uses Marshmallow; other api_v1_* and all web forms use manual checks. Schemas exist for Invoice, Project, Client, Expense, etc. but are not used in corresponding routes. +5. **God files and tight coupling**: `app/routes/api_v1.py`, `app/routes/timer.py`, `app/routes/api.py`, `app/routes/reports.py`, `app/routes/invoices.py` are very large. Large route files mix many endpoints and inline queries. +6. **Logic in models**: `app/models/recurring_invoice.py` `generate_invoice()` does full workflow. `app/models/expense.py`, `app/models/lead.py`, `app/models/issue.py`, `app/models/project.py` contain state transitions and query/aggregation methods that belong in services/repositories. +7. **Template logic**: Budget and status rules in project view/list templates; task counts via `selectattr` in tasks list/my_tasks/kanban; totals and filters in inventory, client portal, expense_categories. Better to precompute in views. +8. **Missing repositories**: No repository for FocusSession, Activity, AuditLog, StockItem/inventory, RecurringInvoice, and others; services and routes use `Model.query` / `db.session` directly. +9. **Unused/refactor-only code**: (Historical: `timer_refactored.py`, `projects_refactored_example.py`, `invoices_refactored.py` are no longer present; refactors were merged or removed.) + +--- + +## Top 10 refactor targets (ranked by impact and risk) + +| # | Target | Impact | Risk | Action | +|---|--------|--------|------|--------| +| 1 | **Centralize "user's distinct project IDs"** | High | Low | Add `TimeEntryRepository.get_distinct_project_ids_for_user(user_id)`; replace 6+ call sites. | +| 2 | **Move RecurringInvoice.generate_invoice to service** | High | Medium | Create `RecurringInvoiceService.generate_invoice(recurring_invoice)`; keep model for state only; add tests. | +| 3 | **Thin reports routes** | High | Medium | Move comparison_view, project_report, unpaid_hours_report (and export) logic into `ReportingService`. | +| 4 | **Standardize API v1 response envelope** | High | Medium | Use `success_response`/`error_response` in api_v1_* routes; document contract. | +| 5 | **Recurring invoices: service + repository** | Medium–High | Medium | Add `RecurringInvoiceRepository` and `RecurringInvoiceService`; move list/create/edit/delete and generate from routes. | +| 6 | **Invoices route thinning (incremental)** | High | High | Move one invoice handler at a time into `InvoiceService` using existing `InvoiceRepository`; add tests per batch. | +| 7 | **Issues: shared "accessible projects/clients" helper** | Medium | Low | Add repository or scope helper; use in all four places in `app/routes/issues.py`. | +| 8 | **API v1 validation and api_responses** | Medium | Low | Use existing schemas + `handle_validation_error` and `success_response`/`error_response` in api_v1_* modules. | +| 9 | **Gantt: extract data and progress to service** | Medium | Low | Add `GanttService` for `get_gantt_data` and progress calculation; route only delegates. | +| 10 | **Precompute task counts and budget in views** | Medium | Low | In tasks/project routes, compute task_counts and budget fields; pass to templates. | + +--- + +## Refactor progress + +| # | Target | Status | +|---|--------|--------| +| 1 | Centralize "user's distinct project IDs" | Done | +| 2 | RecurringInvoiceService.generate_invoice | Done | +| 3 | Thin reports routes | Done | +| 4 | Standardize API v1 response envelope | Done (documented) | +| 5 | Recurring invoices service + repository | Done | +| 6 | Invoices incremental | Done (get_unbilled_data_for_invoice) | +| 7 | Issues accessible IDs helper | Done | +| 8 | API v1 validation and api_responses | Done (api_v1_projects) | +| 9 | Gantt service | Done | +| 10 | Precompute task counts and budget in views | Done | + +*(Update status to Done as refactors are completed.)* diff --git a/docs/DOCS_AUDIT.md b/docs/DOCS_AUDIT.md new file mode 100644 index 00000000..0c349b8b --- /dev/null +++ b/docs/DOCS_AUDIT.md @@ -0,0 +1,73 @@ +# Documentation Audit Summary + +This audit summarizes the state of TimeTracker documentation as of the audit date. Use it to find accurate sources, fix outdated content, and fill gaps. + +--- + +## Accurate (keep; minimal edits only) + +| Doc | Notes | +|-----|--------| +| **README.md** | Tech stack, quick start (Docker HTTPS/HTTP/SQLite), features, doc links correct. Version: states "defined in setup.py"; avoid hardcoding version examples in What's New. | +| **INSTALLATION.md** | Matches actual flow; points to GETTING_STARTED and DOCKER_COMPOSE_SETUP. | +| **DEVELOPMENT.md** | Venv + `flask run`, `docker-compose.local-test.yml`, folder structure, test commands align with repo. | +| **ARCHITECTURE.md** | Module table, data flow, API structure match app/ (blueprint_registry, routes, services, repositories, models). | +| **API.md** (root), **docs/api/REST_API.md** | Accurate overview and auth; REST_API is full reference. | +| **docs/development/SERVICE_LAYER_AND_BASE_CRUD.md** | Accurately describes service/repository pattern and BaseCRUDService. | +| **docs/development/LOCAL_TESTING_WITH_SQLITE.md** | Correct for docker-compose.local-test.yml and scripts. | +| **docs/TESTING_QUICK_REFERENCE.md**, **docs/TESTING_COVERAGE_GUIDE.md** | Align with Makefile targets and pytest markers. | +| **docs/UI_GUIDELINES.md**, **docs/FRONTEND.md** | Match templates (base.html, components/ui.html) and Tailwind. | +| **docs/GETTING_STARTED.md** | Correct: default compose → https://localhost; documents example compose for http://localhost:8080. | +| **requirements-test.txt** | Exists; referenced by Makefile and CI. | + +--- + +## Outdated + +| Item | Location | Fix | +|------|----------|-----| +| Version numbers | README "What's New" / "Current version" | Point to setup.py + CHANGELOG only; remove or generalize hardcoded v4.14.0, v4.6.0. | +| Hardcoded version | docs/development/PROJECT_STRUCTURE.md | Replace "version='4.20.9'" with "version in setup.py (single source of truth)". | +| Hardcoded version | docs/FEATURES_COMPLETE.md | Remove "Version: 4.20.6" or replace with "See setup.py". | +| Docker access URL | docs/development/CONTRIBUTING.md | Default `docker-compose up --build` → https://localhost. For http://localhost:8080 use docker-compose.example.yml or docker-compose.local-test.yml. | +| Compose role | docs/development/PROJECT_STRUCTURE.md | Describe docker-compose.yml as "Default stack (HTTPS via nginx)"; add docker-compose.example.yml (HTTP 8080) and docker-compose.local-test.yml (SQLite). | +| Refactored modules | docs/ARCHITECTURE_AUDIT.md | Note that timer_refactored/projects_refactored/invoices_refactored are historical (merged or removed). | +| Deployment guide label | docs/guides/DEPLOYMENT_GUIDE.md | Content is feature checklist, not "how to deploy". Add note at top pointing to DOCKER_COMPOSE_SETUP and DOCKER_PUBLIC_SETUP. | + +--- + +## Missing + +| Gap | Resolution | +|-----|------------| +| Single contributor onboarding doc | **CONTRIBUTOR_GUIDE.md** — Architecture, local dev, testing, how to add route/service/repository/template, versioning. | +| Versioning for contributors | Short "For contributors" note: app version in setup.py only; desktop/mobile have own config; link BUILD.md and VERSION_MANAGEMENT. | +| Step-by-step "add route/service/repository/template" | Include in CONTRIBUTOR_GUIDE with concrete steps (files, blueprint_registry, tests). | + +--- + +## Duplicated or Overlapping + +| Area | Notes | +|------|--------| +| **Installation** | README Quick Start, INSTALLATION.md, GETTING_STARTED.md, DOCKER_COMPOSE_SETUP all cover install. Keep overlap; add one-line pointers (e.g. "For step-by-step see INSTALLATION.md", "For all env vars see DOCKER_COMPOSE_SETUP"). | +| **Contributing** | Root CONTRIBUTING.md points to docs/development/CONTRIBUTING.md; fix Docker URL in full CONTRIBUTING. | +| **Deployment** | README, INSTALLATION, DOCKER_COMPOSE_SETUP, DOCKER_PUBLIC_SETUP, guides/DEPLOYMENT_GUIDE. Clarify DEPLOYMENT_GUIDE as feature checklist; "how to deploy" = DOCKER_COMPOSE_SETUP / DOCKER_PUBLIC_SETUP. | + +--- + +## Contradictions + +| Issue | Resolution | +|-------|------------| +| **Docker URL** | CONTRIBUTING (full) said http://localhost:8080 after default `docker-compose up --build`. Default compose serves **HTTPS** (https://localhost). Fix: document default = https://localhost; for 8080 use docker-compose.example.yml or docker-compose.local-test.yml. | +| **Compose purpose** | PROJECT_STRUCTURE said "Local development compose" for docker-compose.yml; README uses it for quick start and production. Unify: default = full stack HTTPS; development options = example (HTTP) or local-test (SQLite). | + +--- + +## File reference + +- **Audit doc**: this file — `docs/DOCS_AUDIT.md` +- **Updates**: README.md, docs/development/CONTRIBUTING.md, docs/development/PROJECT_STRUCTURE.md, docs/FEATURES_COMPLETE.md, docs/ARCHITECTURE_AUDIT.md, docs/README.md, docs/guides/DEPLOYMENT_GUIDE.md +- **New**: docs/development/CONTRIBUTOR_GUIDE.md +- **Cross-links**: CONTRIBUTING.md (root), docs/README.md, DEVELOPMENT.md diff --git a/docs/FEATURES_COMPLETE.md b/docs/FEATURES_COMPLETE.md index 1750ee81..9afd7861 100644 --- a/docs/FEATURES_COMPLETE.md +++ b/docs/FEATURES_COMPLETE.md @@ -1,8 +1,10 @@ # TimeTracker - Complete Features Documentation -**Version:** 4.20.6 (see `setup.py` for single source of truth) +**Version:** See `setup.py` for current version (single source of truth). **Last Updated:** 2025-02-20 +**Navigation:** Many features are optional (see Admin → Module Management). Reports are available from the top-level **Reports** sidebar link (or **Finance & Expenses → Reports** for Report Builder, Saved Views, Scheduled Reports). Time entries export is under **Time entries** (overview page). + --- ## Table of Contents diff --git a/docs/FRONTEND.md b/docs/FRONTEND.md new file mode 100644 index 00000000..833315e8 --- /dev/null +++ b/docs/FRONTEND.md @@ -0,0 +1,70 @@ +# TimeTracker Frontend Guide + +This document describes the main app frontend stack, component usage, and conventions. It does **not** cover the client portal or kiosk bases. + +## Stack + +- **Templates**: Jinja2 (Flask) +- **Styles**: Tailwind CSS (built from `app/static/src/input.css` → `app/static/dist/output.css`) +- **Design tokens**: CSS variables and Tailwind theme in `app/static/src/input.css` and `tailwind.config.js` +- **No React/Vue**: The app remains server-rendered with Jinja; use existing macros and minimal JS for behavior. + +References: [UI_IMPROVEMENTS_SUMMARY.md](implementation-notes/UI_IMPROVEMENTS_SUMMARY.md), [STYLING_CONSISTENCY_SUMMARY.md](implementation-notes/STYLING_CONSISTENCY_SUMMARY.md). + +## Base template and blocks + +- **Main app**: `app/templates/base.html` — provides ``, head (meta, CSS, scripts), skip link, sidebar, header, `
`, footer, and mobile bottom nav. +- **Blocks**: `title`, `content`, `extra_css`, `scripts_extra`, `head_extra`, etc. Page templates extend `base.html` and override these blocks. + +## Component usage + +**Primary source**: `app/templates/components/ui.html` (and `app/templates/components/cards.html` where used). Prefer these over legacy `_components.html`. + +### When to use which + +| Need | Macro / component | Import from | +|------|-------------------|-------------| +| Page title + subtitle + optional breadcrumbs and actions | `page_header(icon_class, title_text, subtitle_text=None, actions_html=None, breadcrumbs=None)` | `components/ui.html` | +| Breadcrumbs only | `breadcrumb_nav(items)` | `components/ui.html` | +| Summary / stat block | `stat_card(title, value, icon_class, color, trend=None, subtitle=None)` | `components/ui.html` or `components/cards.html` | +| Empty list / no results | `empty_state(...)` or `empty_state_compact(...)` with `type='no-data'` or `type='no-results'` | `components/ui.html` | +| Buttons | Use classes `.btn`, `.btn-primary`, `.btn-secondary`, `.btn-danger`, `.btn-ghost`, `.btn-sm`, `.btn-lg` from design system | `app/static/src/input.css` | +| Modals | `modal(id, title, content_html, footer_html=None, size)` | `components/ui.html` | +| Confirm (destructive) | `confirm_dialog(id, title, message, confirm_text, cancel_text, confirm_class)` | `components/ui.html` | +| Pagination | `pagination_nav(pagination, route_name, url_params=None, aria_label=None)` | `components/ui.html` | +| Forms | `form_group`, `form_select`, `form_textarea`, etc. | `components/ui.html` | + +### Empty states + +- Use **no-data** when the list is empty and no filters are applied (e.g. “No time entries yet”). +- Use **no-results** when filters are applied but nothing matches (e.g. “No time entries match your filters”). +- Prefer the macro over inline empty markup so messaging and CTAs stay consistent. + +## Buttons and forms + +- **Buttons**: Use design-system classes (`.btn`, `.btn-primary`, `.btn-secondary`, `.btn-danger`, `.btn-ghost`) so focus states and colors stay consistent. Avoid ad-hoc `bg-*` / `px-*` for primary actions. +- **Forms**: Use `form_group` and related form macros from `ui.html` so labels, `aria-required`, `aria-invalid`, and error blocks are consistent. Shared validation lives in `form-validation.js` / `form-validation.css`. + +## Modals + +- Use the **modal** or **confirm_dialog** macros from `components/ui.html` for new and refactored flows. +- Custom dialogs must provide: + - `role="dialog"` and `aria-modal="true"` + - `aria-labelledby` (and preferably `aria-describedby`) pointing to the title and description + - Focus trap when open (keep focus inside the dialog until closed). + +## Tables and pagination + +- **List tables**: Prefer `data-table-enhanced` (see `data-tables-enhanced.js` / `.css`) for sortable headers and consistent ARIA where applicable. +- **Responsive**: Use `responsive-cards` and `data-label` on cells for small screens. +- **Pagination**: Use the `pagination_nav` macro when possible; otherwise wrap pagination in a `