fix(plating): tree editor — expand newly imported nodes + Expand/Collapse All

Two related gaps:

1. loadTree() only auto-expanded nodes when expandedNodes was
   completely empty — that was "first-load only" behaviour. After
   an import, the subsequent loadTree() found the map populated
   and skipped the expand pass entirely, so every freshly imported
   node came in collapsed ("2 hidden"). Users had to click each
   one open by hand.

   Fix: iterate the whole tree on every load and default any node
   whose id isn't yet in expandedNodes to true. Nodes the user
   explicitly collapsed stay that way (their id IS in the map,
   set to false).

2. Added "Expand all" and "Collapse all" buttons to the tree-
   editor header so operators can get a full view (or a tight
   overview) without clicking node by node. Collapse all keeps
   the recipe root expanded — otherwise the canvas goes blank.

fusion_plating → 19.0.7.3.0

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
gsinghpal
2026-04-23 08:20:39 -04:00
parent 9d7b7daf5a
commit 7629af4e00
3 changed files with 42 additions and 10 deletions

View File

@@ -5,7 +5,7 @@
{
'name': 'Fusion Plating',
'version': '19.0.7.2.0',
'version': '19.0.7.3.0',
'category': 'Manufacturing/Plating',
'summary': 'Core plating / metal finishing ERP: facilities, processes, tanks, baths, jobs, operators.',
'description': """

View File

@@ -157,16 +157,19 @@ export class RecipeTreeEditor extends Component {
if (result && result.ok) {
this.state.recipe = result.recipe;
this.state.tree = result.tree;
// Auto-expand every node on first load so the full
// hierarchy is visible. The horizontal bracket layout
// works best when everything is open by default;
// operators can still collapse individual branches.
if (result.tree && Object.keys(this.state.expandedNodes).length === 0) {
const expandAll = (n) => {
this.state.expandedNodes[n.id] = true;
for (const c of (n.children || [])) expandAll(c);
// Auto-expand every node on first load AND auto-expand
// any node we haven't seen before (e.g. freshly imported
// nodes after a "Import from recipe" run). Nodes the
// user has explicitly collapsed stay collapsed — we only
// touch nodes that are missing from expandedNodes.
if (result.tree) {
const applyDefault = (n) => {
if (!(n.id in this.state.expandedNodes)) {
this.state.expandedNodes[n.id] = true;
}
for (const c of (n.children || [])) applyDefault(c);
};
expandAll(result.tree);
applyDefault(result.tree);
}
// Refresh selected node data if panel is open
if (this.state.selectedNodeId) {
@@ -209,6 +212,25 @@ export class RecipeTreeEditor extends Component {
this.state.expandedNodes[nodeId] = !this.state.expandedNodes[nodeId];
}
expandAll() {
const walk = (n) => {
this.state.expandedNodes[n.id] = true;
for (const c of (n.children || [])) walk(c);
};
if (this.state.tree) walk(this.state.tree);
}
collapseAll() {
// Collapse everything EXCEPT the recipe root itself — otherwise
// the canvas goes blank and the user has to click the root open
// again to see anything.
const walk = (n, isRoot) => {
this.state.expandedNodes[n.id] = isRoot;
for (const c of (n.children || [])) walk(c, false);
};
if (this.state.tree) walk(this.state.tree, true);
}
// ---- Node selection (side panel) ----------------------------------------
selectNode(node) {

View File

@@ -179,6 +179,16 @@
</div>
</div>
<div class="o_fp_re_header_actions" t-if="state.recipe">
<button class="o_fp_re_btn_outline"
t-on-click="expandAll"
title="Expand every branch">
<i class="fa fa-expand me-1"/>Expand all
</button>
<button class="o_fp_re_btn_outline"
t-on-click="collapseAll"
title="Collapse every branch">
<i class="fa fa-compress me-1"/>Collapse all
</button>
<button class="o_fp_re_btn_outline"
t-on-click="toggleImportPicker"
title="Import children from another recipe">