yangzhang75 opened a new pull request, #8846:
URL: https://github.com/apache/texera/pull/8846

   ### What changes were proposed in this PR?
   
   Closes #8763. Part of the Form View feature (#8011); from the #8439 
refinements (item 6). The Form View now names the operator on every field it 
renders (`props.operatorID`: `FIELD_OPERATOR_ID_PROP` / `fieldOperatorID` in 
`custom-formly-type.ts`); a shared widget that needs its operator reads it 
there, since nothing is highlighted on the form, and the same mark tells it 
which host it is on where the two must differ (its columns and headers; what 
decides whether it offers Add parameter).
   
   `ui-udf-parameters` is exposable, but its renderer hides formly's labels and 
draws fixed column headers (Value / Name / Type), so the author's per-sub-field 
overrides from the form (#8438) changed nothing the reader saw: a rename lands 
as `props.label` on every row's sub-field and a hide as `hide`, and the fixed 
headers papered over both -- a renamed column kept its old name, a hidden one 
kept its header over an empty cell. Reviewing it also turned up four more 
things the widget got wrong: three on a Form View card, one on the canvas.
   
   - On the Form View the widget decides which columns are in view from the 
first row's sub-fields (the rows all share one override per path; formly builds 
them on demand from a template this widget never sees decorated, and with no 
rows the list is not shown at all): a hidden column is left out, header and 
cells alike, and so is a column whose group is hidden, since formly hides the 
children with the group but marks only the group. The list is read live, on 
every check, not once at populate: the form's hide lands on a row's sub-field 
after formly has built the row, so a list fixed at populate still showed the 
hidden column (found on a running instance). The same array instance comes back 
while nothing changed, so the header's `ngFor` does not redraw.
   - The header text is read live from the first row too: the author's name for 
the column (`props.authorName`: the form puts a saved rename there as well as 
on the label, and the label wrapper writes a name being typed there, which 
otherwise would have shown only after the next rebuild), else the fixed label 
-- not the schema's own title, which the panel does not show either.
   - "Add parameter" works on a Form View card as it does on the panel. It 
inserts a declaration into an operator's code, and it took that operator from 
the canvas highlight -- on the form nothing is highlighted, or another step is, 
so it edited the wrong operator or failed with "code is not available". The 
widget now takes the operator the field is bound to when the field carries one, 
and the highlighted operator otherwise (the panel, as always). Whether a card 
offers it follows the card's own rule, the one the add and remove buttons of 
every list on the form follow: the field is editable (a writer's card, in or 
out of edit mode, since adding a parameter is adding a row; a reader's card is 
disabled). It followed the canvas's modification flag, which the Form View 
holds off outside edit mode against structural edits through its page, so a 
writer could add a row to any list on the page but not a parameter to this 
table without entering edit mode. The panel keeps the canvas's rule, the
  flag, unchanged. The check also sits in the method, not only on the button.
   - The declared parameters then reach the operator: the parser announces the 
UI parameters a UDF's code declares, and the operator property panel's frame 
writes them onto the operator for the operator it shows, only while it acts as 
the editor. With the panel closed or on another step nobody wrote them, so a 
parameter added from a card changed the code but no row appeared. The form 
writes them when the frame does not: a writer only, not while the step panel 
shows that very step live, and only for an operator still on the graph; the 
same value the frame writes.
   - A read-only reader's value cells are locked: the Form View marks a 
reader's field `props.disabled`, and the widget's own "the value is editable" 
used to re-enable the control after formly had disabled it.
   - The widget's own lock on the Name and Type cells now holds under any host, 
the one change the canvas sees. The cells are inferred from the code's 
`self.UiParameter(...)` declarations and the widget marks them `props.disabled` 
(a name typed into the table no longer matches a declaration, and the value 
then never reaches it -- checked on main: the table's name changes, the code's 
does not). The panel's `setInteractivity(true)` enables the whole form group, 
and formly mirrors a control's state back into `props.disabled`, so the 
one-time disable did not survive: on the canvas the cells came back editable 
(sometimes, depending on which of the two ran last) while the Form View, which 
never enables a group wholesale, showed them locked. The widget now registers, 
on each cell it locks, Angular's disabled-change hook of the control 
(`registerOnDisabledChange`, the same hook formly's mirror and the input's 
value accessor use): whenever a host enables the control, the hook disables it 
agai
 n in the microtask after that enable (so the accessor, told last, shows the 
box locked too), announcing the status change as the enable did (ng-zorro's 
`nz-input` paints its disabled attribute from the control's status changes, and 
told only "enabled" it painted the box editable again at the next change 
detection), and formly's mirror then records the lock in `props.disabled` as 
well. A cell the widget configures editable (the Value cell, or any cell once 
reconfigured) is released from the hook, so whether it is editable stays the 
host's call (a read-only panel, a reader's card). A formly expression was tried 
first and dropped: formly re-evaluates expressions on model changes only, not 
on an `enable()`. The frame is untouched.
   - Otherwise the operator property panel is unchanged: the three headers stay 
