Repository navigation
Commit 3db7bbf
refactor(app-shell): move ObjectView's identity import and record navigation into sibling hooks (slices 5+6) (#26353)
<!-- claude-projects-attribution: {"github_login":"os-steve"} -->
_Requested by **Steve** · [project
thread](https://claude.ai/code/project/chan_01FdL1XeUyvVNxLreh3F4Qi9?thread=cmsg_01FdL1XeUyvVNxLreh3F4Qi9VtKf3F9dzJPJM4RRtABaEc)_
Part of #25992 (slices 5 and 6 of the move-only split, paired in one PR
as the seat allowed; slices 1 to 4 landed as #26152, #26233, #26310 and
#26336, and the card stays open for the slices listed below).
Clause-②: no
Metadata-protocol: none
## What moved
Base `b9cd9809` (slice 4 merged).
`ui/packages/app-shell/src/views/ObjectView.tsx` is 3123 lines there.
Two concerns of `ObjectViewInner` move verbatim into custom hooks in new
sibling modules. In both, every input is passed as an argument, the
component destructures the returned values under their original names,
no identifier is renamed and no context is added.
### Slice 5: identity import and the managed-environment Users marker →
`objectViewIdentity.tsx`
Lines 688–752 move into `useObjectViewIdentity({ objectDef, isAdmin,
dataSource, refreshKey, t, actionRuntime })`:
- the identity-import gate (`features` from `useExpressionContext`,
`isIdentityImport`, `identityImportEnabled`),
- the managed-environment Users marker (`managedUsers`, the
metadata-store ref, the grant-loader ref and `managedUserMarker`),
- the import password-policy state, its ref, and `identityDataSource`.
It returns the six names the rest of the component reads:
`identityImportEnabled`, `managedUsers`, `managedUserMarker`,
`identityPasswordPolicy`, `setIdentityPasswordPolicy`,
`identityDataSource`. The module is `.tsx` because the marker callback
returns `<UnauthorizedUserMarker>`. The import-wizard open state
(`showImport`, line 686) stays in the component, because the header and
the wizard read it.
### Slice 6: the record navigation overlay →
`objectViewRecordNavigation.ts`
Two blocks move into `useObjectViewRecordNavigation({ activeView,
objectDef, objects, appName, viewId, searchParams, setSearchParams,
location, navigate, routerRootHref, servedViews, viewLabel,
unlabelledViewText, language })`:
- lines 1456–1490: `detailNavigation` (the authored or derived overlay
mode and width) and `drawerRecordId`,
- lines 1563–1686: `handleNavOverlayNavigate`, `listRecordActions`,
`navOverlay` (`useNavigationOverlay`), `handleDrawerClose`,
`handleRowClick`, `handleExpandDrawer` and the effect that syncs
`?recordId=` to the overlay.
It returns the five names the rest of the component reads:
`listRecordActions`, `navOverlay`, `handleDrawerClose`,
`handleRowClick`, `handleExpandDrawer`.
The block between the two (lines 1491–1562: the `filter[...]` URL
equality filters and the `uf_*` user-filter selections) stays in the
component. It is a different concern (list filter URL state, row H's
neighbour in the seam table), and
`ObjectView.urlFilterSuffix-9196.test.ts` pins `const urlFilters`,
`parseUrlEqualityFilterTriples` and the `./drillUrlFilters.js` import in
`ObjectView.tsx`. Because the hook is called where the first block
stood, the three hooks of that filter block (`useMemo`, `useRef`,
`useCallback`) now run after the navigation hooks instead of between
them. The two groups share no value, the order is the same on every
render, and the only effect in either group, the `?recordId=` sync,
keeps its place among the component's effects.
### Imports
Each import moves with its only readers: `deriveRecordSurface`,
`overlayWidthFor`, `RECORD_DRAWER_PARAM`, `ViewNavigationConfig`,
`useNavigationOverlay`, `listRecordDetailUrl`, `listRecordActionsValue`
(still re-exported from `ObjectView.tsx`, line unchanged) go to the
navigation module. `useMetadata`, `useExpressionContext`,
`createIdentityImportDataSource`, `IDENTITY_IMPORT_OBJECT`,
`IdentityPasswordPolicy`, `MANAGED_USERS_OBJECT`,
`UnauthorizedUserMarker`, `UserGrantLoader` and `isManagedEnvironment`
go to the identity module. `viewTabLabel` is imported by both, since the
component still reads it. Nothing new is exported from `ObjectView.tsx`,
and the package entry is untouched. `ObjectView.tsx` goes from 3123 to
2926 lines.
Move-only proof: the multiset of non-blank lines of the base
`ObjectView.tsx` is contained in new `ObjectView.tsx` plus the two
modules. The only base lines missing are the five import lines that lost
a moved name, each replaced by its trimmed form. The added lines are the
trimmed imports and the two new imports, the module headers and imports,
the hook signatures and parameter types, the `return` objects, and in
`ObjectView.tsx` the two calls with their destructuring and two-line
comments.
## Test edits
None. `identityImportWriteModes-12697` reads `ObjectView.tsx` for the
wizard's `IDENTITY_IMPORT_WRITE_MODES` spread and its import from
`./identityImport.js`; both stay in the component, and the import keeps
that name. `urlFilterSuffix-9196` is covered by keeping the filter block
in place (above). No other source reader names a moved line.
## Seam table of `ObjectViewInner`
The full table (regions A to Q) is in #26336. Measured again on
`b9cd9809`, with the rows this PR changes:
| # | Concern | Lines on `b9cd9809` | Reads | Read by | Slice |
|---|---|---|---|---|---|
| E | Identity import + managed-environment Users marker | 688–752 | A
(`t`), C (`objectDef`, `isAdmin`, `refreshKey`, `actionRuntime`), prop
`dataSource` | O, P, Q | **5, this PR** |
| L-nav | Record navigation overlay, drawer URL state, row click,
expand, record links | 1456–1490, 1563–1686 | A, C, F (`activeView`),
props `objects` | O, Q | **6, this PR** |
| L-filter | `filter[...]` URL equality filters + `uf_*` user-filter
selections | 1491–1562 | A, H (`listIdentityKey`, `ownListParamsRef`) |
O | 8, with H |
| K | Realtime refresh + record count | (moved) | | | 4, #26336 |
## Remaining slices (the last closes the card)
- **Slice 7 — D:** environment entitlements, toolbar actions and the
create and import verdicts into a sibling hook.
- **Slice 8 — G + H + L-filter:** header toolbar actions, the list URL
state and the URL/user filter block into sibling hooks. Moving L-filter
re-points `ObjectView.urlFilterSuffix-9196.test.ts` to the new file
(path change only, under the seat's re-pointing allowance); otherwise it
stays.
- **Slice 9 — N + P:** the view tab bar and the plugin schema plus
header chrome.
- **Slice 10 — Q:** the JSX return's `PageHeader`, import wizard and
`NavigationOverlay` blocks into sub-components with explicit props.
- **Slice 11 — B + I + O (closes the card):** the view-config and
view-tab CRUD handlers and `renderListView`, with the
`writeRefusalCensus-11583` rows and the `relayRungCensus-7559` read
re-pointed to the new file (path and file-key changes only), as the seat
allowed.
The seat allows pairing two of these per PR. A, C, F, J and M (the held
list refs, read only by `renderListView`, which go with O) stay where
the table says.
## Verification
See the os-dev-report comment on the card for the full readings:
app-shell `type-check`, every `ObjectView.*` test in `views/`, the
`AppContent*` tests, every other test that reads `ObjectView.tsx` as
source, the app-shell tests that touch identity import, managed users or
the record drawer, eslint on the 3 touched files, the derived dispatch
gates, and a Console build.
## Acceptance notes
- eslint: 0 errors, and no new warning. The warnings in the moved code
are the ones it carried in the component: refs read during render in the
grant-loader block, `any` casts, and the two `exhaustive-deps` warnings
on `handleExpandDrawer` (`handleDrawerClose`) and the drawer-sync effect
(`navOverlay`). Dependency arrays and casts are kept verbatim because
the slices are move-only. The three files report 152 warnings in total,
against 158 for the base `ObjectView.tsx` alone.
- The navigation hook's parameters are typed from where the component
gets each value, not as `any` (seat review, lane `any` removal #25918):
`activeView` is `ReturnType<typeof buildViewTabs>[number]`, `objects` is
`ConsoleObjectViewProps['objects']` and `objectDef` its element. The
`ConsoleObjectViewProps` import from `./ObjectView.js` is `import type`,
so it is erased and adds no runtime cycle.
Changeset: `.changeset/25992-objectview-identity-navigation-split.md`
(patch, `@object-ui/app-shell`).
---
🤖 Generated with [Claude Code](https://claude.com/claude-code)
https://claude.ai/code/session_01QciHBvFJXnhZqXmdqpDtpz
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent 222755e commit 3db7bbf
4 files changed
Lines changed: 359 additions & 232 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
32 | 32 | | |
33 | 33 | | |
34 | 34 | | |
35 | | - | |
| 35 | + | |
36 | 36 | | |
37 | | - | |
38 | 37 | | |
39 | 38 | | |
40 | 39 | | |
| |||
56 | 55 | | |
57 | 56 | | |
58 | 57 | | |
59 | | - | |
| 58 | + | |
60 | 59 | | |
61 | 60 | | |
62 | 61 | | |
| |||
75 | 74 | | |
76 | 75 | | |
77 | 76 | | |
78 | | - | |
| 77 | + | |
79 | 78 | | |
80 | | - | |
| 79 | + | |
81 | 80 | | |
82 | | - | |
83 | 81 | | |
84 | 82 | | |
85 | 83 | | |
| |||
89 | 87 | | |
90 | 88 | | |
91 | 89 | | |
92 | | - | |
| 90 | + | |
93 | 91 | | |
94 | 92 | | |
95 | 93 | | |
| |||
104 | 102 | | |
105 | 103 | | |
106 | 104 | | |
107 | | - | |
108 | 105 | | |
109 | 106 | | |
110 | 107 | | |
| |||
126 | 123 | | |
127 | 124 | | |
128 | 125 | | |
| 126 | + | |
| 127 | + | |
129 | 128 | | |
130 | 129 | | |
131 | 130 | | |
| |||
685 | 684 | | |
686 | 685 | | |
687 | 686 | | |
688 | | - | |
689 | | - | |
690 | | - | |
691 | | - | |
692 | | - | |
693 | | - | |
694 | | - | |
695 | | - | |
696 | | - | |
697 | | - | |
698 | | - | |
699 | | - | |
700 | | - | |
701 | | - | |
702 | | - | |
703 | | - | |
704 | | - | |
705 | | - | |
706 | | - | |
707 | | - | |
708 | | - | |
709 | | - | |
710 | | - | |
711 | | - | |
712 | | - | |
713 | | - | |
714 | | - | |
715 | | - | |
716 | | - | |
717 | | - | |
718 | | - | |
719 | | - | |
720 | | - | |
721 | | - | |
722 | | - | |
723 | | - | |
724 | | - | |
725 | | - | |
726 | | - | |
727 | | - | |
728 | | - | |
729 | | - | |
730 | | - | |
731 | | - | |
732 | | - | |
733 | | - | |
734 | | - | |
735 | | - | |
736 | | - | |
737 | | - | |
738 | | - | |
739 | | - | |
740 | | - | |
741 | | - | |
742 | | - | |
743 | | - | |
744 | | - | |
745 | | - | |
746 | | - | |
747 | | - | |
748 | | - | |
749 | | - | |
750 | | - | |
751 | | - | |
752 | | - | |
| 687 | + | |
| 688 | + | |
| 689 | + | |
| 690 | + | |
| 691 | + | |
| 692 | + | |
| 693 | + | |
| 694 | + | |
| 695 | + | |
| 696 | + | |
753 | 697 | | |
754 | 698 | | |
755 | 699 | | |
| |||
1453 | 1397 | | |
1454 | 1398 | | |
1455 | 1399 | | |
1456 | | - | |
1457 | | - | |
1458 | | - | |
1459 | | - | |
1460 | | - | |
1461 | | - | |
1462 | | - | |
1463 | | - | |
1464 | | - | |
1465 | | - | |
1466 | | - | |
1467 | | - | |
1468 | | - | |
1469 | | - | |
1470 | | - | |
1471 | | - | |
1472 | | - | |
1473 | | - | |
1474 | | - | |
1475 | | - | |
1476 | | - | |
1477 | | - | |
1478 | | - | |
1479 | | - | |
1480 | | - | |
1481 | | - | |
1482 | | - | |
1483 | | - | |
1484 | | - | |
1485 | | - | |
1486 | | - | |
1487 | | - | |
1488 | | - | |
1489 | | - | |
1490 | | - | |
| 1400 | + | |
| 1401 | + | |
| 1402 | + | |
| 1403 | + | |
| 1404 | + | |
| 1405 | + | |
| 1406 | + | |
| 1407 | + | |
| 1408 | + | |
| 1409 | + | |
| 1410 | + | |
| 1411 | + | |
| 1412 | + | |
| 1413 | + | |
| 1414 | + | |
| 1415 | + | |
| 1416 | + | |
| 1417 | + | |
1491 | 1418 | | |
1492 | 1419 | | |
1493 | 1420 | | |
| |||
1560 | 1487 | | |
1561 | 1488 | | |
1562 | 1489 | | |
1563 | | - | |
1564 | | - | |
1565 | | - | |
1566 | | - | |
1567 | | - | |
1568 | | - | |
1569 | | - | |
1570 | | - | |
1571 | | - | |
1572 | | - | |
1573 | | - | |
1574 | | - | |
1575 | | - | |
1576 | | - | |
1577 | | - | |
1578 | | - | |
1579 | | - | |
1580 | | - | |
1581 | | - | |
1582 | | - | |
1583 | | - | |
1584 | | - | |
1585 | | - | |
1586 | | - | |
1587 | | - | |
1588 | | - | |
1589 | | - | |
1590 | | - | |
1591 | | - | |
1592 | | - | |
1593 | | - | |
1594 | | - | |
1595 | | - | |
1596 | | - | |
1597 | | - | |
1598 | | - | |
1599 | | - | |
1600 | | - | |
1601 | | - | |
1602 | | - | |
1603 | | - | |
1604 | | - | |
1605 | | - | |
1606 | | - | |
1607 | | - | |
1608 | | - | |
1609 | | - | |
1610 | | - | |
1611 | | - | |
1612 | | - | |
1613 | | - | |
1614 | | - | |
1615 | | - | |
1616 | | - | |
1617 | | - | |
1618 | | - | |
1619 | | - | |
1620 | | - | |
1621 | | - | |
1622 | | - | |
1623 | | - | |
1624 | | - | |
1625 | | - | |
1626 | | - | |
1627 | | - | |
1628 | | - | |
1629 | | - | |
1630 | | - | |
1631 | | - | |
1632 | | - | |
1633 | | - | |
1634 | | - | |
1635 | | - | |
1636 | | - | |
1637 | | - | |
1638 | | - | |
1639 | | - | |
1640 | | - | |
1641 | | - | |
1642 | | - | |
1643 | | - | |
1644 | | - | |
1645 | | - | |
1646 | | - | |
1647 | | - | |
1648 | | - | |
1649 | | - | |
1650 | | - | |
1651 | | - | |
1652 | | - | |
1653 | | - | |
1654 | | - | |
1655 | | - | |
1656 | | - | |
1657 | | - | |
1658 | | - | |
1659 | | - | |
1660 | | - | |
1661 | | - | |
1662 | | - | |
1663 | | - | |
1664 | | - | |
1665 | | - | |
1666 | | - | |
1667 | | - | |
1668 | | - | |
1669 | | - | |
1670 | | - | |
1671 | | - | |
1672 | | - | |
1673 | | - | |
1674 | | - | |
1675 | | - | |
1676 | | - | |
1677 | | - | |
1678 | | - | |
1679 | | - | |
1680 | | - | |
1681 | | - | |
1682 | | - | |
1683 | | - | |
1684 | | - | |
1685 | | - | |
1686 | | - | |
1687 | 1490 | | |
1688 | 1491 | | |
1689 | 1492 | | |
| |||
0 commit comments