From a4227c54400dcfa0cf3f94e6965a8377eb71a67d Mon Sep 17 00:00:00 2001 From: dengzq1234 Date: Fri, 20 Dec 2024 13:15:28 +0100 Subject: [PATCH 01/26] allow delete layouts --- treeprofiler/app.py | 43 +++++++++++--- treeprofiler/views/explore_tree_v2.html | 77 ++++++------------------- 2 files changed, 54 insertions(+), 66 deletions(-) diff --git a/treeprofiler/app.py b/treeprofiler/app.py index b992e8c..a250deb 100644 --- a/treeprofiler/app.py +++ b/treeprofiler/app.py @@ -498,14 +498,18 @@ def check_job_status(): status = job_status.get(job_id, "not_found") return status -@app.route('/explore_tree/', method=['GET', 'POST']) +@app.route('/explore_tree/', method=['GET', 'POST', 'PUT']) def explore_tree(treename): tree_info = trees.get(treename) if not tree_info: return f"Tree '{treename}' not found." - + # Retrieve and initialize layouts, properties, and tree current_layouts = tree_info.get('layouts', []) + + layout_manager = {} + if current_layouts: + layout_manager = {layout.name: layout for layout in current_layouts} current_props = sorted(list(tree_info['prop2type'].keys())) if tree_info['updated_tree']: @@ -540,7 +544,6 @@ def explore_tree(treename): tree_info['layouts'] = [] # Clear applied layouts current_layouts = [] # Clear layouts layouts_metadata.clear() # Clear metadata - else: layers_data = request.forms.get('layers') level = int(request.forms.get('level', default_configs['level'])) @@ -590,6 +593,7 @@ def explore_tree(treename): "color_config": getattr(layout, 'color_config', {}) } }) + layout_manager[layout.name] = layout elif layout_prefix in ['alignment', 'domain']: layouts_metadata.append({ "layout_name": layout.name, @@ -602,6 +606,7 @@ def explore_tree(treename): "color_config": getattr(layout, 'color_config', {}) } }) + layout_manager[layout.name] = layout elif layout_prefix in ['profiling', 'categorical-matrix', 'numerical-matrix', 'binary-matrix']: # Append with applied props and full config name = layout.name @@ -617,6 +622,7 @@ def explore_tree(treename): "color_config": getattr(layout, 'color_config', {}) } }) + layout_manager[layout.name] = layout elif layout_prefix in ['collapsed-by', 'highlighted-by']: # Append with applied props and full config name = layout.name @@ -632,6 +638,7 @@ def explore_tree(treename): "color_config": getattr(layout, 'color_config', {}) } }) + layout_manager[layout.name] = layout else: # Append with applied props and full config name = layout.name @@ -647,13 +654,35 @@ def explore_tree(treename): "color_config": getattr(layout, 'color_config', {}) } }) - + layout_manager[layout.name] = layout + + # Process PUT request for updating layouts + if request.method == 'PUT': + if request.forms.get('updated_metadata'): + try: + # layouts_metadata.clear() + updated_metadata = json.loads(request.forms.get('updated_metadata')) + tree_info['layouts_metadata'] = updated_metadata + current_layouts = [] + + for layout in updated_metadata: + layout = layout_manager.get(layout['layout_name']) + if layout: + current_layouts.append(layout) + + tree_info['layouts'] = current_layouts + start_explore_thread(t, treename, current_layouts, current_props) + #return "Layouts metadata updated successfully." + except json.JSONDecodeError: + return "Invalid metadata format.", 400 # Start the ete exploration thread - start_explore_thread(t, treename, current_layouts, current_props) + + if request.method == 'GET': + start_explore_thread(t, treename, current_layouts, current_props) # Before rendering the template, convert to JSON #layouts_json = json.dumps(tree_info['layouts']) - #layouts_metadata_json = json.dumps(layouts_metadata) + layouts_metadata_json = json.dumps(layouts_metadata) # Render template return template( @@ -663,7 +692,7 @@ def explore_tree(treename): selected_props=current_props, color_schemes=continuous_colormaps, layouts_metadata=layouts_metadata, - #layouts_metadata_json = json.dumps(layouts_metadata) + layouts_metadata_json = json.dumps(layouts_metadata) ) def get_colormap_hex_colors(colormap_name, num_colors): diff --git a/treeprofiler/views/explore_tree_v2.html b/treeprofiler/views/explore_tree_v2.html index d20ae38..0bfa750 100644 --- a/treeprofiler/views/explore_tree_v2.html +++ b/treeprofiler/views/explore_tree_v2.html @@ -572,7 +572,7 @@
Manage Loaded Layouts
- +
@@ -852,70 +852,30 @@

Explore Tree: {{treename}}

.catch(error => console.error('Error:', error)); }); - // update changes - // document.addEventListener('DOMContentLoaded', () => { - // // Event delegation for the delete button - // document.getElementById('activeLayoutsTable').addEventListener('click', function(event) { - // const deleteBtn = event.target.closest('.delete-layout-btn'); - // if (deleteBtn) { - // const row = deleteBtn.closest('tr'); - - // // Clear all cells' content except the row structure - // row.querySelectorAll('td').forEach(cell => { - // cell.innerHTML = ''; - // }); - // } - // }); - - // // Handle Apply Changes - // document.getElementById('applyChangesBtn').addEventListener('click', function() { - // const remainingLayouts = []; - // console.log('Applying changes...', remainingLayouts) - // // Collect rows with content - // document.querySelectorAll('#activeLayoutsTable tr').forEach(row => { - // const layoutName = row.querySelector('td:nth-child(1)').innerText.trim(); - // const appliedProps = Array.from(row.querySelectorAll('td:nth-child(2) li')) - // .map(prop => prop.innerText.trim()); - - // if (layoutName) { // Only include rows that are not cleared - // remainingLayouts.push({ - // layout_name: layoutName, - // applied_props: appliedProps - // }); - // } - // }); - - // // Send the remaining layouts back to the backend - // fetch('', { - // method: 'POST', - // headers: { 'Content-Type': 'application/json' }, - // body: JSON.stringify({ action: 'apply_changes', layouts: remainingLayouts }) - // }) - // .then(response => response.text()) - // .then(data => { - // alert('Changes applied successfully!'); - // location.reload(); // Optionally reload the page - // }) - // .catch(error => console.error('Error:', error)); - // }); - // }); + + - - + - --> + - +