Skip to content

Data engagement: reporting links, group stats, Fixometer fixes (#919) - #926

Open
edwh wants to merge 14 commits into
developfrom
data-engagement-919
Open

edwh wants to merge 14 commits into
developfrom
data-engagement-919

Conversation

@edwh

@edwh edwh commented Sep 30, 2026 •

Copy link
Copy Markdown
Collaborator

Implements the code changes for #919 (sub-issues #920–#925). The Metabase reports and dashboards live outside this repo. Each sub-issue has a write-up with screenshots.

What changes

Reporting links — #920, #921

  • Networks have a reporting dashboard address (networks.reporting_url, new migration). Only administrators can set it, on the network edit page. When it's set, the network page links to it in two places: Network actions → View reports, and a "See more in your network's reports" link under the impact figures.
  • Groups link to the group reporting dashboard, filtered to that group. The links are in Group actions → View reports and under the group stats.
    • There's one dashboard per language: GROUP_REPORTING_URL_EN and GROUP_REPORTING_URL_FR.
    • A group uses the default language of its network. A regional language such as fr-BE uses its base language. Anything else falls back to English.
    • {group} and {group_name} in the address are filled in.
    • Group members and the people who look after the group see the link. Without a dashboard address there's no link.

Group page stats — #922

  • Device breakdown is removed, along with the queries that fed it. Most repaired devices is renamed Most repaired items, here and on the admin stats page. It now includes unpowered categories, leaving out both "None of the above" ones.
  • Three layouts are on the page for Neil and James to compare. ?stats_layout=compact (the default), after or split picks one. The other two, and the option, go once one is chosen.

Fixometer headline stats — #923

  • Powered/unpowered items fixed and years of time volunteered have their new labels.
  • New events held figure: past events that weren't cancelled, in approved groups.
  • New items seen figure: every item recorded.
  • "See more analysis in our further reports." links to FIXOMETER_REPORTING_URL. It doesn't appear when that isn't set.
  • The homepage stats cache key is now homepage_data_v3, so the new figures appear straight after deploy.

Fixometer repair records — #924

  • One list. Powered and unpowered records are in one list. Before, they were in separate tabs. A Powered or unpowered select (Both, Powered, Unpowered) filters it. The item entry on event pages keeps its tabs.
  • Filters. The order is Powered or unpowered, Category, Item ("What is it?"), Brand, Model, Assessment, Repair status. Brand and Model show for every type of item. The 'i' icons are gone from the filters and from expanded records, but stay on data entry.
  • Fixes. Sorting uses the column clicked. The status filter works. The To date includes that day and now defaults to today. Deleted events are left out. Expanding a record shows its details.
  • Table. The date is the event date and links to that event's items. Status comes before Group. The list is white again, without the how-to text.
  • Old ?category_powered= / ?category_unpowered= links still work.

Repair data download — #925

  • Download all data is shown to everyone.
  • export:repair-data builds the full file at public/exports/repair-data.csv, holding what anyone can see. The web server sends it directly, as compressed CSV, without going through PHP.
  • The command runs hourly, but rebuilds at most once a day, and only when repairs, events or groups have changed. A new server gets the file within the hour; until then, the button uses the live export.
  • The CSV writing moved into App\Services\RepairDataExport, which the per-event and per-group exports share. The query applies User::userCanSeeEvent()'s visibility rules and works in chunks.

Screenshots

Fixometer (#923, #924)
Fixometer

Group page, compact layout (#921, #922). The other layouts are on #922.
Group compact

Network impact with the reports link (#920)
Network

Tests

  • PHPUnit: reporting links (per language, fallbacks, group name), events held and items seen, most repaired items, the repair records API, and the export file (what's in it, the once-a-day rule, skipping when nothing changed, the Fixometer button).
  • Jest: the Fixometer filters, records table and headline; group stats layouts; network page link.
  • Checked on the preview with production data: the export built in 44 seconds (40 MB), and it's served as compressed CSV.

For the code review

  • /api/devices without powered returns both powered and unpowered records. Before, it returned unpowered only. The Vue client is the only known caller.
  • Production needs GROUP_REPORTING_URL_EN (and later _FR) and FIXOMETER_REPORTING_URL set for those links to appear.
  • GROUP_REPORTING_URL is no longer read. It isn't set in production (checked the Fly secrets).

Reporting links (#920, #921)
- Networks have a reporting dashboard address (new networks.reporting_url
  column), set by administrators on the network edit page and linked from the
  network actions menu.
- Groups link to the group reporting dashboard, filtered to the group, from
  the group actions menu and the stats section. The address comes from
  GROUP_REPORTING_URL, with {group} replaced by the group id; members of the
  group and those who look after it see the link.

Group page stats (#922)
- Items worked on and most repaired items sit alongside group achievements
  and environmental impact; the device breakdown section is gone, along with
  the queries that fed it.
- "Most repaired devices" is now "Most repaired items".

Fixometer headline stats (#923)
- Powered/unpowered figures say they are items fixed.
- "years volunteered" is now "years of time volunteered".
- Adds the number of events held.

Fixometer repair records (#924)
- One list of powered and unpowered items, with a powered/unpowered filter.
- Sorting uses the column clicked; the API maps table columns to database
  columns and ignores anything else.
- The status filter works (the API accepts the status names the client sends).
- The "to" date includes events on that day; deleted events are left out.
- Expanding a record shows its details instead of empty fields.
- The date column is the event date, and records keep their own dates rather
  than those of the joined tables.

Repair data download (#925)
- Everyone can download the repair records from the Fixometer page.
- The export checks visibility in the query and loads events and groups with
  the devices, in chunks, rather than querying each event and group in turn.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Comment thread tests/Feature/Events/ExportDevicesQueryCountTest.php Fixed
@ngm

ngm commented Sep 30, 2026

Copy link
Copy Markdown
Contributor

@edwh That's great, thanks - but can we move the discussion about each of the items to the related sub-issue?

edwh and others added 2 commits September 30, 2026 18:56
Split the device list filters out of getDevices(), make the record details
toggle a button so it works from the keyboard, and tidy the new tests.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@edwh

edwh commented Sep 30, 2026

Copy link
Copy Markdown
Collaborator Author

@ngm Done - each sub-issue now has a comment with what this PR does for it, its screenshots, and the points to discuss: #920, #921, #922, #923, #924, #925. The PR description now just points to them.

There's also a preview of this PR on production data at https://restarters-pr-926.fly.dev (it's being deployed now), which is the place to try the repair records list and time the full download (#925).

@github-actions

github-actions Bot commented Sep 30, 2026 •

Copy link
Copy Markdown

Preview: https://restarters-pr-926.fly.dev

✅ Ready - restore and migrations succeeded.

  • Password-protected test environment (usual dev gate password); commit f68ad0ed62d28b33be0e09cd70f3f975c7031101 merged with develop.
  • If you see a "warming up" page, give it a few minutes - it refreshes itself.
  • The preview database is refreshed on every deploy and may reset at any time; anything you create here is disposable.
  • Emails go to shared Mailpit, never to real recipients. Image uploads are disabled.
  • The app suspends when idle; the first request after a pause can take a moment.

edwh and others added 7 commits October 1, 2026 17:04
GROUP_REPORTING_URL becomes GROUP_REPORTING_URL_EN and _FR, because
Metabase can only show a dashboard in another language as a separate
dashboard. A group gets the one for its network's default language,
falling back to English. The address can include {group_name} as well
as {group}.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…#923)

- Events held leaves out cancelled events and those of unapproved groups.
- New total items seen figure, left of powered items fixed, which fills
  the gap in the desktop grid.
- 'See more analysis in our further reports.' after the estimates note,
  linking to FIXOMETER_REPORTING_URL. No sentence when it isn't set.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Filters in the order Powered or unpowered, Category, Item, Brand,
  Model, Assessment, Repair status. Brand and model stay for unpowered
  items, since they can be recorded for them too.
- Powered or unpowered is a select like the others, defaulting to Both.
- The Item filter asks 'What is it?', as on data capture.
- No info icons in the filters or on an expanded record - they explain
  what to enter, which doesn't apply here. They stay on data capture.
- Status before Group; the event date links to that event's items.
- White background again; the how-to-use-the-table text is gone.
- The To date defaults to today, so records from mis-dated future
  events don't head the list. Today isn't written into the URL.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Leaves out both 'None of the above' categories.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
?stats_layout= picks one:
- compact (default): all before the events, achievements over impact
  beside items worked on over most repaired, without the note on what
  the impact leaves out.
- after: all after the events.
- split: achievements and impact before the events, items after - the
  original layout.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
# Conflicts:
#	resources/js/components/FixometerRecordsTable.vue
export:repair-data writes what anyone can see to
public/exports/repair-data.csv, which nginx serves directly (and now
gzips). It runs hourly but rebuilds at most once a day, and only when
repairs, events or groups have changed. Hourly means a new machine,
which starts without the file, has it within the hour; until then the
Fixometer button falls back to the live export.

The CSV writing moves from ExportController into RepairDataExport so
the command and the per-event/group exports share it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@edwh
edwh deployed to preview October 1, 2026 16:43 — with GitHub Actions Active
edwh and others added 3 commits October 1, 2026 18:00
…ard (#921)

Repair Together's network language is fr-BE, which would otherwise fall
back to the English dashboard.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
nginx's mime types don't know .csv, so the file went out as
application/octet-stream and uncompressed. Checked on the #926 preview:
a GET now comes back as text/csv with gzip.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
edwh added a commit that referenced this pull request Oct 1, 2026
@edwh
edwh deployed to preview October 1, 2026 17:05 — with GitHub Actions Active
@sonarqubecloud

sonarqubecloud Bot commented Oct 1, 2026

Copy link
Copy Markdown

This branch was successfully deployed

1 active deployment
preview — f68ad0ed Deployed Oct 1, 2026 by edwh via Deploy preview #524
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

preview Deploy a Fly.io preview for this PR

Projects

None yet

3 participants