Skip to content

fix: repair broken trigger, driver, system and admin features - #315

Merged
MrYuion merged 19 commits into
developfrom
fix/broken-features
Sep 30, 2026
Merged

MrYuion merged 19 commits into
developfrom
fix/broken-features

Conversation

@MrYuion

@MrYuion MrYuion commented Sep 30, 2026

Copy link
Copy Markdown
Collaborator

Problem

Many features did not work. The main ones:

  • Weekly and yearly trigger schedules saved an invalid cron (m h * * -1). Editing a daily schedule turned it into every 9 hours. A custom cron saved within 1 s of typing stored * * * * *.
  • Clicking the date field in the trigger condition dialog reloaded the page.
  • The module form reset port and URI to the driver defaults on every edit.
  • A zone reorder on its own could not be saved.
  • Delete trigger instance, remove module from a driver and mailer reorder called the wrong thing.
  • Bulk adding groups to a user did nothing, because the modal result changed shape.
  • Tenant secret expiry colours were inverted, and the expiry banner never showed.
  • The offline banner never showed. ?lang=fr was ignored on first load.
  • Tab state carried over from one system to the next.

This is part of a stack of 6 PRs from a review of the whole app. Merge them in order: confirm-cancel, security, data loss, broken features, async errors, cleanup. Each PR targets the branch before it, so the diff shows only its own changes.

Fix

About 50 fixes, grouped by area in the commits. Some highlights:

  • Cron build and parse move to buildCronString and parseCronString in triggers.utilities.ts, with round-trip tests. The custom cron field writes at once.
  • Custom field buttons get type="button", and the condition form blocks native submit.
  • Driver defaults apply once for each driver.
  • The offline banner follows navigator.onLine as well as ts-client. The locale reads lang from the URL before translations load, and still loads the full browser tag (en-US.json).
  • SettingsService.value() is reactive for keys that have not been posted yet, so the banner renders.
  • Turning Outlook off sends outlook_config: {}. Staff API ignores null.
  • Tab components reset pending state when the item changes.
  • Zone lists load every page.

Also fixed while testing, and also broken on develop: the zone reorder highlight used the removed --wal variable, the diff viewer disposed models too early, and a repository could save with an empty branch.

Checks

  • tsc, bun run lint, bunx vitest run (1029 tests) pass. New tests cover cron building, tenant expiry, driver defaults, locale parsing and the empty branch check.
  • All 6 branches were merged and tested in a browser against a local PlaceOS stack (nightly images, with core and triggers). Test agents created their own records, checked results through the API, and removed the records after. Core compiled a driver, so module start and stop were tested live.

Made by Claude Opus 5.5 (1M context) in Claude Code (T3 Code).

🤖 Generated with Claude Code

MrYuion and others added 19 commits September 30, 2026 13:11
- Weekly and yearly schedules used indexOf on translated labels, which
  gave -1. Use the selected weekday and month values directly.
- Parsing set the day of month from the hour and mapped periods off by
  one. Move build/parse into tested helpers and remove the dead block.
- Fix the hour picker trigger label that printed the signal source.
- Cron input: fix the day range regex and allow Tab, Home/End and
  modifier shortcuts.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Instance delete passed the trigger instead of the row, and the state
  dot read `bookable` instead of `enabled`.
- Mailer reorder emitted the 'function' type.
- Zone instances were removed with the system API. Remove the trigger
  from the zone's trigger list instead.
- Derive the instance tab count from the state service so it refreshes.
- System trigger form used a missing `Trigger.*` locale key and allowed
  repeat submits while saving.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Remove driver modules with removeModule and reload the list.
- Show the update badge when any update exists, refresh it after an
  update, and replace the active driver with the saved response.
- Update list modal: sync total with the filtered list so select all
  and auto close work.
- Driver form: fall back to the raw commit id when it is not in the
  fetched list, always clear the spinner, and pre-select the repository
  and driver for new drivers.
- Docs tab: show the empty state after the readme loads instead of
  redirecting deep links away.
