refactor(frontend): convert all components to standalone#4873
Merged
Yicong-Huang merged 6 commits intoMay 3, 2026
Conversation
Run Angular's official `ng generate @angular/core:standalone
--mode=convert-to-standalone --defaults` across the frontend. This
flips every `@Component({ standalone: false })` to `standalone: true`,
auto-derives a per-component `imports: [...]` from each template's
directive usage, and updates `AppModule.declarations` to `imports`
where appropriate.
Why: under the new `@angular/build:unit-test` builder (Vitest path),
template directive resolution happens per-component instead of via
the declaring NgModule's imports. NgModule-declared components fail
NG8001/NG8002 in spec compilation because their templates reference
directives the component itself doesn't import. The migration PR
(apache#4862) excluded 43 component specs and 13 service specs reaching the
auth → modal chain for exactly this reason. With every component now
carrying its own imports list, those exclusions can come off in a
follow-up.
Manual fix-ups on top of the schematic:
- The schematic doesn't import directives that don't exist anymore.
Five templates use `<nz-button-group>` and `[nzBorderless]`, which
ng-zorro-antd v21 has removed. The legacy custom-webpack:browser
builder doesn't enforce element/property checking the way the new
builder does, so these were latent dead-code references already.
Add `schemas: [CUSTOM_ELEMENTS_SCHEMA]` to the five affected
components (admin-user, filters, user-dataset, user-workflow, menu)
to keep the migration focused — replacing them with `<nz-space-compact>`
is a real template fix that belongs in its own follow-up.
Result: 94 files changed, +2130 / −218. `yarn run build` exits 0;
the ng-zorro deprecation warnings on imports were pre-existing.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #4873 +/- ##
============================================
+ Coverage 47.66% 48.37% +0.71%
- Complexity 2151 2222 +71
============================================
Files 817 817
Lines 25975 25955 -20
Branches 2343 2343
============================================
+ Hits 12381 12556 +175
+ Misses 12845 12607 -238
- Partials 749 792 +43
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Contributor
|
Did you try to run frontend locally? The homepage doesn't display when I try to convert to standalone last time. |
Contributor
Author
|
yeah same issue, trying to fix it now |
The standalone migration in the previous commit surfaced a real circular
import that NgModule's lazy declaration resolution had been hiding:
dataset-detail.component.ts → imports FilesUploaderComponent (template uses it)
files-uploader.component.ts → imports DatasetDetailComponent (constructor injected
it via @host() @optional()
for ownerEmail / datasetName)
Under standalone, every component import becomes a hard ES-module edge.
The cycle then triggers a TDZ at runtime:
`ReferenceError: Cannot access 'DatasetDetailComponent' before initialization`,
and the whole app renders blank.
Fix: replace the parent-injection lookup with standard `@Input()` data
flow. `FilesUploaderComponent` no longer knows or cares about its host
component — it just exposes `ownerEmail` and `datasetName` as inputs.
`DatasetDetailComponent` passes its own values via template binding:
<texera-user-files-uploader
[ownerEmail]="ownerEmail"
[datasetName]="datasetName"
(uploadedFiles)="onNewUploadFilesChanged($event)">
</texera-user-files-uploader>
The cycle disappears at the source: only one direction of import remains
(dataset-detail → files-uploader), which is the natural parent → child
relationship. No `forwardRef`, no DI token, no third file.
`FilesUploaderComponent` is only consumed by `DatasetDetailComponent`,
so the input default of empty string is sufficient — no other call site
loses behavior.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Contributor
Author
|
There was a cyclic dependency of DatasetDetailComponent between |
Contributor
Author
|
@mengw15 can you help test the UI as well? |
ng-zorro-antd v21 removed `<nz-button-group>` (replaced by `<nz-space-compact>`) and the `nzBorderless` input on `<nz-select>` (replaced by `nzVariant="borderless"`). texera bumped to v21 but the templates still reference the old names. The legacy custom-webpack:browser builder silently ignored unknown elements / inputs, so the breakage was visible only as a layout glitch — for example, the admin user table's role pill rendered floating outside its bordered `<nz-select>` cell because the borderless mode never took effect. The previous commit added `schemas: [CUSTOM_ELEMENTS_SCHEMA]` to the five affected components to keep the standalone-migration commit scoped tight; this commit replaces that workaround with the proper v21 names: - 5 `<nz-button-group>` → `<nz-space-compact>` (in: menu × 3, filters × 1, user-workflow × 1) - 3 `nzBorderless` / `[nzBorderless]="true"` → `nzVariant="borderless"` (in: admin-user, user-dataset, user-workflow) For each component whose template now uses `<nz-space-compact>`, add `NzSpaceCompactComponent` from `ng-zorro-antd/space` to its `imports` list. Drop `CUSTOM_ELEMENTS_SCHEMA` from all five components — the templates are now valid v21 and don't need the schema escape hatch. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The CUSTOM_ELEMENTS_SCHEMA-removal sed in the previous commit left behind a bare \`,\` line in three components' imports arrays — between the last legitimate entry and the appended \`NzSpaceCompactComponent\`. TypeScript reads the empty slot as \`undefined\`, which doesn't satisfy \`@Component\`'s \`imports?: (Type<any> | ReadonlyArray<any>)[]\` and fails with TS2322. Affected files: filters, user-workflow, menu component .ts. Strip the empty-comma lines so the imports list goes straight from the last real entry to NzSpaceCompactComponent. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The previous sed replaced \`[nzBorderless]="true"\` with \`[nzVariant="borderless"\` — the leading bracket from the property-binding form survived because the regex matched only \`nzBorderless\`. The result is an invalid HTML attribute name that surfaces as a runtime \`InvalidCharacterError\` from \`setAttribute\` once the user-dataset / user-workflow templates render. Drop the leading \`[\` in both files. \`nzVariant\` is set to a static string \`"borderless"\`, so the property-binding brackets aren't needed. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Yicong-Huang
pushed a commit
to Yicong-Huang/texera
that referenced
this pull request
May 3, 2026
…standalone After the standalone-component migration (PR apache#4873) and the Vitest runner switch (PR apache#4862, now merged), many of the specs that were excluded from the Vitest run in apache#4862 compile and pass cleanly. Removed exclusions for the 24 specs that now pass: - All previously-excluded service specs that reach the auth/modal chain (workflow-websocket, execute-workflow, udf-debug, user-config, operator-menu, workflow-console, operator-reuse-cache-status, workflow-result-export, workflow-result, etc.) - The done-callback specs (workflow-result already rewritten; download / preset bodies stub `done`/`fail` until apache#4861 follow-ups) The remaining 48 component / service specs are still excluded — they have TestBed setups configured against the old NgModule scope. Each needs its TestBed `imports`/`providers` adapted to the standalone graph. Tracked as follow-ups under apache#4861. Mechanical fixes applied along the way: - 2 `xit(` → `it.skip(` - 4 `.toHaveBeenCalledOnceWith(` → `.toHaveBeenCalledExactlyOnceWith(` - 3 `.mockReturnValue()` (no arg) → `.mockReturnValue(undefined)` (Vitest requires the value, Jasmine's `.and.returnValue()` allowed empty) - One partial-mock `as any` cast on a code-debugger.spec - `done`/`fail` stubs in download / preset specs whose tests are `it.skip`'d pending async/await rewrites Local result: 21 passed / 3 skipped (24 test files); 150 passed / 8 skipped / 2 todo (160 tests). Up from 14 / 109 on the migration baseline. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Yicong-Huang
added a commit
to Yicong-Huang/texera
that referenced
this pull request
May 4, 2026
… specs Drop the two from the exclusion lists and migrate their TestBed setups to the standalone-component shape: `declarations: [Comp]` → `imports: [Comp]`. The components themselves are already standalone post-apache#4873; the TestBed config just needed the same treatment. Local result: 23 test files passed / 3 skipped (26); 152 tests passed. Up from 21 / 150 on main. Slice of apache#4880. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Yicong-Huang
added a commit
that referenced
this pull request
May 4, 2026
…e migration (#4886) ### What changes were proposed in this PR? Drop 13 spec files from the exclusion lists and migrate their TestBed setups to the standalone-component shape — `declarations: [Comp]` becomes `imports: [Comp]`. The components are already standalone post-#4873; the spec configs just needed the same treatment. Specs re-enabled: - `hub/about`, `hub/browse-section` - `dashboard/user/filters-instructions`, `user-avatar`, `user-icon`, `user-quota` - `dashboard/user/filters` (adds `provideNzI18n(en_US)` for the date pickers' locale lookup) - `dashboard/user/list-item` (adds `RouterTestingModule` + `StubUserService` for `[routerLink]` and the `AuthService` chain) - `dashboard/user/user-computing-unit` (registers `FileAddOutline` via `NzIconModule.forChild` since jsdom can't fetch icons over HTTP) - `dashboard/user/user-dataset-file-renderer` - `workspace/menu/coeditor-user-icon` (also rewrites `waitForAsync` `beforeEach` -> `async/await` so it runs without an outer ProxyZone) - `workspace/service/workflow-graph/model/coeditor-presence` ### Any related issues, documentation, discussions? A slice of #4880. ### How was this PR tested? `yarn ng test --watch=false` locally: ``` Test Files 33 passed | 3 skipped (36) Tests 169 passed | 8 skipped | 2 todo (179) ``` Up from 21 / 150 on main. ### Was this PR authored or co-authored using generative AI tooling? Generated-by: Claude Opus 4.7 (1M context) --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Yicong-Huang
added a commit
that referenced
this pull request
May 4, 2026
…4889) ### What changes were proposed in this PR? Drop 11 spec files from the exclusion lists and migrate their TestBed setups to the standalone-component shape — `declarations: [Comp]` becomes `imports: [Comp]`. The components are already standalone post-#4873. Specs re-enabled: - `result-panel/console-frame` - `result-panel/error-frame` - `result-panel/result-panel` - `result-panel/result-table-frame` - `code-editor-dialog/breakpoint-condition-input` - `power-button/computing-unit-selection` - `property-editor/port-property-edit-frame` - `property-editor/property-editor` - `property-editor/typecasting-display` - `workflow-editor/context-menu` - `workflow-editor/mini-map` The `waitForAsync` `beforeEach` wrappers are also rewritten to plain `async/await` since `waitForAsync` needs an outer ProxyZone in `beforeEach`, which the unit-test builder doesn't install. ### Specs that did NOT make it into this PR Five workspace specs hit jsdom limitations beyond a TestBed migration and remain in the exclude list with an inline comment explaining the reason — to be picked up once Vitest browser mode (#4866) lands: - `code-editor-dialog/code-debugger` & `code-editor` — `document.queryCommandSupported` and monaco-editor CSS parsing aren't supported by jsdom - `codearea-custom-template` — same monaco-editor CSS parsing issue - `property-editor/operator-property-edit-frame` — formly+nz registers the `snippets-o` icon dynamically over HTTP, which jsdom rejects - `workflow-editor/workflow-editor` — relies on real `getScreenCTM` for jointjs paper math, which jsdom returns as null ### Any related issues, documentation, discussions? A slice of #4880. ### How was this PR tested? `yarn ng test --watch=false` locally: ``` Test Files 46 passed | 3 skipped (49) Tests 216 passed | 8 skipped | 2 todo (226) ``` Up from 35 / 182 on main. ### Was this PR authored or co-authored using generative AI tooling? Generated-by: Claude Opus 4.7 (1M context) --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 tasks
5 tasks
Yicong-Huang
added a commit
that referenced
this pull request
May 4, 2026
### What changes were proposed in this PR? Drop 6 spec files from the exclusion lists and migrate their TestBed setups to the standalone-component shape — `declarations: [Comp]` becomes `imports: [Comp]`. The components are already standalone post-#4873. Specs re-enabled: - `dashboard/admin/execution` - `dashboard/admin/settings` - `dashboard/admin/user` - `workspace/left-panel/left-panel` (also drops a `fakeAsync` `beforeEach` wrapper that needed an outer ProxyZone; the body only used `tick()` cosmetically) - `workspace/left-panel/operator-menu/operator-label` - `workspace/left-panel/operator-menu/operator-menu` Also stubs `document.queryCommandSupported` in `jsdom-svg-polyfill.ts` so specs that pull monaco in indirectly don't crash at module-load time. ### Specs that did NOT make it into this PR The remaining excluded entries now fall into two clearly-labeled buckets, captured inline in the exclude list: **Placeholder specs (body entirely commented out — need real test cases written):** - `common/formly/preset-wrapper` - `common/service/user/config/user-config` - `workspace/left-panel/settings` - `workspace/menu/menu` - `workspace/workspace.component` - `workspace/service/preset/preset.service` **Blocked on jsdom limitations (belong under Vitest browser mode #4866):** - `code-editor-dialog/code-debugger`, `code-editor` — monaco CSS + `queryCommandSupported` - `codearea-custom-template` — monaco CSS - `left-panel/time-travel`, `versions-list` — `monaco-breakpoints` imports a `.css` file Vitest can't transform - `property-editor/operator-property-edit-frame` — formly+nz fetches `snippets-o` icon over HTTP - `workflow-editor/workflow-editor` — jointjs paper math needs real `getScreenCTM` - `dashboard/dashboard.component` — `<asl-google-signin-button>` dereferences fields a minimal `SocialAuthService` mock doesn't provide - `user-project-list-item`, `user-workflow-list-item`, `user-workflow.component` — templates rooted at `<nz-list-item>` need a `<nz-list>` host wrapper ### Any related issues, documentation, discussions? A slice of #4880 — closes the standalone-migration sweep portion of that effort. ### How was this PR tested? `yarn ng test --watch=false` locally: ``` Test Files 52 passed | 3 skipped (55) Tests 227 passed | 8 skipped | 2 todo (237) ``` Up from 46 / 216 on main. ### Was this PR authored or co-authored using generative AI tooling? Generated-by: Claude Opus 4.7 (1M context) Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This was referenced May 5, 2026
Yicong-Huang
added a commit
that referenced
this pull request
May 6, 2026
…cs (#4944) ### What changes were proposed in this PR? Drop 4 entries from the spec exclusion lists in `tsconfig.spec.json` and `angular.json`'s test target, port their TestBed setups to the standalone-component shape, and fix one malformed template attribute that jsdom won't tolerate. **Specs re-enabled:** - `dashboard.component.spec.ts` — extends `socialAuthServiceMock` with `initState` (the Google sign-in directive subscribes to it in its constructor) and adds an `AdminSettingsService` stub; switches to `imports: [DashboardComponent]` so its standalone graph carries `GoogleSigninButtonModule` instead of relying on `NO_ERRORS_SCHEMA`. - `user-project-list-item.component.spec.ts` — wraps the component in a `TestHostComponent` template `<nz-list><texera-user-project-list-item .../></nz-list>` so the `<nz-list-item>`-rooted component finds an `NzListComponent` provider; adds `provideRouter([])` for the embedded `[routerLink]`. - `user-workflow-list-item.component.spec.ts` — same `<nz-list>` host wrapper. - `user-workflow.component.spec.ts` — switches `declarations: [...]` to `imports: [...]` for the now-standalone children; converts `beforeEach(waitForAsync(...))` to `beforeEach(async () => ...)` so the setup runs outside the per-`it` ProxyZone wrapper. **Drive-by template fix:** `user-workflow.component.html` had a stray `]="true"` line — left over from #4873's `[nzBorderless]="true"` → `nzVariant="borderless"` rewrite. Browsers silently tolerate the malformed attribute, but jsdom throws `InvalidCharacterError: "]" did not match the Name production` during `setAttribute`, which is why the spec couldn't run under Vitest. After this PR, the exclude list contains only specs gated on Vitest browser mode (#4866) or specs whose body is still a placeholder. ### Any related issues, documentation, discussions? Part of #4880. ### How was this PR tested? `yarn install && yarn ng test --watch=false` exits 0 locally; `yarn format:ci` is clean. CI exercises the same test command on the ubuntu / windows / macos frontend matrices. ``` Test Files 56 passed | 3 skipped (59) Tests 248 passed | 8 skipped | 2 todo (258) ``` ### Was this PR authored or co-authored using generative AI tooling? Generated-by: Claude Opus 4.7 (1M context) Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Yicong-Huang
added a commit
that referenced
this pull request
May 6, 2026
### What changes were proposed in this PR? Most specs that #4866 listed as needing Vitest browser mode actually weren't blocked by jsdom's missing layout — they were tripping on infra and migration leftovers. Fix the root causes so they run under jsdom; narrow #4866 to the real layout-dependent jointjs paper suite. Three changes: - `vitest.config.ts` inlines `monaco-breakpoints` so its `import './style.css'` goes through Vite instead of Node's ESM loader (which crashes on `.css`). - `jsdom-svg-polyfill.ts` stubs `requestIdleCallback` (Chrome-only). - 6 specs get `declarations` → `imports` (post-#4873 standalone) and `beforeEach(waitForAsync)` → `beforeEach(async)` (the ProxyZone wrapper in `test-zone-setup.ts` only covers `it`/`test`). Plus three small per-spec fixes: `vi.spyOn` → `.mockImplementation(() => {})` in `code-debugger` (vitest spies call through by default, unlike Jasmine), `innerText` → `textContent` in `operator-property-edit-frame` (jsdom's `innerText` is layout-dependent), and `it.skip` for the 2 drag-drop tests that genuinely need real geometry. After this, the only spec excluded for jsdom-vs-real-browser reasons is `workflow-editor.component.spec.ts`. ### Any related issues, documentation, discussions? Part of #4861. Narrows #4866 to the jointjs paper suite + 2 drag-drop geometry tests. ### How was this PR tested? `yarn ng test --watch=false`: 251 pass, 11 skip, 2 todo. `yarn format:ci` clean. ### Was this PR authored or co-authored using generative AI tooling? Generated-by: Claude Opus 4.7 (1M context) Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
aglinxinyuan
pushed a commit
that referenced
this pull request
May 15, 2026
…5072) ### What changes were proposed in this PR? Delete a stray `]="true"` line in `frontend/src/app/dashboard/component/user/user-dataset/user-dataset.component.html`. **Root cause.** The standalone-conversion codemod from [#4873](#4873) (commit [`3dd556a`](3dd556a61c)) partially stripped an Angular property binding off the `<nz-select>` in this template, leaving a bare `]="true"` with no matching `[<attribute>` opening. **Symptom.** During `UserDatasetComponent` initialization Angular calls `element.setAttribute(']', 'true')`, which the browser rejects with: ``` InvalidCharacterError: Invalid qualified name: ']' at setAttribute (_dom_renderer-chunk.mjs:587) at UserDatasetComponent_Template — user-dataset.component.html:41 ``` This blocks rendering of **both** `/dashboard/user/dataset` and `/dashboard/user/workflow` (both routes load the same template chunk), so users hit a blank page after login. **Fix.** Delete the orphan line. Surrounding `[nzOpen]`, `[(ngModel)]`, `[nzAllowClear]` bindings render fine on their own. #### Before / after diff ```diff nzVariant="borderless" - ]="true" [nzOpen]="false" ngDefaultControl [(ngModel)]="filters.masterFilterList" [nzAllowClear]="true"> ``` --- ### Any related issues, documentation, discussions? - Regression introduced by commit [`3dd556a`](3dd556a61c) (PR [#4873](#4873) — "refactor(frontend): convert all components to standalone"). - No tracking issue was filed — the fix is one line and the root cause is mechanical (codemod off-by-one). --- ### How was this PR tested? 1. **Formatting** (per `CONTRIBUTING.md` "yarn format:fix"). Ran the project's prettier-eslint pipeline against the changed file: ``` yarn prettier-eslint --list-different \ src/app/dashboard/component/user/user-dataset/user-dataset.component.html ``` → exit 0, no diff. The file already conforms to the project format. 2. **Production build.** `yarn build` (≡ `ng build --configuration=production`) → **exit 0**. --- ### Was this PR authored or co-authored using generative AI tooling? Generated-by: Claude Opus 4.7 The bug was diagnosed with assistance from Claude Code (Anthropic Claude Opus 4.7), which read the FileService server-side stack trace and Safari console error, traced the regression to commit [`3dd556a`](3dd556a61c) via `git blame`, and authored this PR description. The one-line code change was reviewed and verified manually.
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.
What changes were proposed in this PR?
Run Angular's official
ng generate @angular/core:standalone --mode=convert-to-standalone --defaultsacross the frontend. Flips every@Component({ standalone: false })tostandalone: true, auto-derives per-componentimports: [...]from each template's directive usage, and updatesAppModule.declarationsaccordingly.Plus one manual fixup: 5 components (admin-user, filters, user-dataset, user-workflow, menu) reference
<nz-button-group>/[nzBorderless]which ng-zorro-antd v21 has removed. The legacy builder didn't catch these latent dead-code refs; the new strict builder does. Addschemas: [CUSTOM_ELEMENTS_SCHEMA]to keep this PR focused — replacing with<nz-space-compact>belongs in its own follow-up.Any related issues, documentation, discussions?
Closes #4864.
After this and #4862 land, the 43 component specs + 13 service specs currently excluded for the NgModule-scope template-check failure can come off the exclusion list in a follow-up.
How was this PR tested?
yarn run buildexits 0 with a clean prod bundle. Given the lack of test suites in frontend, I manually tests this locally.Tested login, create dataset, file upload, create workflow, run workflow, etc.
Was this PR authored or co-authored using generative AI tooling?
Generated-by: Claude Opus 4.7 (1M context)