fix: repair the app shell, and stop querying per table row - #8
Merged
Merged
Conversation
@lattice-php/ui/css sources its own dist and the Vite plugin sources every discovered component package, but neither covers the sibling runtime packages. @lattice-php/core owns the responsive-visibility wrapper (`hidden md:contents`), so `md:contents` was never generated and every visibleFrom()/hiddenFrom() node stayed hidden at all widths — silently, since the class simply did not exist. The same glob restores the table header and cell utilities that only appear in the table package's dist, which is why the members and invitations tables rendered without a header row.
The sidebar was collapsible but nothing could toggle it, and Lattice ships no trigger of its own — below the md breakpoint the drawer stayed shut, so a phone had no team switcher, no navigation and no way to log out. A topbar now carries the toggle, the breadcrumb trail, and the user menu. DashboardPage has declared breadcrumbs() since it was written, but no layout ever rendered a Breadcrumbs node, so the trail was dead code. Callouts joins it so an effect flashed from a controller or listener has somewhere to land.
TeamsTable asked teamRole() for a role the membership pivot had already loaded — 8 queries for 6 teams. User::teams() now uses the Membership pivot class, so the cast role is read straight off the row: 1 query. TeamMembersTable and TeamInvitationsTable ran their policy checks inside actions(), which a table calls once per row: 13 queries for 6 members. The new AuthorizesRowActions concern caches the answer on the definition instance, which lives exactly one render — 2 queries, one per ability. Caching on the User model instead looked tempting and is wrong: a later attach() leaves it stale, which is exactly what the suite caught.
Four pages repeated the same layout and middleware; AppPage carries them and the notification listeners, leaving each page its own route, name and gate. SettingsPage overrides the middleware to drop `verified` — its profile tab is where an unverified user resends the mail. PageHeader replaces ten hand-built heading-plus-lead stacks, and TeamPage and TeamsPage gain the breadcrumbs the new trail can now show.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up to #7, taking the same pass over the teams surface. Three real bugs, one performance fix, and the deduplication that fell out of them. No new features.
Bugs
visibleFrom()/hiddenFrom()did nothing.@lattice-php/coreowns the responsive-visibility wrapper (hidden md:contents), and nothing pointed Tailwind at that package's dist —@lattice-php/ui/csssources only its own, and the Vite plugin sources only component packages (the ones declaringextra.lattice.plugin). Somd:contentswas never generated and every such node stayed hidden at all widths, silently. The same missing glob is why the members and invitations tables rendered without a header row.This affects any app installing Lattice from npm; the fix here is one
@sourceline, but the plugin arguably ought to source the runtime packages itself.The sidebar had no trigger. It was
collapsible(), but Lattice ships no trigger of its own — belowmdthe drawer never opened, so a phone had no team switcher, no navigation and no way to log out. A topbar now carries the toggle, the breadcrumb trail and the user menu.DashboardPage::breadcrumbs()was dead code — no layout ever rendered aBreadcrumbsnode.Calloutsjoins it so an effect flashed from a controller or listener has somewhere to land.Performance
TeamsTablesource, 6 teamsUser::teams()now uses theMembershippivot class, so the cast role is read off the already-loaded row instead of re-queried per team.AuthorizesRowActionscaches a row action's policy check on the definition instance, which lives exactly one render. Caching on theUsermodel instead looked tempting and is wrong — a laterattach()leaves the loaded relation stale, which is what the suite caught.Deduplication
AppPagecarries the layout, middleware and notification listeners for the four signed-in pages, leaving each its own route, name and gate;SettingsPageoverrides the middleware to dropverified, since its profile tab is where an unverified user resends the mail.PageHeaderreplaces ten hand-built heading-plus-lead stacks.Verification
composer ci:checkgreen,composer test:browsergreen — including two new browser tests: the mobile drawer opening, and the breadcrumb trail after navigating into a team.Both traps are recorded in
.ai/rules/.