- Repository drivers: pass the driver row to the new driver form and
  stop navigating away when the list is empty.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Zones tab: make the reorder flag a signal so a reorder alone can be
  saved, mark the moved zone, and clear pending changes on system change.
- Triggers tab: drop the temp trigger merge that left ghost rows. The
  service already reloads the list.
- Modules tab: exclude modules already in the system by id and clear the
  pending module on system change.
- About tab: show the Public row based on `public`, not `email`.
- Module form: apply driver defaults once per driver so user edits stick.
- Module and system forms ignore repeat submits while
  saving.
- Module state: capture the active module before awaiting start/stop.
- Show the real module count in module and zone system lists.
- Modules view: import MatRippleModule instead of a duplicate icon.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Users: read `items` from the bulk add groups result and type the
  dialog, so bulk adding groups works again.
- Zones: page through systems and child zones so the lists match the
  tab counts, hide admin-only tabs for non-admins, show the timezone
  empty state from the filtered list, and clear the selected system
  when the zone changes.
- Groups: add a control to clear the parent group and lock the domain
  when editing an existing group.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Metadata details: stop passing a number as `change`, which threw on
  save and kept the dialog open. Type the dialog data.
- Metadata history: test the diff signals by value and update the diff
  on selection change, not option click.
- Duplicate: accept 1 to 50 whole duplicates, stop when the dialog
  closes, and track rows by index.
- Bulk add: count mapped fields from the mapping signal, reset mappings
  for a new upload, and block closing while items are created.
- Auth source: disable Save until a source type is chosen.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Staff API: expired and expiring checks were inverted. Move them into
  tested helpers.
- Resource imports: create systems 5 at a time, catch each failure, and
  replace rows so the zoneless table updates.
- Upload library: tolerate a cancelled permissions modal, bound the
  progress poll, show loading, and refresh the list after uploads.
- Tenant modal: show Outlook settings when a config exists and drop the
  config when the user turns it off.
- Cluster tasks: only accept an exact cluster id and remove a debug log.
- Date calendar: use the calendar year (`yyyy`) in the month header.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Tenant check read each tenant as an array of values, compared expiry
  the wrong way, overwrote one banner per tenant and had no catch. Show
  one banner for all expiring secrets.
- Uploads captured the token once and failed after a refresh. Pass the
  current token to the upload service before each upload.
- The offline banner read a plain getter. Use a signal from onlineState.
- Load translations before the shell renders, as TranslatePipe is pure,
  and set the matched locale id instead of the raw browser tag.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Matching locale ids such as 'en' have no locale file, so loading the
matched id fell back to bundled en-AU text for every browser.

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

- Custom cron wrote to the form after 1s, so a quick Save stored '* * * * *'.
- Buttons in custom fields had no type, so the date field submitted the
  condition form natively and reloaded the page. Set type="button" and
  prevent submit on the condition form.
- The remove instance confirm showed an empty name. Use the zone or
  system id, as the instance list does.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- onlineState only changes on auth, so also track the browser online state.
- Read ?lang from the URL before translations load, from both the hash
  query and the page search.
- SettingsService.value() did not track keys not yet posted, so the
  banner did not update after a later post.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Send outlook_config: null so the backend clears it, and read the toggle
from app_id as a cleared config is stored as { app_id: '' }.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A disabled branch field skips validation, so a failed branch load saved
an empty branch.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
staff-api ignores a null outlook_config, so send an empty one. The
system remove-module confirm now shows the module name, not its driver.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The backend strips empty values, so clearing the parent never saved.

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

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your trial has ended. Reactivate Greptile to resume code reviews.

@vercel

vercel Bot commented Sep 30, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
backoffice Ready Ready Preview Sep 30, 2026 3:24am UTC

Base automatically changed from fix/data-loss to develop September 30, 2026 04:49
@MrYuion
MrYuion merged commit 7fb3b8f into develop Sep 30, 2026
3 of 5 checks passed
@MrYuion
MrYuion deleted the fix/broken-features branch September 30, 2026 04:56

This branch was successfully deployed

1 active deployment
Preview — 9832af3a Deployed Sep 30, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant