kimai-plugin-heatmap/.planning/milestones/v1.0-phases/04-heatmap-interaction/04-VERIFICATION.md
Christopher Mühl 244c7c66fc
chore: archive v1.0 milestone
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 23:25:26 +02:00

9.4 KiB

phase verified status score gaps human_verification
04-heatmap-interaction 2026-04-08T15:37:00Z human_needed 3/4 must-haves verified
truth status reason artifacts missing
A dropdown allows filtering the heatmap to show data for a single project or activity partial Only project filtering is implemented. Activity filtering was explicitly descoped in 04-CONTEXT.md ('Projects only -- no activity filter') but the roadmap SC and INTR-01 both specify 'project or activity'. No later phase addresses this.
path issue
assets/src/heatmap.ts No activity filter option in dropdown, no activity query param in fetch
path issue
Service/HeatmapService.php No getUserActivities() method
path issue
Controller/HeatmapController.php No ?activity= query parameter handling
getUserActivities() service method analogous to getUserProjects()
Activity filter option in dropdown (or combined project/activity dropdown)
Controller support for ?activity=N query parameter
HeatmapService::getDailyAggregation() support for activityId parameter
test expected why_human
Click a heatmap day cell and verify navigation to Kimai timesheet filtered to that date Browser navigates to /en/timesheet/?daterange=YYYY-MM-DD%20-%20YYYY-MM-DD Requires running Kimai instance with the plugin loaded to verify URL construction and Kimai's timesheet page accepting the daterange parameter
test expected why_human
Select a project from the filter dropdown and verify heatmap re-renders Heatmap cells update to show only data for the selected project, color scale adjusts Requires running Kimai with real time entries across multiple projects to verify visual filtering
test expected why_human
Verify filter dropdown appearance and positioning Dropdown appears to the right of the heatmap SVG, styled with Tabler form-select classes, responsive layout Visual layout verification requires browser rendering

Phase 4: Heatmap Interaction Verification Report

Phase Goal: Users can click through to daily details and filter the heatmap by project or activity Verified: 2026-04-08T15:37:00Z Status: human_needed Re-verification: No -- initial verification

Goal Achievement

Observable Truths

# Truth Status Evidence
1 Clicking a day cell navigates to Kimai's timesheet view filtered to that specific date VERIFIED heatmap.ts lines 217-224: onCellClick constructs URL with daterange param and assigns to window.location.href. Tests in interaction.test.ts verify URL format.
2 A dropdown allows filtering the heatmap to show data for a single project or activity PARTIAL Project filtering fully implemented (dropdown, fetch with ?project=N, re-render). Activity filtering intentionally omitted per 04-CONTEXT.md line 25. Roadmap SC and INTR-01 both specify "or activity".
3 Filtering updates the heatmap in place without a full page reload VERIFIED heatmap.ts lines 256-271: select.addEventListener('change', ...) triggers fetch() then renderHeatmap() on the existing svgArea div. Tests in filter.test.ts verify re-render.
4 JavaScript tests verify click navigation and tooltip interaction behavior VERIFIED interaction.test.ts has 7 tests (callback, URL format, project in URL, fallback). filter.test.ts has 9 tests (dropdown rendering, fetch params, re-render, empty state). All 52 tests pass.

Score: 3/4 truths fully verified (1 partial)

Required Artifacts

