refactor: metadata store cleanup, SSE unification, mock metadata loading & login redirect fix (#18651)

## Summary
- **SSE unification**: Replaced 11 individual SSE effect components with
a single generic `MetadataStoreSSEEffect`
- **Metadata store cleanup**: Merged `metadataCollectionHashesState`
into `metadataStoreState` (currentCollectionHash / draftCollectionHash
per entity), moved `objectMetadataItemsSelector` to `object-metadata`
domain, converted `navigationMenuItemsState` to a derived selector
- **Naming clarity**: Renamed `isAppMetadataReadyState` →
`isMinimalMetadataReadyState`, `MetadataGater` → `MinimalMetadataGater`,
`useIsLogged` → `useHasAccessTokenPair`,
`patchMetadataStoreFromSSEEvent` now takes named object params
- **Mock metadata loading**: Added `generate-navigation-menu-items.ts`
script, rewrote `useLoadMockedMinimalMetadata` to load full
objects/fields/indexes/views/navItems from generated mock data, enabling
proper sign-in background rendering (table columns, view picker,
navigation)
- **Login/logout transitions**: `MinimalMetadataLoadEffect` manages
mocked↔real metadata transitions based on auth state,
`MainContextStoreProvider` computes context on auth pages for view
picker support
- **Login redirect fix**: `handleLoadWorkspaceAfterAuthentication` now
re-enables `isAppEffectRedirectEnabled` after `loadCurrentUser()`
completes, fixing the blocked post-login navigation
- **Dead code removal**: Deleted `useRefreshPageLayouts`,
`useApplyPageLayouts`, `useStaleMetadataEntities`,
`metadataCollectionHashesState`, and all individual SSE effects

## Test plan
- [x] Login from welcome page redirects to companies page
- [x] Logout transitions cleanly to mocked metadata on welcome page
- [x] Sign-in background shows table columns, view picker, and
navigation items
- [x] SSE events still update metadata store entries correctly
- [x] Navigation menu items persist across page refreshes
- [ ] CI: lint, typecheck, tests pass
This commit is contained in:
Charles Bochet
2026-03-16 00:38:11 +01:00
committed by GitHub
parent 06efee1eef
commit ba9aa41bba
161 changed files with 3106 additions and 4350 deletions
@@ -1,4 +1,3 @@
import { metadataCollectionHashesState } from '@/metadata-store/states/metadataCollectionHashesState';
import {
metadataStoreState,
type MetadataEntityKey,
@@ -22,19 +21,29 @@ type SSEEventOperation =
deletedRecordId: string;
};
export const patchMetadataStoreFromSSEEvent = (
store: JotaiStore,
entityKey: MetadataEntityKey,
operation: SSEEventOperation,
updatedCollectionHash?: string,
) => {
export const patchMetadataStoreFromSSEEvent = ({
store,
entityKey,
operation,
updatedCollectionHash,
}: {
store: JotaiStore;
entityKey: MetadataEntityKey;
operation: SSEEventOperation;
updatedCollectionHash?: string;
}) => {
const entry = store.get(metadataStoreState.atomFamily(entityKey));
const currentItems = entry.current as Array<{ id: string }>;
const hashUpdate = isDefined(updatedCollectionHash)
? { currentCollectionHash: updatedCollectionHash }
: {};
switch (operation.type) {
case 'create': {
store.set(metadataStoreState.atomFamily(entityKey), {
...entry,
...hashUpdate,
current: [...currentItems, operation.createdRecord],
});
break;
@@ -42,6 +51,7 @@ export const patchMetadataStoreFromSSEEvent = (
case 'update': {
store.set(metadataStoreState.atomFamily(entityKey), {
...entry,
...hashUpdate,
current: currentItems.map((item) =>
item.id === (operation.updatedRecord as { id: string }).id
? { ...item, ...operation.updatedRecord }
@@ -53,6 +63,7 @@ export const patchMetadataStoreFromSSEEvent = (
case 'delete': {
store.set(metadataStoreState.atomFamily(entityKey), {
...entry,
...hashUpdate,
current: currentItems.filter(
(item) => item.id !== operation.deletedRecordId,
),
@@ -60,13 +71,4 @@ export const patchMetadataStoreFromSSEEvent = (
break;
}
}
if (isDefined(updatedCollectionHash)) {
const currentHashes = store.get(metadataCollectionHashesState.atom);
store.set(metadataCollectionHashesState.atom, {
...currentHashes,
[entityKey]: updatedCollectionHash,
});
}
};