From 522d8ca903c795cdde9921d3a3148611fd4a3720 Mon Sep 17 00:00:00 2001 From: baigner <benedikt.aigner@rwth-aachen.de> Date: Tue, 22 May 2018 17:04:42 +0200 Subject: [PATCH] VISTOMS update: Upload and execution of custom kadmos scripts is now possible Former-commit-id: 9b113eaa7dee14869abd706b9e94a9d085562ce8 --- kadmos/vistoms/templates/VISTOMS.html | 200 ++++++++++++++++++++------ kadmos/vistoms/vistoms.py | 68 ++++++++- 2 files changed, 224 insertions(+), 44 deletions(-) diff --git a/kadmos/vistoms/templates/VISTOMS.html b/kadmos/vistoms/templates/VISTOMS.html index c6b1e9f9a..d414490cd 100644 --- a/kadmos/vistoms/templates/VISTOMS.html +++ b/kadmos/vistoms/templates/VISTOMS.html @@ -655,7 +655,7 @@ $('#addForm').on('submit',function(event){ event.preventDefault(); //aigner: Uploading files for KADMOS - formData = new FormData($('form')[0]); + var formData = new FormData($('#addForm')[0]); formData.append('newGraphID', newGraphID); formData.append('fileType',selectValue) @@ -20961,6 +20961,161 @@ //#################################################################################################################### + //aigner: Upload custom KADMOS script + //HIER WEITER!! + //#################################################################################################################### + var uploadCustomScript_ul = optionsDiv.append("ul") + var uploadCustomScript_li = uploadCustomScript_ul.append("li") + .on("mouseover", function(){ + d3.select(this) + .style("cursor", "pointer") + }) + .on("mousedown", function(){ + bootbox.dialog({ + title: "Upload custom script", + message: "<button id='downloadBtn' class='btn btn-primary'><i class='glyphicon glyphicon-download-alt '></i> Download template script</button>" + +"<form style='margin-top:20px;' id='scriptForm' method='post' enctype='multipart/form-data'>" + +"<label>" + +"<text>Upload script file:</text>" + +"<input type='file' name='file[]' />" + +"<input type='submit' value='Submit'/>" + +"</label></form>", + buttons : + { + cancel: { + label: "Cancel", + className: 'btn-danger' + } + } + }); + + //aigner: template for custom script that user can download + $('#downloadBtn').on("mousedown", function(){ + var script_template = "import sys\n\n" + +"from kadmos.graph import *\n\n\n" + +"def script(graph, mpg):\n" + +" \"\"\"\n" + +" Script to include manual operations in the KADMOS integration in VISTOMS\n\n" + +" :param graph: Any kadmos graph\n" + +" :param mpg: A corresponding MDO process graph\n" + +" :return: graph, mpg\n" + +" \"\"\"\n" + +" # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #\n" + +" # ADD YOUR SCRIPT BELOW THIS LINE #\n" + +" # Example script:\n" + +" # graph.remove_node('node_ID')\n" + +" # graph.remove_edge('node_ID1', 'node_ID2')\n" + +" # END SCRIPT ABOVE THIS LINE #\n" + +" # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #\n" + +" return graph, mpg\n" + + download('script_template.py',script_template); + }) + //upload of custom script + $('#scriptForm').on('submit',function(event){ + event.preventDefault(); + var formData = new FormData($('#scriptForm')[0]); + formData.append('graphID', graphID); + + if (typeof currentGraph.xdsm.workflow !== 'undefined' && currentGraph.xdsm.workflow.length > 0) + { + // the array is defined and has at least one element + upload_custom_script() + } + else + { + upload_custom_script() + } + + function upload_custom_script() + { + var bootboxContent = {title: "Upload custom KADMOS script", message: '<p>Please be patient...</p>'}; + var xhr = $.ajax({ + type: 'POST', + url: '/kadmosRunCustomScript', + data: formData, + processData: false, + contentType: false, + success: function(result) + { + if (result.includes("ERROR:")) + { + bootboxContent.message = result + kadmosErrorMessage(bootboxContent); + } + else + { + var updatedData = {}; + updatedData = data; + var graphData = JSON.parse(result); + for (var i = 0; i < updatedData.graphs.length; i++) + { + if (graphID == updatedData.graphs[i].id) + { + updatedData.graphs[i] = graphData.graphs[0]; + } + } + + clearView(); + makeKadmosMenu(updatedData); + xdsm_script(updatedData,graphID); + + bootboxContent.message = "Success!" + kadmosSuccessMessage(bootboxContent) + } + }, + error: function(result) + { + bootboxContent.message = result + kadmosErrorMessage(bootboxContent); + } + }); + kadmosHavePatience(xhr, bootboxContent) + } + }); + }) + + uploadCustomScript_li.append("a").text("Upload Custom Script") + //#################################################################################################################### + + + //aigner: Data Model Tree View Button + //#################################################################################################################### + var dataModelDiv = d3.select(".xdsmDiv").append("div").attr("class","dataModelDiv").attr("transform","translate(10,0)") + var ul = dataModelDiv.append("ul") + var dropdown1 = ul.append("li").on("mouseover", function(){d3.select(this).style("cursor", "default")}) + dropdown1.append("img").attr("src",fileReference.AGILE_Icon) + .attr("align","left") + .style("margin-left","6px") + .style("margin-right","-10px") + .style("margin-top","10px") + .style("margin-bottom","0px") + .attr("height","20") + .attr("width","20") + dropdown1.append("a").text("Data Model Tree") + var links = dropdown1.append("ul"); + var xOffset_ul = dropdown1._groups[0][0].offsetLeft+dropdown1._groups[0][0].offsetWidth-40; + links.style("left", String(xOffset_ul)+"px") + for (var j=0; j< varCategories.length; j++) + { + //console.log(varCategories[j]) + var linkLi = links.append("li"); + var linkA = linkLi.append("a") + .attr("id",j) + .text(varCategories[j].description) + .on("mouseover", function(){d3.select(this).style("cursor", "pointer")}) + .on("click", function() + { + showFullTree(varCategories[this.id].name,varCategories[this.id].description) + }) + } + //aigner: Set width of the div, so the VISTOMS dropdown (in the top of the page) still works + //dataModelDiv.style("width", String(dropdown1.node().getBoundingClientRect().width+20)+"px") + //#################################################################################################################### + + //aigner: Data Model List View Button + //#################################################################################################################### + //aigner: Function, that shows a list of elements function showList(aTitle,aList,aMenu) { if (aList.length != 0) @@ -21004,44 +21159,7 @@ } } - - //aigner: Data Model Tree View Button - //#################################################################################################################### - var dataModelDiv = d3.select(".xdsmDiv").append("div").attr("class","dataModelDiv").attr("transform","translate(10,0)") - var ul = dataModelDiv.append("ul") - var dropdown1 = ul.append("li").on("mouseover", function(){d3.select(this).style("cursor", "default")}) - dropdown1.append("img").attr("src",fileReference.AGILE_Icon) - .attr("align","left") - .style("margin-left","6px") - .style("margin-right","-10px") - .style("margin-top","10px") - .style("margin-bottom","0px") - .attr("height","20") - .attr("width","20") - dropdown1.append("a").text("Data Model Tree") - var links = dropdown1.append("ul"); - var xOffset_ul = dropdown1._groups[0][0].offsetLeft+dropdown1._groups[0][0].offsetWidth-40; - links.style("left", String(xOffset_ul)+"px") - for (var j=0; j< varCategories.length; j++) - { - //console.log(varCategories[j]) - var linkLi = links.append("li"); - var linkA = linkLi.append("a") - .attr("id",j) - .text(varCategories[j].description) - .on("mouseover", function(){d3.select(this).style("cursor", "pointer")}) - .on("click", function() - { - showFullTree(varCategories[this.id].name,varCategories[this.id].description) - }) - } - //aigner: Set width of the div, so the VISTOMS dropdown (in the top of the page) still works - //dataModelDiv.style("width", String(dropdown1.node().getBoundingClientRect().width+20)+"px") - //#################################################################################################################### - - //aigner: Data Model List View Button - //#################################################################################################################### - var ul_list = dataModelDiv.append("ul") + var ul_list = dataModelDiv.append("ul") var dropdownList = ul_list.append("li").on("mouseover", function(){d3.select(this).style("cursor", "default")}) dropdownList.append("img").attr("src",fileReference.AGILE_Icon) .attr("align","left") @@ -21913,10 +22031,6 @@ $('form').on('submit',function(event){ event.preventDefault(); - - var formData = new FormData($('form')[0]); - formData.append('graphID', graphID); - }); diff --git a/kadmos/vistoms/vistoms.py b/kadmos/vistoms/vistoms.py index 7b3d11601..e23622cce 100644 --- a/kadmos/vistoms/vistoms.py +++ b/kadmos/vistoms/vistoms.py @@ -618,6 +618,70 @@ def kadmosL3Check(): # Logs the error appropriately. ######################################################################################################################## +# Upload custom kadmos script +######################################################################################################################## +@app.route('/kadmosRunCustomScript', methods=['POST']) +def kadmosRunCustomScript(): + """ + Generic function to import and execute a custom kadmos script + + :param script_file: the custom kadmos script + :param graph: the kadmos graph, on which the changes are performed + :return: newVistomsData: Merged string of the vistoms data and the script string value + """ + try: + # Get request form + graphID = request.form['graphID'] + uploaded_files = request.files.getlist("file[]") + + script_file = [] + for aFile in uploaded_files: + file_type = aFile.filename.rsplit('.', 1)[1].lower() + if not file_type == "py": + return "ERROR: wrong file type \"" + file_type + "\"" + script_file = aFile + + # Save previous graph as backup before making the changes + savePreviousGraph(graphID) + + path = UPLOAD_FOLDER + graphFileName = TEMP_FILE + '_' + graphID + '.kdms' + mpgFileName = TEMP_FILE + '_' + graphID + '_mpg.kdms' + if os.path.exists(os.path.join(path, mpgFileName)): + graph = load(os.path.join(path, graphFileName), file_check_critical=False) + mpg = load(os.path.join(path, mpgFileName), file_check_critical=False) + else: + graph = load(os.path.join(path, graphFileName), file_check_critical=False) + mpg = None + + # save kadmos script in temp folder + script_file.save(os.path.join(UPLOAD_FOLDER, script_file.filename)) + kadmos_file_path = os.path.join(UPLOAD_FOLDER, script_file.filename) + + # execute script and return graph data (graph, mpg) + import imp + script_module = imp.load_source('kadmos_custom_fun_{}', kadmos_file_path) + graph, mpg = script_module.script(graph, mpg) + + # Get function order for VISTOMS in case of FPG + function_order = None + if mpg == None: + # Get function_oder of the graph after the script has done the manipulations + if graph.graph_has_nested_attributes('problem_formulation', 'function_order'): + function_order = graph.graph['problem_formulation']['function_order'] + + # Add modified graph to VISTOMS + newVistomsData = graph.vistoms_add_json(function_order=function_order, graph_id=graphID, mpg=mpg) + # Save the graph in temp/tmp.kdms + graph.save(os.path.join(UPLOAD_FOLDER, TEMP_FILE + '_' + graphID + '.kdms'), file_type='kdms', + graph_check_critical=False, mpg=mpg) + return newVistomsData + + except Exception as e: + return "ERROR: " + e.message + # Logs the error appropriately. +######################################################################################################################## + # FPG manipulation functions ######################################################################################################################## @@ -748,9 +812,11 @@ def kadmosDeleteNode(): # update function order function_order.remove(nodeName) - # Add the graph with the updated function order to VISTOMS newVistomsData = graph.vistoms_add_json(function_order=function_order, graph_id=graphID, mpg=mpg) + # Use function order for VISTOMS if it is available in the graph information + if graph.graph_has_nested_attributes('problem_formulation', 'function_order') and mpg == None: + graph.graph['problem_formulation']['function_order'] = function_order # Save the graph in temp/tmp.kdms graph.save(os.path.join(UPLOAD_FOLDER, TEMP_FILE+'_'+graphID+'.kdms'), file_type='kdms', graph_check_critical=False, mpg=mpg) -- GitLab