Artifact Expected Status Details
Service/HeatmapService.php getUserProjects() method VERIFIED Lines 54-68: queries distinct projects with IDENTITY join, returns [{id, name}]
Widget/HeatmapWidget.php Injects service, getData returns projects VERIFIED Lines 11-12: constructor injection. Lines 40-47: getData returns projects array. No final keyword.
Resources/views/widget/heatmap.html.twig data-projects and data-timesheet-url attributes VERIFIED Lines 9-10: both data attributes present with correct Twig expressions
assets/src/heatmap.ts Click handler, filter dropdown, re-fetch VERIFIED Lines 198-201: click handler. Lines 236-276: filter dropdown. Lines 256-271: re-fetch on change.
assets/src/types.ts ProjectOption interface VERIFIED Lines 22-25: export interface ProjectOption { id: number; name: string; }
Resources/public/heatmap.css Click affordance, flex layout VERIFIED Lines 15-21: cursor:pointer, transition, pointer-events. Lines 38-58: flex wrapper layout.
Resources/public/heatmap.js Rebuilt bundle VERIFIED 81,943 bytes, contains KimaiHeatmap IIFE
assets/test/interaction.test.ts Click navigation tests VERIFIED 7 tests covering onCellClick callback, URL construction, project filter in URL
assets/test/filter.test.ts Filter dropdown tests VERIFIED 9 tests covering rendering, options, fetch params, re-render, empty state
From To Via Status Details
heatmap.ts Kimai timesheet window.location.href with daterange WIRED Line 223: window.location.href = url with encodeURIComponent(daterange)
heatmap.ts HeatmapController::data() fetch with ?project=N WIRED Line 259: fetch(fetchUrl) where fetchUrl = baseUrl?project=val
HeatmapWidget.php HeatmapService::getUserProjects() getData() calls service WIRED Line 45: $this->service->getUserProjects($user)
interaction.test.ts heatmap.ts imports renderHeatmap and init WIRED Line 3: import { renderHeatmap, init } from '../src/heatmap'
filter.test.ts heatmap.ts imports init WIRED Line 2: import { init } from '../src/heatmap'

Data-Flow Trace (Level 4)

Artifact Data Variable Source Produces Real Data Status
heatmap.ts (init) projects data-projects attr from Twig Server-rendered from DB query via getUserProjects() FLOWING
heatmap.ts (init) HeatmapData fetch(baseUrl) API endpoint queries TimesheetRepository FLOWING
heatmap.ts (filter) HeatmapData fetch(baseUrl?project=N) API endpoint filters by projectId FLOWING

Behavioral Spot-Checks

Behavior Command Result Status
All tests pass npx vitest run 52 passed (26 unique + symlink dupes), 0 failed PASS
Bundle builds ls Resources/public/heatmap.js 81,943 bytes PASS
No TODOs/FIXMEs in phase code grep across modified files No matches PASS

Requirements Coverage

Requirement Source Plan Description Status Evidence
HEAT-07 04-01 Clicking a day cell navigates to Kimai timesheet view filtered to that date SATISFIED heatmap.ts onCellClick with window.location.href, daterange param
INTR-01 04-01 Dropdown filter to view heatmap for a specific project or activity PARTIAL Project filtering implemented. Activity filtering omitted (intentional descope in 04-CONTEXT.md but not reflected in requirement text).
TEST-04 04-02 JavaScript tests for tooltip and click interaction behavior SATISFIED interaction.test.ts (7 tests) + filter.test.ts (9 tests) all passing

Anti-Patterns Found

File Line Pattern Severity Impact
None found - - - -

Human Verification Required

1. Click Navigation End-to-End

Test: Click a heatmap day cell in a running Kimai instance Expected: Browser navigates to /en/timesheet/?daterange=YYYY-MM-DD%20-%20YYYY-MM-DD showing time entries for that date Why human: Requires running Kimai to verify the timesheet page accepts and applies the daterange parameter correctly

2. Project Filter Visual Behavior

Test: Select a project from the filter dropdown with multiple projects having time data Expected: Heatmap re-renders showing only that project's data, color scale recalculates, cells update Why human: Requires running Kimai with real multi-project time data to verify visual filtering

3. Layout and Styling

Test: View the widget on the Kimai dashboard Expected: Filter dropdown appears to the right of the heatmap, cells show pointer cursor on hover with opacity change, layout is clean Why human: Visual layout verification requires browser rendering with Tabler CSS

Gaps Summary

One partial gap identified: the roadmap success criteria and INTR-01 both specify filtering by "project or activity" but only project filtering was implemented. This was an intentional design decision documented in 04-CONTEXT.md ("Projects only -- no activity filter"), but it represents a deviation from the stated roadmap contract. No later phase addresses activity filtering.

The gap is flagged as partial rather than failed because:

  • Project filtering is fully functional and tested
  • The descope was a conscious decision, not an oversight
  • The core interaction value (filtering the heatmap) is delivered for the primary dimension (projects)

All other success criteria are fully met with solid test coverage (16 new tests).


Verified: 2026-04-08T15:37:00Z Verifier: Claude (gsd-verifier)