# tom4711/easyredminetool architecture

> Architecture diagram of the GitHub repository tom4711/easyredminetool, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-08-03). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/tom4711/easyredminetool
- Repository: https://github.com/tom4711/easyredminetool

## Overview

#### Purpose and runtime
EasyRedmineTool is a cross-platform .NET 10 desktop client for Redmine/Easy Redmine. It manages tickets, creates time entries, stores favorites, plans recurring bookings, and summarizes weekly hours. Avalonia 12 provides the macOS, Windows, and Linux UI; Redmine’s REST API is the only stated external service.

#### Entry point and composition
The application starts in `src/EasyRedmineTool.Desktop/Program.cs`, initializes Avalonia through `src/EasyRedmineTool.Desktop/App.axaml`, and registers the object graph in `src/EasyRedmineTool.Desktop/DependencyInjection/ServiceCollectionExtensions.cs`. Desktop-specific composition owns shell navigation and platform presentation; reusable business/UI state lives in Core.

#### Desktop shell and presentation boundary
`src/EasyRedmineTool.Desktop/Views/MainWindow.axaml` hosts the feature views, coordinated by `src/EasyRedmineTool.Desktop/ViewModels/MainWindowViewModel.cs`. Feature screens bind Core view models for ticket list, time entries, weekly summary, settings, and series booking. Avalonia views should remain presentation adapters, rather than owning API or persistence behavior.

#### Core MVVM application layer
Core view models orchestrate user actions and expose bindable state: `src/EasyRedmineTool.Core/ViewModels/TicketListViewModel.cs`, `src/EasyRedmineTool.Core/ViewModels/TimeEntriesViewModel.cs`, and `src/EasyRedmineTool.Core/ViewModels/WeeklySummaryViewModel.cs`. They depend on service interfaces, translate service results into rows/form state, and connect flows such as selecting a ticket from the summary to time entry creation.

#### Redmine integration and service boundary
`src/EasyRedmineTool.Core/Api/EasyRedmineApiClient.cs` is the HTTP/JSON boundary to Redmine, behind `src/EasyRedmineTool.Core/Api/IEasyRedmineApiClient.cs`; API failures are represented by `src/EasyRedmineTool.Core/Api/RedmineApiException.cs`. Domain services encapsulate workflows: `src/EasyRedmineTool.Core/Services/TicketService.cs` loads and merges ticket data, while `src/EasyRedmineTool.Core/Services/TimeEntryService.cs` loads activities/entries and submits creates or updates. API DTOs and request/response models isolate Redmine payload shape from UI state.

#### Local settings, cache, and connection flow
`src/EasyRedmineTool.Core/Services/AppSettingsService.cs` persists base URL, API key, theme, cached tickets, favorites, and last-entry defaults in the per-user settings file. `src/EasyRedmineTool.Core/Services/ConnectionTestService.cs` validates configured credentials through the API boundary. Credentials are intentionally local but unencrypted; no secrets belong in repository state.

#### Planning and reporting transformations
Recurring booking intent is expanded into dated preview/actions by `src/EasyRedmineTool.Core/SeriesBookingPlanner.cs`, consumed through `src/EasyRedmineTool.Core/ViewModels/SeriesBookingViewModel.cs`. Loaded time entries are aggregated into quarterly calendar-week and ticket totals by `src/EasyRedmineTool.Core/WeeklySummaryBuilder.cs`. These are deterministic domain transformations separate from HTTP and Avalonia rendering.

#### Delivery
The solution is `EasyRedmineTool.slnx`; GitHub Actions in `.github/workflows/release.yml` produces self-contained platform artifacts and GitHub Releases. The app targets Windows x64, macOS x64/ARM64, and Linux x64/ARM64.

