From 88cf523d5d482a7de4607563bf3507ec2a55ad73 Mon Sep 17 00:00:00 2001 From: Eric Fayolle Date: Thu, 14 Mar 2024 16:30:52 +0100 Subject: [PATCH] Fusion depuis le branche web_fancy-tree --- Web/mdm3.py | 147 ++++++++++++++++- Web/templates/available_catalogs.html | 178 ++++++++++---------- Web/templates/base.html | 4 +- Web/templates/commandes.html | 37 ----- Web/templates/commandes_2.html | 226 ++++++++++++++++++-------- Web/templates/file_management.html | 2 +- Web/templates/main_menu.html | 19 ++- 7 files changed, 399 insertions(+), 214 deletions(-) delete mode 100644 Web/templates/commandes.html diff --git a/Web/mdm3.py b/Web/mdm3.py index 9ea0c6ce..43eef43c 100644 --- a/Web/mdm3.py +++ b/Web/mdm3.py @@ -23,14 +23,16 @@ import traceback import json import os from pprint import pprint +#from forms import BasicForm #Essais WtForms from collections import OrderedDict from markupsafe import escape # Flask management of Server Side Event +# Necessite redis from flask_sse import sse +# from flask_uploads import UploadSet, configure_uploads, IMAGES app = Flask(__name__) -app.secret_key = 'EssaiPN' # CATALOGS_EXT=("py","jpg") #TODO : supprimer jpg pour test # catalogs = UploadSet("catalogs",CATALOGS_EXT) @@ -94,7 +96,8 @@ def propageValide(sId, eId, id, valid): #TODO: RENAME TO ... propagateValidation def updateNodeInfo(sId, eId, id, info): print ('Flask/updateNodeInfo', sId, eId, id, info) - sse.publish( {'eId' : eId, 'id':id, 'info':info, 'message': "Hello from updateNodeInfo!"}, type='updateNodeInfo', channel = sId) + sse.publish( {'eId' : eId, 'id':id, 'info':info, 'message': "Hello from updateNodeInfo!"}, type='updateNodeInfo') +# sse.publish( {'eId' : eId, 'id':id, 'info':info, 'message': "Hello from updateNodeInfo!"}, type='updateNodeInfo', channel = sId) def appendChildren(sId, eId, id, fcyTreeJson, pos): print ('Flask/appendChildren: ', id, fcyTreeJson, pos) @@ -126,6 +129,7 @@ def afficheAlerte(sId, eId, titre, message): #TODO: RENAME TO . # Pour PROC : Ajoute, Supprime # Pour OPER : Ajoute, Supprime, Nomme, Renomme # @app.route('/post/') + @app.route("/updateSimp", methods=['POST']) def updateSimp(): # Validate the request body contains JSON @@ -171,6 +175,8 @@ def updateSDName(): # Parse the JSON into a Python dictionary req = request.get_json() # Print the dictionary + #print(req) + #print(req['id']) id=req['id'];sdnom=req['sdnom'] sdnom = str(sdnom) #On peut écrire Pi # On attendant que l externalEditorId soit dans le tree @@ -218,9 +224,9 @@ def removeNode(): @app.route("/appendChild", methods=['POST']) def appendChild(): # Validate the request body contains JSON - print ('__________________________________________') - print ( 'in appendChild') - print ('__________________________________________') + # print ('__________________________________________') + # print ( 'in appendChild') + # print ('__________________________________________') if request.is_json: # Parse the JSON into a Python dictionary req = request.get_json() @@ -235,7 +241,7 @@ def appendChild(): (newId, codeErreur, message) = eficasEditor.appendChild(session['canalId'],session['externEditorId'],id,name,pos); print (__file__+"/appendChild : newId : ",newId); - return make_response(json.dumps( {'id':newId} )) + return make_response(json.dumps( {'id':newId} )) #TODO: Code Erreur # return make_response(json.dumps( {'source':node, 'changeIsAccepted' : changeDone, 'message': message} )) # Return a string along with an HTTP status code # return "JSON received!", 200 @@ -244,6 +250,46 @@ def appendChild(): return "Request was not JSON", 400 #return make_response(jsonify({"message": "Request body must be JSON"}), 400) +@app.route("/newDataset", methods=['POST']) +def newDataset(): + + # Validate the request body contains JSON + if request.is_json: + # Parse the JSON into a Python dictionary + req = request.get_json() + # Print the dictionary + print(__file__+"/newDataset : ",req); + catalogName=req['catalogName'];datasetName=req['datasetName']; + #QUESAKO code ? + + #TODO: pour l'instant un seul connecteur mono utilisateur + # il faudra gérer les différents utilisateurs avec la session Flask et + # disposer de plusieurs connecteurs par utilisateur. + #try { ? + # monConnecteur=createConnecteur(app,catalogName,datasetName) + # ou + monConnecteur = createConnecteur(app,catalogFile=os.path.join('data',catalogName)) + #monConnecteur.litFichierComm(datasetName) + myFancyTreeDico= monConnecteur.getDicoForFancy(monConnecteur.monEditeur.tree.racine) + myFancyTreeJS = json.dumps([myFancyTreeDico],indent=4) #TODO : remove indent if not DEBUG + pprint( myFancyTreeJS) + commands = monConnecteur.getListeCommandes(); + #TODO: Gérer le titre + # return make_response(json.dumps( {'source':myFancyTreeJS, 'commands':commands, 'titre':code} )) + + # TODO : Envoyer un evenement de création de JDD au javascript qui gèrera les onglets... + # et ne relancera pas le render + # return render_template('commandes_2.html', + # titre=code, + # listeCommandes = monConnecteur.getListeCommandes(), + # tree=myFancyTreeJS, + # ) + + else: + # The request body wasn't JSON so return a 400 HTTP status code + return "Request was not JSON", 400 + #return make_response(jsonify({"message": "Request body must be JSON"}), 400) + @app.route('/') def index(): print ('_______________________________________________') @@ -260,7 +306,7 @@ def index(): # listeCommandes = [], # tree= None # ) - cataFile = os.path.abspath('../Codes/WebTest/cata_essai.py') + cataFile = os.path.abspath('../Codes/WebTest/cata_essai.py') dataSetFile = os.path.abspath('../Codes/WebTest/web_tres_simple_avec_2Fact.comm') # En attendant la partie Eric # notion de plage @@ -319,6 +365,43 @@ def index(): +# @app.route("/forward/", methods=['POST']) +# def move_forward(): +# #Moving forward code +# forward_message = "Moving Forward..." +# return render_template('mdm.html', message=forward_message) + + + +# @app.route('/form', methods=['GET', 'POST']) +# def basicform(): +# form = BasicForm(request.form) +# if request.method == 'POST' and form.validate(): +# with open('/tmp/test.txt', 'w') as f: +# for k in request.form: +# f.write('{0}: {1}\n'.format(k, request.form[k])) +# return render_template('basic.html', form=form) + +# @app.route("/json", methods=["POST"]) +# def json_example(): + +# if request.is_json: + +# req = request.get_json() + +# response_body = { +# "message": "JSON received!", +# "sender": req.get("name") +# } + +# res = make_response(jsonify(response_body), 200) + +# return res + +# else: + +# return make_response(jsonify({"message": "Request body must be JSON"}), 400) + #TODO: #from fileManagement import * @@ -435,6 +518,8 @@ def get_file(filename): # @app.route("/_upload", methods=['POST']) # def _upload(): +# # Validate the request body contains JSON +# if request.is_json: # # Parse the JSON into a Python dictionary # req = request.get_json() # # Print the dictionary @@ -470,3 +555,51 @@ def get_file(filename): if __name__ == "__main__": app.run(host="localhost", port=8321, debug=True) +#$("#386bc28a2ff811ec853cac220bca9aa6").html('Essai') + +# $("#550f63502b6611ecab61ac220bca9aa6").hover(function(){ +# alert("The text has been changed."); +# }); + +# $("#1f3ca24a2cf911ecab61ac220bca9aa6").hover(function(){ +# $.post("{{ url_for('static', filename='demo_test.txt') }}", +# { +# id: $(this).attr("id"), +# }, +# function(data, status){ +# alert("Data: " + data + "\nStatus: " + status); +# }); +# }); + +# $("#e0a1f2862cfa11ecab61ac220bca9aa6").hover(function(){ +# $.post("http://127.0.0.1:8123/test1", +# { +# id: $(this).attr("id"), +# }, +# function(data, status){ +# alert("Data: " + data + "\nStatus: " + status); +# }); +# }); + +# $(".MCSIMPValide").hover(function(){ +# alert("-5-- :"+ $(this).text() + $("#e0a1f2862cfa11ecab61ac220bca9aa6").text() + $(this).attr("class") + $(this).attr("id")); +# $.post("http://127.0.0.1:8123/test1", +# { +# id: $(this).attr("id"), +# }, +# function(data, status){ +# alert("Data: " + data + "\nStatus: " + status +"\nId :", $(this).attr("id") ); +# }); +# }); + + +# # # $("#550f63502b6611ecab61ac220bca9aa6")[0].id +# $("#e0a1f2862cfa11ecab61ac220bca9aa6").hover(function(){ +# alert("-4-- :"+ $(this).text() + $("#e0a1f2862cfa11ecab61ac220bca9aa6").text() + $(this).attr("class") + $(this).attr("id")); +# }); + +# $("#550f63502b6611ecab61ac220bca9aa6")[0].id + +#$("#ec7abddd2dca11ecab61ac220bca9aa6").parents()[0] +# Pour obtenir le nodeid treeview a partir de l'eficasID +#$("#ec7abddd2dca11ecab61ac220bca9aa6").parent()[0].attributes['data-nodeid'].value diff --git a/Web/templates/available_catalogs.html b/Web/templates/available_catalogs.html index 506a73fb..09f058b5 100644 --- a/Web/templates/available_catalogs.html +++ b/Web/templates/available_catalogs.html @@ -12,108 +12,100 @@ + @@ -123,6 +115,7 @@ {% raw %} + +
@@ -211,7 +266,7 @@ function callService(serviceName, obj) { treeMessage(msgCssSelStr,"alert-success",message) ; }; - const url = "{{ url_for('appendChild') }}"; //WARN : jinja url_for évalué dynamiquent + const url = "{{ url_for('appendChild') }}"; //WARN : jinja url_for évalué dynamiquement const newurl = url.replace("appendChild", serviceName); //TODO : Trouver une meilleure solution ! return $.ajax({ type : "POST", @@ -225,35 +280,10 @@ function callService(serviceName, obj) { }; -// TODO : Il faudrait s'assurer que si une requête de ce type est envoyée au serveur -// on récupère bien l'evenement appendChild --> validation, promise... -// TODO : ?async? -// cf callService -// function callServiceOld(serviceName, obj, callBack) { -// const msgCssSelStr = '#tree1-messages'; -// const success = function(data, status) { -// message="Successfull "+serviceName+" call with status : " + status; -// treeMessage(msgCssSelStr,"alert-success",message) ; -// callBack(data); -// }; - -// const url = "{{ url_for('appendChild') }}"; //ATT : jinja url_for évalué dynamiquent -// const newurl = url.replace("appendChild", serviceName); //TODO : Trouver une meilleure solution ! -// $.ajax({ -// type : "POST", -// url : newurl, -// data : JSON.stringify(obj), -// contentType : "application/json; charset=utf-8", -// dataType : "json", -// success : success, -// failure : function(errMsg) { alert(errMsg); } -// }); -// }; - // APPELS EXPLICITES AU SERVER function clickOnRemove(treeCssSelStr, msgCssSelStr, key ) { 'use strict'; - const tree = $.ui.fancytree.getTree(treeCssSelStr); + const tree = $.ui.fancytree.getTree(treeCssSelStr); const _key = key; if ( key === undefined || key == "") { activeNode = tree.activeNode; @@ -310,7 +340,7 @@ function sendAppendChild( key, name, pos) { const checkCallBack = function(data) { // Tester data == NULL ! - let rId = data['id']; + let rId = data['id']; //TODO : Changer en code d'erreur if ( rId == 0 || rId == null ) { let message = "Unsuccessfull appendChild processing for command " + name + ". Service appendChild has returned an error ("+data.message+")"; treeMessage(msgCssSelStr,"alert-danger",message) ; @@ -331,9 +361,11 @@ function getParentCommandNode(node) { // utilsées dans les attributs des elements html on="clickOn('arg1','arg2',)" function clickOnCommand(treeCssSelStr, msgCssSelStr, cmdName, key ) { 'use strict'; - const tree = $.ui.fancytree.getTree(treeCssSelStr); //TODO : Une fonction pour récupérer le tree en paramètre soit par css ou objet + const tree = $.ui.fancytree.getTree(treeCssSelStr); //TODO : Une fonction pour récupérer le tree en paramètre soit par css ou objet const rootDatasetNode = tree.rootNode.children[0]; - let fromNode = null; + let fromNode = null; + let pos; + if ( key !== undefined && key != "") { fromNode = tree.getNodeByKey(key); } else { @@ -342,7 +374,10 @@ function clickOnCommand(treeCssSelStr, msgCssSelStr, cmdName, key ) { if ( fromNode == null) { pos=0; } else { - parentList = fromNode.getParentList(); // default : (false,false)==(rootNode exclus, not self) + let activeCommandKey = ""; + let commandList = null; + let index = 0; + let parentList = fromNode.getParentList(); // default : (false,false)==(rootNode exclus, not self) console.log("clickOnCommand : parentList "+parentList) if ( parentList.length == 0 ) { //If the current dataset filename node is activated console.log("clickOnCommand : index is forced = 0"); @@ -419,7 +454,7 @@ function sendUpdateSimp( node, eltNameWithValue) { console.log('wValue : '+ node.data.wValue); console.log('validite : '+validite); } else { - // Gérer le input pour laisser le focus et passer en rouge + // TODO: Gérer le input pour laisser le focus et passer en rouge ? let message = "Unsuccessfull SIMP processing for |" + node.getPath() + "|, value |"+value+"| has not been accepted ("+rMessage+")"; treeMessage(_msgCssSelStr,"alert-warning",message); }; @@ -433,6 +468,63 @@ function sendUpdateSimp( node, eltNameWithValue) { return callService('updateSimp', {id: node.key, value:value } ).done( (data)=>checkCallBack(data) ); +}; + +function sendNewDataset( catalogName, datasetName) { + 'use strict'; + + const _msgCssSelStr = '#tree1-messages'; + const _treeCssSelStr = '#tree1'; + const tree = $.ui.fancytree.getTree(_treeCssSelStr); //TODO : Une fonction pour récupérer le tree en paramètre soit par css ou objet + + //let $input=$(node.tr).find('input'); + // let $input=$(node.tr).find(eltNameWithValue); + // let value=$input.val(); + + let checkCallBack = function(data) { + // Tester data == NULL ! + const source = data.source; + const commands = data.commands; + const titre = data.titre; + const rMessage = data.message + + // TODO: détacher la constuction des options fancytree de #tree1 ! + //tree.destroy(); + let message = "New Dataset has been loaded ("+rMessage+")"; + tree.clear(); //Remove all the nodes but keep the configuration + tree.setOption('source', source); + tree.reload().done( ()=>treeMessage(_msgCssSelStr,"alert-success",message)); + //TODO : Gérer les commandes + //TODO : Gérer le titre/code + + //node.fromDict() + //source=JSON.parse(getTree1()) + // if ( changeIsAccepted ) { + // // Il faudrait gérer les représentations des types pour activer cet assert (ex: string vs int) + // // or on laisse le kernel eficas vérifier des strings. + // // $.ui.fancytree.assert(value == wValue); + // // node.data.wValue = wValue + // // node.data.validite = validite + // let message = "New Dataset "+node.title+" value to "+value+" has been accepted ("+rMessage+")"; + // treeMessage(_msgCssSelStr,"alert-success",message); + // //node.data = data.source ?? A priori, il est inutile d'essayer de remplacer la source complète du noeud + // console.log('wValue : '+ node.data.wValue); + // console.log('validite : '+validite); + // } else { + // // TODO: Gérer le input pour laisser le focus et passer en rouge ? + // let message = "Unsuccessfull SIMP processing for |" + node.getPath() + "|, value |"+value+"| has not been accepted ("+rMessage+")"; + // treeMessage(_msgCssSelStr,"alert-warning",message); + // }; + // //alert("sendNewDataset-2"); + // node.render(true,false); //force rendering the node (not parents nor descendants) + // if (eltNameWithValue != 'select') node.render(true,false); //force rendering the node (not parents nor descendants) + //node.renderStatus(); //CSS element updates + }; + + //alert("sendNewDataset-1"); + return callService('newDataset', { catalogName:catalogName, datasetName:datasetName } ).done( (data)=>checkCallBack(data) ); + + }; @@ -721,7 +813,10 @@ $(function(){ const statut = node.data.statut; const cmdName = node.data.nomCommande; // undefined if classeAccas != 'MCFACT' const repeatable = node.data.repetable; // ?? undefined if classeAccas != 'MCFACT' ?? - const into = node.data.into; // only used for SIMP + const into = node.data.into; // only used for SIMP //TODO: BUG: un into reel xx.0 devient ici un entier chaîne + // eficas doit envoyer tjrs des chaînes + console.log("into :"+into); //All JavaScript numbers are stored as decimal numbers (floating point). + //Numbers can be written with, or without decimals: const infoOptionnels = node.data.infoOptionnels; const key = node.key; const name = node.title; @@ -796,12 +891,11 @@ $(function(){ //let selectFunction = "alert(\"SELECT EVENT\");setTimeout(clickOnSelect(\"#tree1\", \"#tree1-messages\", \""+key+"\", \"select\"),50000)"; // console.log("----AVANT html :------"+$tdList.eq(3).html()); // console.log($tdList.eq(3).find("select").length); - $tdList3 let html= "
"+ - "
" + - ""+ - "
"+ + "
" + + ""+ + "
"+ "
"; $tdList3 .html(html) diff --git a/Web/templates/file_management.html b/Web/templates/file_management.html index bab47a94..3e11fdb9 100644 --- a/Web/templates/file_management.html +++ b/Web/templates/file_management.html @@ -12,9 +12,9 @@
+