block / block/proto-fleet

Server-driven building-clear preview on AssignRacksToSite

Open
#492 0 comments 0 reactions 0 assignees View on GitHub
client enhancement multi-site server
Dominant language
Go
Stars
55
Forks
16
Avg merge
1d 22h
Merged PRs (30d)
87

Description

## Context

PR #489 adds a client-side detection + confirm dialog for the cross-site building clear in `AssignRacksToSite`: when an operator picks "Add to site" on a rack list selection and any selected rack's current building belongs to a different site, the client opens a "Move racks between sites?" dialog before dispatching.

That detection lives entirely in the browser, using `allBuildings` (already loaded for the building filter chip) cross-referenced against each rack's `building_id`. It works, but it's structurally asymmetric with the `AssignDevicesToBuilding` flow shipped in the same PR — that one is server-driven: the server returns `PerDeviceBuildingConflict[]` on a no-force call and the client retries with `force_clear_conflicting_rack_membership=true`.

The asymmetry isn't load-bearing today (worst case is a missed or stale dialog; server still cascades correctly), but server-driven is the right shape for consistency and for closing the stale-`allBuildings` window where one operator's cached state could mislabel another operator's concurrent building move.

## Proposed change

Add `optional bool force_clear_building` to `AssignRacksToSiteRequest` and a `repeated RackBuildingClearPreview previews` field to the response. When `!force` and any rack would have its `building_id` cleared (current building lives at a different site than the target), the server returns the preview list with zero writes. Client opens the same dialog (now driven by the server's response), then retries with `force=true`.

Same shape as the `AssignDevicesToSite` / `AssignDevicesToBuilding` conflict pattern.

## Sketch of work

- `proto/sites/v1/sites.proto` — new field + new message.
- `server/internal/domain/sites/{service,models}.go` — Phase A captures per-rack `(rack_id, building_id)` instead of just incrementing `clearedCount`; on no-force + any preview, return early with zero writes.
- `server/internal/handlers/sites/{handler,translate}.go` — pass `ForceClearBuilding`, translate previews to proto.
- `client/src/protoFleet/api/sites.ts` — add `forceClearBuilding` prop; surface previews via the existing `onError` channel.
- `client/.../pages/RacksPage.tsx` — delete `summarizeBuildingClearance` + the inline state machine; replace with the no-force → preview → force-retry flow (resolve building labels client-side from `buildingNameById`).
- Tests: update existing `AssignRacksToSite` service + handler tests to expect the new force flag; add a preview-path test.

Estimate: ~9 hand-edited files, ~200 LOC net, ~30–45 min including test updates and proto regen.

## Open question

Once Option A lands here, the same pattern probably wants to apply to `AssignBuildingsToSite` (silently re-stamps every rack + device under the moved buildings; no preview). Worth deciding in one place whether every silent cascade across a site boundary should be gated by a confirm dialog.

Contributor guide

Open the contributing guide

Research direction

Start with the existing AssignDevicesToSite and AssignDevicesToBuilding conflict flows, then read proto/sites/v1/sites.proto and the listed server service, model, handler, and translation files. Trace the current AssignRacksToSite client flow in client/src/protoFleet/api/sites.ts and RacksPage.tsx, and run the existing service and handler tests. Done means the no-force path previews without writes, the client confirms and retries with force, and the updated tests pass.

Written by the indexing model from the issue text.

Assessment

Tech stack
go, react, typescript
Domain
api, backend-api-design, full-stack
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.