Main entry points: [`src/EasyRedmineTool.Desktop/Views/MainWindow.axaml`](https://github.com/tom4711/easyredminetool/blob/main/src/EasyRedmineTool.Desktop/Views/MainWindow.axaml) (Main window), [`src/EasyRedmineTool.Core/ViewModels/WeeklySummaryViewModel.cs`](https://github.com/tom4711/easyredminetool/blob/main/src/EasyRedmineTool.Core/ViewModels/WeeklySummaryViewModel.cs) (Weekly summary VM), [`src/EasyRedmineTool.Core/ViewModels/TimeEntriesViewModel.cs`](https://github.com/tom4711/easyredminetool/blob/main/src/EasyRedmineTool.Core/ViewModels/TimeEntriesViewModel.cs) (Time entries VM), [`src/EasyRedmineTool.Core/Services/TimeEntryService.cs`](https://github.com/tom4711/easyredminetool/blob/main/src/EasyRedmineTool.Core/Services/TimeEntryService.cs) (Time entry service)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_desktop["Desktop host"]
  node_program["Program<br/>desktop entry point<br/>[Program.cs]"]
  node_app["Avalonia app<br/>application bootstrap<br/>[App.axaml]"]
  node_di{{"Service registration<br/>DI composition"}}
  node_main_window["Main window<br/>Avalonia shell view<br/>[MainWindow.axaml]"]
  node_main_vm["Main window VM<br/>shell navigation"]
end

subgraph group_application["Core application"]
  node_ticket_vm["Ticket list VM<br/>Core view model"]
  node_entries_vm["Time entries VM<br/>Core view model"]
  node_summary_vm["Weekly summary VM<br/>Core view model"]
  node_series_vm["Series booking VM<br/>Core view model"]
end

subgraph group_domain["Domain workflows"]
  node_ticket_service["Ticket service<br/>domain service<br/>[TicketService.cs]"]
  node_entry_service["Time entry service<br/>domain service"]
  node_planner["Series booking planner<br/>domain transformation"]
  node_summary_builder["Weekly summary builder<br/>domain transformation"]
  node_connection_service["Connection test service<br/>domain service"]
end

subgraph group_integration["Integration and storage"]
  node_api_contract{{"Redmine API contract<br/>client interface"}}
  node_api_client["Redmine API client<br/>HTTP/JSON adapter"]
  node_settings[("App settings service<br/>local persistence")]
end

subgraph group_delivery["Delivery"]
  node_release{{"Release workflow<br/>GitHub Actions pipeline<br/>[release.yml]"}}
end

node_redmine(("Redmine REST API<br/>external service"))

node_program -->|"initializes"| node_app
node_app -->|"builds services"| node_di
node_di -->|"composes"| node_main_window
node_main_window -->|"binds shell"| node_main_vm
node_main_window -->|"hosts feature"| node_ticket_vm
node_main_window -->|"hosts feature"| node_entries_vm
node_main_window -->|"hosts feature"| node_summary_vm
node_main_window -->|"hosts feature"| node_series_vm
node_ticket_vm -->|"loads tickets"| node_ticket_service
node_entries_vm -->|"manages entries"| node_entry_service
node_summary_vm -->|"loads entries"| node_entry_service
node_summary_vm -->|"builds totals"| node_summary_builder
node_summary_vm -.->|"selects ticket for entry"| node_entries_vm
node_series_vm -->|"creates dated plan"| node_planner
node_series_vm -->|"submits planned entries"| node_entry_service
node_ticket_service -->|"uses"| node_api_contract
node_entry_service -->|"uses"| node_api_contract
node_connection_service -->|"tests credentials"| node_api_contract
node_api_client -->|"implements"| node_api_contract
node_api_client -->|"HTTP/JSON"| node_redmine
node_ticket_service -->|"reads cache and favorites"| node_settings
node_entries_vm -->|"uses entry defaults"| node_settings
node_connection_service -->|"reads connection settings"| node_settings

click node_program "https://github.com/tom4711/easyredminetool/blob/main/src/EasyRedmineTool.Desktop/Program.cs"
click node_app "https://github.com/tom4711/easyredminetool/blob/main/src/EasyRedmineTool.Desktop/App.axaml"
click node_di "https://github.com/tom4711/easyredminetool/blob/main/src/EasyRedmineTool.Desktop/DependencyInjection/ServiceCollectionExtensions.cs"
click node_main_window "https://github.com/tom4711/easyredminetool/blob/main/src/EasyRedmineTool.Desktop/Views/MainWindow.axaml"
click node_main_vm "https://github.com/tom4711/easyredminetool/blob/main/src/EasyRedmineTool.Desktop/ViewModels/MainWindowViewModel.cs"
click node_ticket_vm "https://github.com/tom4711/easyredminetool/blob/main/src/EasyRedmineTool.Core/ViewModels/TicketListViewModel.cs"
click node_entries_vm "https://github.com/tom4711/easyredminetool/blob/main/src/EasyRedmineTool.Core/ViewModels/TimeEntriesViewModel.cs"
click node_summary_vm "https://github.com/tom4711/easyredminetool/blob/main/src/EasyRedmineTool.Core/ViewModels/WeeklySummaryViewModel.cs"
click node_series_vm "https://github.com/tom4711/easyredminetool/blob/main/src/EasyRedmineTool.Core/ViewModels/SeriesBookingViewModel.cs"
click node_ticket_service "https://github.com/tom4711/easyredminetool/blob/main/src/EasyRedmineTool.Core/Services/TicketService.cs"
click node_entry_service "https://github.com/tom4711/easyredminetool/blob/main/src/EasyRedmineTool.Core/Services/TimeEntryService.cs"
click node_planner "https://github.com/tom4711/easyredminetool/blob/main/src/EasyRedmineTool.Core/SeriesBookingPlanner.cs"
click node_summary_builder "https://github.com/tom4711/easyredminetool/blob/main/src/EasyRedmineTool.Core/WeeklySummaryBuilder.cs"
click node_connection_service "https://github.com/tom4711/easyredminetool/blob/main/src/EasyRedmineTool.Core/Services/ConnectionTestService.cs"
click node_api_contract "https://github.com/tom4711/easyredminetool/blob/main/src/EasyRedmineTool.Core/Api/IEasyRedmineApiClient.cs"
click node_api_client "https://github.com/tom4711/easyredminetool/blob/main/src/EasyRedmineTool.Core/Api/EasyRedmineApiClient.cs"
click node_settings "https://github.com/tom4711/easyredminetool/blob/main/src/EasyRedmineTool.Core/Services/AppSettingsService.cs"
click node_release "https://github.com/tom4711/easyredminetool/blob/main/.github/workflows/release.yml"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_program,node_app,node_di,node_main_window,node_main_vm toneBlue
class node_ticket_vm,node_entries_vm,node_summary_vm,node_series_vm toneAmber
class node_ticket_service,node_entry_service,node_planner,node_summary_builder,node_connection_service toneMint
class node_api_contract,node_api_client,node_settings toneRose
class node_release toneIndigo
class node_redmine toneNeutral
```

## Components

### Desktop host

Avalonia startup, composition, and shell presentation.

- [Program](https://github.com/tom4711/easyredminetool/blob/main/src/EasyRedmineTool.Desktop/Program.cs): desktop entry point · `src/EasyRedmineTool.Desktop/Program.cs`
- [Avalonia app](https://github.com/tom4711/easyredminetool/blob/main/src/EasyRedmineTool.Desktop/App.axaml): application bootstrap · `src/EasyRedmineTool.Desktop/App.axaml`
- [Service registration](https://github.com/tom4711/easyredminetool/blob/main/src/EasyRedmineTool.Desktop/DependencyInjection/ServiceCollectionExtensions.cs): DI composition · Connects desktop presentation to Core services and view models. · `src/EasyRedmineTool.Desktop/DependencyInjection/ServiceCollectionExtensions.cs`
- [Main window](https://github.com/tom4711/easyredminetool/blob/main/src/EasyRedmineTool.Desktop/Views/MainWindow.axaml): Avalonia shell view · Hosts feature views. · `src/EasyRedmineTool.Desktop/Views/MainWindow.axaml`
- [Main window VM](https://github.com/tom4711/easyredminetool/blob/main/src/EasyRedmineTool.Desktop/ViewModels/MainWindowViewModel.cs): shell navigation · `src/EasyRedmineTool.Desktop/ViewModels/MainWindowViewModel.cs`

### Core application

MVVM state and user-facing workflows.

- [Ticket list VM](https://github.com/tom4711/easyredminetool/blob/main/src/EasyRedmineTool.Core/ViewModels/TicketListViewModel.cs): Core view model · `src/EasyRedmineTool.Core/ViewModels/TicketListViewModel.cs`
- [Time entries VM](https://github.com/tom4711/easyredminetool/blob/main/src/EasyRedmineTool.Core/ViewModels/TimeEntriesViewModel.cs): Core view model · `src/EasyRedmineTool.Core/ViewModels/TimeEntriesViewModel.cs`
- [Weekly summary VM](https://github.com/tom4711/easyredminetool/blob/main/src/EasyRedmineTool.Core/ViewModels/WeeklySummaryViewModel.cs): Core view model · Can route a selected ticket into time-entry creation. · `src/EasyRedmineTool.Core/ViewModels/WeeklySummaryViewModel.cs`
- [Series booking VM](https://github.com/tom4711/easyredminetool/blob/main/src/EasyRedmineTool.Core/ViewModels/SeriesBookingViewModel.cs): Core view model · `src/EasyRedmineTool.Core/ViewModels/SeriesBookingViewModel.cs`

### Domain workflows

Service orchestration and deterministic transformations.

- [Ticket service](https://github.com/tom4711/easyredminetool/blob/main/src/EasyRedmineTool.Core/Services/TicketService.cs): domain service · Loads and merges ticket data. · `src/EasyRedmineTool.Core/Services/TicketService.cs`
- [Time entry service](https://github.com/tom4711/easyredminetool/blob/main/src/EasyRedmineTool.Core/Services/TimeEntryService.cs): domain service · Loads activities and entries; submits creates and updates. · `src/EasyRedmineTool.Core/Services/TimeEntryService.cs`
- [Series booking planner](https://github.com/tom4711/easyredminetool/blob/main/src/EasyRedmineTool.Core/SeriesBookingPlanner.cs): domain transformation · Expands recurring intent into dated previews and actions. · `src/EasyRedmineTool.Core/SeriesBookingPlanner.cs`
- [Weekly summary builder](https://github.com/tom4711/easyredminetool/blob/main/src/EasyRedmineTool.Core/WeeklySummaryBuilder.cs): domain transformation · Aggregates entries into calendar-week and ticket totals. · `src/EasyRedmineTool.Core/WeeklySummaryBuilder.cs`
- [Connection test service](https://github.com/tom4711/easyredminetool/blob/main/src/EasyRedmineTool.Core/Services/ConnectionTestService.cs): domain service · Validates configured credentials through the API boundary. · `src/EasyRedmineTool.Core/Services/ConnectionTestService.cs`

### Integration and storage

Redmine HTTP boundary and per-user settings.

- [Redmine API contract](https://github.com/tom4711/easyredminetool/blob/main/src/EasyRedmineTool.Core/Api/IEasyRedmineApiClient.cs): client interface · Abstraction used by Core services. · `src/EasyRedmineTool.Core/Api/IEasyRedmineApiClient.cs`
- [Redmine API client](https://github.com/tom4711/easyredminetool/blob/main/src/EasyRedmineTool.Core/Api/EasyRedmineApiClient.cs): HTTP/JSON adapter · Isolates Redmine payloads and API failures from UI state. · `src/EasyRedmineTool.Core/Api/EasyRedmineApiClient.cs`
- [App settings service](https://github.com/tom4711/easyredminetool/blob/main/src/EasyRedmineTool.Core/Services/AppSettingsService.cs): local persistence · Persists connection settings, cache, favorites, theme, and entry defaults per user. · `src/EasyRedmineTool.Core/Services/AppSettingsService.cs`

### Delivery

Cross-platform release packaging.

- [Release workflow](https://github.com/tom4711/easyredminetool/blob/main/.github/workflows/release.yml): GitHub Actions pipeline · Builds self-contained artifacts and GitHub Releases for five target platforms. · `.github/workflows/release.yml`

### Other components

- **Redmine REST API**: external service

## Connections

- Program → Avalonia app: initializes
- Avalonia app → Service registration: builds services
- Service registration → Main window: composes
- Main window → Main window VM: binds shell
- Main window → Ticket list VM: hosts feature
- Main window → Time entries VM: hosts feature
- Main window → Weekly summary VM: hosts feature
- Main window → Series booking VM: hosts feature
- Ticket list VM → Ticket service: loads tickets
- Time entries VM → Time entry service: manages entries
- Weekly summary VM → Time entry service: loads entries
- Weekly summary VM → Weekly summary builder: builds totals
- Weekly summary VM → Time entries VM: selects ticket for entry
- Series booking VM → Series booking planner: creates dated plan
- Series booking VM → Time entry service: submits planned entries
- Ticket service → Redmine API contract: uses
- Time entry service → Redmine API contract: uses
- Connection test service → Redmine API contract: tests credentials
- Redmine API client → Redmine API contract: implements
- Redmine API client → Redmine REST API: HTTP/JSON
- Ticket service → App settings service: reads cache and favorites
- Time entries VM → App settings service: uses entry defaults
- Connection test service → App settings service: reads connection settings
