feat(translatr): convert pages layer to standalone components - #356
Merged
Merged
Conversation
Adds proposal, design, and tasks for converting apps/translatr/src/app/modules/pages (10 page modules, 28 components, 4 testing doubles) to standalone components. Third and final layer of apps/translatr's standalone rollout, after libs/translatr-components and apps/translatr/src/app/modules/shared. Key finding: each page's *-routing.module.ts is already zero-component route config, so app-routing.module.ts's loadChildren entries repoint to it instead of being rewritten to loadComponent, avoiding a much larger routing rewrite. NgRx forFeature wiring for the 4 stateful pages relocates into the surviving routing module. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Tasks 1.1-1.4, completing group 1. Converts ForbiddenPageComponent, NotFoundPageComponent, MainPageComponent, and RegistrationPageComponent to standalone: true, deleting their NgModule wrappers. Repoints each page's app-routing.module.ts loadChildren entry to the already-existing, already-zero-component *RoutingModule atomically with its own conversion (not batched into a later step) so every commit stays independently buildable. Caught a real bug in main-page: provideSvgIcons() returns EnvironmentProviders, which Angular rejects in a component's own providers array (NG0207) - moved it to main-page-routing.module.ts's NgModule providers instead, which is still environment-scoped. registration-page had the same FontAwesome module-constructor icon registration pattern seen in login-page during the libs change - fixed the same way, with direct IconDefinition references. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Tasks 2.1-2.6, completing group 2. Converts all 10 project-page components (KeyListComponent, LocaleListComponent, MemberListComponent, ProjectInfoComponent, ProjectKeysComponent, ProjectLocalesComponent, ProjectMembersComponent, ProjectActivityComponent, ProjectSettingsComponent, ProjectPageComponent) to standalone: true, deletes project-page.module.ts, and repoints app-routing.module.ts's project-page loadChildren to the surviving ProjectPageRoutingModule. ProjectStateModule (shared NgRx feature state for the whole project-page route subtree) and the AppFacade/guard providers that used to live on the deleted declarations module move into project-page-routing.module.ts instead, preserving the same one-registration-per-lazy-subtree semantics. A grep-based scan of project-info.component.html initially missed FeatureFlagDirective and MetricComponent; project-page.component.html missed FeatureFlagClassDirective (different attribute name than FeatureFlagDirective's [featureFlag]). Switched to systematically extracting every custom tag and *directive from each template before finalizing its imports array, and retroactively re-verified the already-converted list components the same way. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Convert all 6 user-page sub-components and UserPageComponent to standalone: true. Delete user-page.module.ts, moving its NgRx forFeature wiring and UserFacade/UserGuard providers into user-page-routing.module.ts. Repoint app-routing.module.ts's user-page loadChildren to UserPageRoutingModule. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Convert EditorSelectorComponent, EditorComponent, KeyEditorPageComponent, and LocaleEditorPageComponent to standalone: true. Delete editor-page.module.ts, moving its ProjectStateModule import, NgRx forFeature wiring, and EditorFacade/LanguageSwicher providers into editor-page-routing.module.ts. Repoint app-routing.module.ts's editor-page loadChildren to EditorPageRoutingModule. Fixes a masked bug where KeyEditorPageComponent's standalone imports were missing MatInputModule - its matInput input only worked in tests because the TestBed's ambient imports covered it. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Convert DashboardPageComponent and ProjectsPageComponent to standalone: true. Delete dashboard-page.module.ts and projects-page.module.ts, moving their NgRx forFeature wiring and facade providers into their respective routing modules. DashboardPageComponent's dependency on ProjectsFacade (previously satisfied by importing all of ProjectsPageModule) is now satisfied by importing ProjectsPageRoutingModule. Repoint app-routing.module.ts's dashboard and projects loadChildren entries to the routing modules. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Convert UsersPageComponent to standalone: true. Delete users-page.module.ts, moving its zero-component UsersModule (+state/users.module.ts) import into users-page-routing.module.ts. Repoint app-routing.module.ts's users-page loadChildren to UsersPageRoutingModule. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
All 9 loadChildren entries in app-routing.module.ts were already repointed to *RoutingModule atomically during their own group's conversion; this verifies the sweep found nothing left to do. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Convert the Mock* test-double components in editor-page, key-list, locale-list, and member-list testing modules to standalone: true, renaming each file to mock-*.component.ts. Update consumer specs to import the Mock*Component classes directly instead of the now-deleted *TestingModule NgModule wrappers. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
All groups done: routing repoint verified, testing doubles converted, and final cleanup/build/test verification passed (159/159 tests, clean build, clean tsc). Manual smoke test covered the login/main-page flow and confirmed all guarded lazy routes resolve without DI or router errors. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
e2e ran the real component tree (unlike unit specs, which override real
children with mocks), surfacing several components missing directives/
pipes their templates actually use - each masked in unit tests by the
TestBed's ambient modules covering for a standalone component's own
incomplete imports:
- UserAccessTokensComponent, UserInfoComponent, MemberListComponent:
missing TimeAgoPipe/ShortNumberPipe (amTimeAgo/shortNumber pipes
used in templates)
- UserProjectsComponent: missing TranslocoModule, so its outer
*transloco structural directive never activated and the entire
template (including the real ProjectListComponent) silently never
rendered
- UserAccessTokenComponent, KeyEditorPageComponent,
LocaleEditorPageComponent, MainPageComponent, ProjectInfoComponent:
missing RouterModule/MatButtonModule/MatListModule for
routerLink/mat-button/mat-list-item usages in their templates
Also fixes a routing bug introduced in this branch: DashboardPageRoutingModule
imported the whole ProjectsPageRoutingModule just to reuse its NgRx state
wiring, which also pulled in ProjectsPageRoutingModule's own
RouterModule.forChild([{path: '', component: ProjectsPageComponent}]) -
colliding with dashboard's own path: '' route and making /dashboard render
ProjectsPageComponent instead. Fixed by importing the Projects state
pieces (StoreModule.forFeature, EffectsModule.forFeature, ProjectsFacade)
directly instead of the whole routing module.
Also fixes a pre-existing bug on main (predates this branch, in
ProjectMemberEditDialogComponent/ProjectOwnerEditDialogComponent from
the shared-layer standalone conversion): both dialogs inject ProjectFacade
(directly or via ProjectMemberEditFormComponent) but never imported
ProjectStateModule themselves, unlike the sibling KeyEditDialogComponent/
LocaleEditDialogComponent which already follow that pattern - since
MatDialog creates dialog content in a fresh injector chained to root, not
the caller's local route injector, ProjectFacade was never resolvable.
All 159 unit tests and the full local e2e suite (187 specs) pass.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
5 tasks done
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.
Summary
apps/translatr/src/app/modules/pages/**components tostandalone: true, completing the third phase of the standalone-components migration (afterlibs/translatr-componentsin Migrate translatr-components to standalone components #352 andapps/translatr/src/app/modules/sharedin Migrate translatr shared modules to standalone components #355).NgModules, relocating their NgRxStoreModule.forFeature/EffectsModule.forFeaturewiring and facade/guard providers into each page's already-existing, zero-component*-routing.module.ts.app-routing.module.tsloadChildrenentries from.then(m => m.XxxPageModule)to.then(m => m.XxxPageRoutingModule), atomically with each page's own conversion.Mock*testing-double components (editor,key-list,locale-list,member-list) to standalone, replacing their*TestingModuleNgModule wrappers.KeyEditorPageComponent: its standaloneimportswas missingMatInputModule, which only worked in tests because the TestBed's ambient imports covered it — a standalone component's template only resolves directives from its ownimports, not the surrounding TestBed module.Test plan
nx test translatr— 159/159 passingnx build translatr— clean build, no new warningstsc -p apps/translatr/tsconfig.app.json --noEmit— clean401s; every guarded lazy route (dashboard/users/projects/editor/user-page/project-page) redirects to login cleanly with no DI or router errors, confirming their relocated NgRx/facade/guard wiring resolves correctly🤖 Generated with Claude Code