fixed, Add parameter adds to the highlighted operator, the value column stays 
editable.
   
   ### Any related issues, documentation, discussions?
   
   Closes #8763. Raised by Copilot on #8438; filed from #8439. Based on main. 
#8760 (the form's own code editor host) needs the same operator mark and the 
same write of the declared parameters; whichever lands second drops its copy. 
Checked under real formly while reviewing: hiding the `attribute` group itself 
keeps the rows' names and types in the model (formly resets a hidden field's 
children only on a hide that happens after the build; the form sets `hide` at 
build only, and a reader's card is rebuilt rather than toggled). Table 
semantics for assistive tech (the header and cells are plain `div`s, as on the 
canvas) stay a follow-up. One difference between the hosts is the Form View's 
own and not changed here: a writer's cards stay editable while a run is in 
flight (the add and remove buttons of every list included), so a card offers 
Add parameter then as well, while the operator property panel is locked during 
a run.
   
   ### How was this PR tested?
   
   Unit tests (vitest). The widget's spec: a renamed column shows its name and 
a hidden one is left out, in the header and the cells; rows built on demand are 
read from the first row; a hidden group hides its columns; the author's name 
shows while renaming and follows the typing without a rebuild; no rows keeps 
the fixed headers; the panel keeps them whatever the sub-fields carry; a 
reader's value cells are locked; Add parameter is offered on the form and adds 
to the card's operator, on the panel to the highlighted one; a writer's card 
offers it while the canvas's modification flag is off (the Form View holds it 
outside edit mode) and a reader's card, its field disabled, does not and adds 
nothing; on the panel `addParameter` adds nothing while modification is off, 
whoever calls. The widget's spec also pins the lock: a locked cell's control is 
held locked when the host enables it (in the microtask after the enable, 
announcing its status change) while the Value cell is left to the host
 ; a cell configured editable again is released; a cell the host disables again 
before the microtask is left alone; a group control gets no hook, and a control 
is hooked once. A second widget spec stands it up under real formly 
(`FormlyModule.forRoot`, a form, a builder row template as formly-jsonschema 
produces, the cells `nz-input`s as in the app): the rows build with Name and 
Type locked and Value editable; a wholesale `form.enable()`, as the panel does, 
leaves Name and Type locked, read from the inputs' disabled state, not only the 
controls'; a read-only `form.disable()` locks everything and a later `enable()` 
gives only Value back; a writer's Form View card offers Add parameter with the 
canvas's flag off, a reader's card (`props.disabled`, which formly turns into a 
disabled field) does not. The form's spec: every field carries its operator; a 
renamed sub-field carries the author's name apart from its label (a sub-field 
formly built without props too); the declared UI parameters 
 are written for a writer when the panel is not editing that step, left to the 
frame while it shows the step live, written when it shows the step read-only, 
and not written for a reader or a vanished operator. `custom-formly-type`'s 
spec pins the operator mark. Each guard was deletion-checked and turned a named 
test red. eslint, prettier and the production (AOT) build pass; the full 
frontend suite passes; every statement, function and branch this PR adds is 
covered.
   
   Checked on a flag-on instance (main-demo; a Python source feeding a Python 
UDF whose code declares two UI parameters, `uiParameters` exposed with the Name 
column renamed "Parameter" and the Type column hidden), the canvas and the form 
open side by side. On main the card shows Value / Name / Type, the overrides 
ignored. With this PR the card shows Value / Parameter, the Type column gone, 
while the canvas panel still shows Value / Name / Type. A writer's card offers 
Add parameter in and out of edit mode (on main it appeared only in edit mode, 
while any list's rows could be added either way); adding `cutoff` (double) 
inserts `self.UiParameter(name="cutoff", type=AttributeType.DOUBLE)` into that 
UDF's code, and the new row appears on the card and in the canvas tab's panel 
within a few seconds, and is there after a reload.
   
   On the canvas panel (widened so that the Name and Type columns are in view; 
at its default width the table's fixed 250px columns clip them, a layout bug of 
its own since #5043, not touched here), main's Name and Type cells come back 
editable on about half the panel openings (2 of 4 loads; the frame enables the 
whole form group one task after each render, racing the widget's lock) and 
whenever the modification-enabled stream enables the group, e.g. when a run 
finishes. With this PR they stayed locked on 4 of 4 loads and through a forced 
wholesale enable followed by real change-detection passes, read from the DOM 
(the input's disabled state, the select's disabled class) as well as from the 
controls. The Value cell follows the host in both.
   
   #### Video
   
   **Before**
   
   _(to be added)_
   
   **After**
   
   _(to be added)_
   
   ### Was this PR authored or co-authored using generative AI tooling?
   
   Yes. Generated-by: Claude Code (Claude Fable 5.1, Anthropic). Co-authored 
with Claude, reviewed line by line by the author before submission.
   
   🤖 Generated with [Claude Code](https://claude.com/claude-code)


-- 
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]

Reply via email to