yangzhang75 opened a new pull request, #9023: URL: https://github.com/apache/texera/pull/9023
### What changes were proposed in this PR? Closes #8760. Part of the Form View feature (#8011); from the #8439 refinements (item 1). The code editor renders into an outlet the operator canvas published once (`<ng-template #codeEditor>` in `WorkspaceComponent`, handed to `CodeEditorService` as `vc`) and never let go of. The Form View has no outlet of its own, yet its step panel shows the operator's real property frame and, in edit mode, the ordinary **Edit code content** button. Pressing it opened the editor into whatever `vc` held: nothing, from a direct open of the Form View, or the destroyed canvas's outlet after the routed switch between the views (#8581), where Monaco rendered into a detached view and nothing appeared. Verified on main before changing anything: the button is there and enabled, the click does nothing, and no error is raised. Each view that shows operator properties now carries its own outlet, marked `texeraCodeEditorHost` on an `<ng-template>` in its template: - `CodeEditorHostDirective` attaches the outlet to `CodeEditorService` when the view's template is built and detaches it -- only its own, so a host that has since replaced it stays -- when the view is destroyed, which also closes an editor still open in it (the view's teardown destroys what its outlet holds before the hook runs). The views are sibling routes and never overlap, so there is one host at a time. - The canvas uses the directive in place of its `@ViewChild` + `vc` hand-over; the Form View gets the same one line. The service exposes `host`, `attachHost` and `detachHost` in place of the public `vc`. - The code button opens into whichever host is up. While none is, it is disabled with a tooltip on its wrapper (a disabled button takes no pointer events, so it cannot carry one) and an accessible name saying where the editor opens; a co-editor's open reaching a codearea with no host neither throws nor marks that operator's editor open. - The editor is told its operator by its opener (`currentOperatorId` is an input) instead of reading the highlight in its constructor, and may be dragged within the Form View's page as well as the canvas (`cdkDragBoundary`). The Form View lifts the editor above its sticky title row. Deliberately not in this change: exposing a code property as a form input. The form's rules keep the code editor out of what an author may expose (`NON_FORM_FIELD_TYPES`) and fall back from it on an old workflow that carries one (`CANVAS_ONLY_FORMLY_TYPES`) -- editing code is not filling in a value, and a form reader should not be writing code. The step panel is the author's own editing surface, and that is what this fixes. ### Any related issues, documentation, discussions? Closes #8760. Part of #8439 (item 1, raised by @mengw15 on #8436) and the Form View feature #8011. The routed switch that left the canvas's outlet destroyed under the Form View is #8581. ### How was this PR tested? Unit tests (vitest). The directive's spec: attaches its outlet on construction, closes what it hosts and lets go of the host on destroy, and does not let go of a host that has since replaced it. The service's spec: `host`/`attachHost`/`detachHost`, including that detaching a stale host leaves the current one. The code button's spec: opens into the host and tells the editor its operator, which is the highlighted one; sets only inputs the editor declares; stays closed when a co-editor opens another operator's editor; and, without a host, opens nothing and marks nothing open on a click, and stays closed instead of throwing when a co-editor opens theirs. The editor's spec: takes its operator as an input and still highlights it on focus; a read-only control gets no context-menu actions. The Form View's rendered spec: hosts the editor while the page is up and lets go of the host when it is destroyed; the workspace's spec: the same through the directive instead of the old `@ViewChild`. By hand, on two dev builds of the same base commit, one with this change and one without, as the workflow's owner in the Form View's edit mode with the workflow strip open and the Python UDF step selected: on main, **Edit code content** is enabled and the click opens nothing. On this branch, the click opens the editor as a floating box titled with the step's name, showing its code, over the form page (a Monaco instance in the page, inside the Form View's own subtree), and the button reads as open while it is. Each guard was deletion-checked and turned a named test red: the form's outlet, the detach on destroy, and the button's no-host guard (that one fails to compile without it). eslint, prettier and the production (AOT) build pass; every statement, function and branch this PR adds is covered; the full frontend suite passes. #### Video **Before** **After** ### Was this PR authored or co-authored using generative AI tooling? Yes. Generated-by: Claude Code (Anthropic). Co-authored with Claude, reviewed line by line by the author before submission. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01FVvP3ttj22f9LB4p9u2anY -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
