From 7629af4e00ceb277ead12b5c0c536e6bcf2f3909 Mon Sep 17 00:00:00 2001 From: gsinghpal Date: Thu, 23 Apr 2026 08:20:39 -0400 Subject: [PATCH] =?UTF-8?q?fix(plating):=20tree=20editor=20=E2=80=94=20exp?= =?UTF-8?q?and=20newly=20imported=20nodes=20+=20Expand/Collapse=20All?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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) --- fusion_plating/fusion_plating/__manifest__.py | 2 +- .../static/src/js/recipe_tree_editor.js | 40 ++++++++++++++----- .../static/src/xml/recipe_tree_editor.xml | 10 +++++ 3 files changed, 42 insertions(+), 10 deletions(-) diff --git a/fusion_plating/fusion_plating/__manifest__.py b/fusion_plating/fusion_plating/__manifest__.py index 2f1e7b68..e9d774e9 100644 --- a/fusion_plating/fusion_plating/__manifest__.py +++ b/fusion_plating/fusion_plating/__manifest__.py @@ -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': """ diff --git a/fusion_plating/fusion_plating/static/src/js/recipe_tree_editor.js b/fusion_plating/fusion_plating/static/src/js/recipe_tree_editor.js index fccbb59b..bd5e81af 100644 --- a/fusion_plating/fusion_plating/static/src/js/recipe_tree_editor.js +++ b/fusion_plating/fusion_plating/static/src/js/recipe_tree_editor.js @@ -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) { diff --git a/fusion_plating/fusion_plating/static/src/xml/recipe_tree_editor.xml b/fusion_plating/fusion_plating/static/src/xml/recipe_tree_editor.xml index 770e9422..124e2e9c 100644 --- a/fusion_plating/fusion_plating/static/src/xml/recipe_tree_editor.xml +++ b/fusion_plating/fusion_plating/static/src/xml/recipe_tree_editor.xml @@ -179,6 +179,16 @@
+ +