diff --git a/webapp/home/utils/create_nodes.py b/webapp/home/utils/create_nodes.py index 28b616a6..cc23f84e 100644 --- a/webapp/home/utils/create_nodes.py +++ b/webapp/home/utils/create_nodes.py @@ -26,7 +26,7 @@ from webapp.utils import null_string from webapp.home.home_utils import RELEASE_NUMBER, log_error, log_info from webapp.home.metapype_client import VariableType -from webapp.home.utils.node_utils import new_child_node, remove_child, add_node, Optionality +from webapp.home.utils.node_utils import new_child_node, add_node, Optionality import webapp.home.utils.load_and_save as load_and_save diff --git a/webapp/home/utils/node_utils.py b/webapp/home/utils/node_utils.py index 09feacc1..9301176c 100644 --- a/webapp/home/utils/node_utils.py +++ b/webapp/home/utils/node_utils.py @@ -81,3 +81,23 @@ def remove_child(child_node:Node): parent_node = child_node.parent if parent_node: parent_node.remove_child(child_node) + + +def replace_node(new_node:Node, old_node_id:str): + """ + If the old_node_id is not '1', replace the old node with the new node. + This is used on pages that support Save Changes, where we want the modified node to replace the original node, + using the same node ID so the Back button works as expected. + """ + if old_node_id and old_node_id != '1': + old_node = Node.get_node_instance(old_node_id) + if old_node: + parent_node = old_node.parent + if parent_node: + # Make the replacement in the node tree + parent_node.replace_child(old_node, new_node, delete_old=False) + # Make the replacement in the node instance dictionary + new_node_id = new_node.id + new_node._id = old_node.id + Node.set_node_instance(new_node) + Node.delete_node_instance(id=new_node_id) diff --git a/webapp/home/views.py b/webapp/home/views.py index 345ae5e2..c75c5002 100644 --- a/webapp/home/views.py +++ b/webapp/home/views.py @@ -1764,7 +1764,7 @@ def open_template(): filename = copy_template_to_user_data(filename) flash(f'Template "{filename}" has been copied to your user data directory and opened for editing.\n\n' - f"When you are done editing, use 'Save As Template' to save your changes to the template.", 'success') + f"When you are done editing, use 'Save As Template' on the 'Manage Templates' page to save your changes to the template.", 'success') # Open the document. Note that open_document takes care of handling locks. return open_document(filename) diff --git a/webapp/views/data_tables/dt.py b/webapp/views/data_tables/dt.py index 3dd55295..976ca6e9 100644 --- a/webapp/views/data_tables/dt.py +++ b/webapp/views/data_tables/dt.py @@ -23,7 +23,7 @@ from markupsafe import Markup import webapp.home.utils.create_nodes -import webapp.home.utils.node_utils +# import webapp.home.utils.node_utils import webapp.views.data_tables.load_data from webapp.config import Config @@ -51,7 +51,7 @@ ) from webapp.home.metapype_client import VariableType -from webapp.home.utils.node_utils import remove_child, new_child_node, add_child +from webapp.home.utils.node_utils import remove_child, new_child_node, add_child, replace_node from webapp.home.utils.hidden_buttons import is_hidden_button, handle_hidden_buttons, check_val_for_hidden_buttons from webapp.home.utils.node_store import dump_node_store from webapp.home.utils.load_and_save import load_eml, save_both_formats, handle_custom_unit_additional_metadata @@ -269,9 +269,7 @@ def compose_atts(att_list: list = []): # If we're modifying an existing data table, we need to replace the old data table node with the # new one. - dataset_parent_node = old_dt_node.parent - dataset_parent_node.replace_child(old_dt_node, dt_node) - dt_node_id = dt_node.id + replace_node(dt_node, old_dt_node.id) else: msg = f"No node found in the node store with node id {dt_node_id}" dump_node_store(eml_node, 'data_table') @@ -1300,8 +1298,7 @@ def attribute_dateTime(filename=None, dt_node_id=None, node_id=None): if node_id and len(node_id) != 1: old_att_node = Node.get_node_instance(att_node_id) if old_att_node: - att_parent_node = old_att_node.parent - att_parent_node.replace_child(old_att_node, att_node) + replace_node(att_node, old_att_node.id) else: msg = f"No node found in the node store with node id {node_id}" dump_node_store(eml_node, 'attribute_dateTime') @@ -1547,8 +1544,7 @@ def attribute_numerical(filename=None, dt_node_id=None, node_id=None, mscale=Non if node_id and len(node_id) != 1: old_att_node = Node.get_node_instance(att_node_id) if old_att_node: - att_parent_node = old_att_node.parent - att_parent_node.replace_child(old_att_node, att_node) + replace_node(att_node, old_att_node.id) else: msg = f"No node found in the node store with node id {node_id}" dump_node_store(eml_node, 'attribute_numerical') @@ -1858,8 +1854,7 @@ def code_definition_from_attribute(att_node: Node = None): if node_id and len(node_id) != 1: old_att_node = Node.get_node_instance(att_node_id) if old_att_node: - att_parent_node = old_att_node.parent - att_parent_node.replace_child(old_att_node, att_node) + replace_node(att_node, old_att_node.id) else: msg = f"No node found in the node store with node id {node_id}" dump_node_store(eml_node, 'attribute_categorical') diff --git a/webapp/views/responsible_parties/rp.py b/webapp/views/responsible_parties/rp.py index 13fa4a50..4b9c3a56 100644 --- a/webapp/views/responsible_parties/rp.py +++ b/webapp/views/responsible_parties/rp.py @@ -19,7 +19,7 @@ from webapp.home.utils.load_and_save import load_eml, save_both_formats from webapp.home.utils.lists import list_responsible_parties from webapp.home.utils.create_nodes import create_responsible_party -from webapp.home.utils.node_utils import add_child, new_child_node +from webapp.home.utils.node_utils import add_child, new_child_node, replace_node from metapype.eml import names from metapype.model.node import Node @@ -266,9 +266,6 @@ def responsible_party(filename=None, rp_node_id=None, child nodes, and it is easier to create a new one from scratch than to try to modify an existing one. The responsibleParty node has a number of child nodes that have cardinality 0..infinity, which makes it a lot more complicated to find and modify the appropriate children to modify. - - A complication, though, is that the node ID will change, which we need to allow for if Save Changes is - clicked, bringing us back to the same page. I.e., we want the generated URL to use the new node ID. """ rp_node = Node(node_name, parent=parent_node) @@ -299,16 +296,15 @@ def responsible_party(filename=None, rp_node_id=None, if rp_node_id and len(rp_node_id) != 1: old_rp_node = Node.get_node_instance(rp_node_id) if old_rp_node: - old_rp_parent_node = old_rp_node.parent - old_rp_parent_node.replace_child(old_rp_node, rp_node) + replace_node(rp_node, old_rp_node.id) else: msg = f"No node found in the node store with node id {rp_node_id}" raise Exception(msg) else: add_child(parent_node, rp_node) - # We want generated URLs, below, to point to the new responsibleParty node - rp_node_id = rp_node.id + # We want generated URLs, below, to point to the new responsibleParty node, but we have + # given the new node the same node ID as the old node. So, we just leave the node ID as is. save_both_formats(filename=filename, eml_node=eml_node) # flash(f"Changes to the '{node_name}' element have been saved.")