From 2865f916e269ef6fb1f49432c88ce9581983ffcd Mon Sep 17 00:00:00 2001 From: Eric Fayolle Date: Tue, 5 Apr 2022 15:08:23 +0200 Subject: [PATCH] =?utf8?q?Un=20peu=20de=20m=C3=A9nage?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- WebTest/cata_Vallee.py | 104 ++++++ testFlask/cata_Vallee.py | 105 +----- testFlask/mdm.py | 474 ++++++++++++--------------- testFlask/prefs_Morgane.py | 40 +++ testFlask/templates/base.html | 9 + testFlask/templates/commandes_2.html | 123 +++++-- 6 files changed, 457 insertions(+), 398 deletions(-) create mode 100644 WebTest/cata_Vallee.py mode change 100644 => 120000 testFlask/cata_Vallee.py create mode 100644 testFlask/prefs_Morgane.py diff --git a/WebTest/cata_Vallee.py b/WebTest/cata_Vallee.py new file mode 100644 index 00000000..988822de --- /dev/null +++ b/WebTest/cata_Vallee.py @@ -0,0 +1,104 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2008-2018 EDF R&D +# +# This file is part of SALOME ADAO module +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +import os +from Accas import OPER, BLOC, FACT, SIMP, ASSD, JDC_CATA, VerifTypeTuple, Matrice, UserASSD +from Extensions.i18n import tr +import types +monFichier = os.path.abspath(__file__) + +JdC = JDC_CATA( + code='Morgane', + fr = "Modèle physique d'une vallée", +) +VERSION_CATALOGUE = 'V_0' + +class vallee(ASSD) : pass +class usine(UserASSD) : pass +class reservoir(UserASSD) : pass + +unitesChute=['hm3','m3'] + +Vallee=OPER(nom="Vallee", sd_prod=vallee, + fr="Elément défini pour éventuellement contenir la définition des vallées de manière autonome. Les contraintes sont définies au niveau de l'élément et doivent donc être répétées si le type est utilisé ailleurs", + Reservoirs=FACT(statut='o', + Reservoir = FACT ( statut ='o', max='**', + NomReservoir = SIMP(statut='o', typ=(reservoir,'createObject'),), + TypeReservoir = SIMP(statut='o', typ= 'TXM', into = ['Lac', 'Eclusee',]), + Volume = SIMP(statut='o', typ= 'R', defaut=0, val_min=0,), + Surface = SIMP(statut='o', typ= 'R'), + CotesVolume = FACT(statut='f', + fr="Si, quelque part dans l'étude (usine ou réservoir), il y a des cotes (ie on travaille en mètres), il faut les cotes volumes car le coeur de calcul travaille en volume", + CoteVolume = FACT (statut='o', max='**', + Cote = SIMP(statut='o', typ='R', defaut=0, val_min=0), + Volume = SIMP(statut='o', typ='R', defaut=0, val_min=0), + Surface = SIMP(statut='o', typ='R', defaut=0, val_min=0), + ), + ), + ), + ), # Reservoirs + + Usines = FACT(statut ='o', + fr="Attention, l'ordre des usines a une importance", + Usine = FACT ( statut ='o', max='**', + fr="Les usines sont des turbines, des pompes ou des non énergétiques. Leur description dépend de ce type", + NomDUsine = SIMP(statut='o', typ=(usine,'createObject'),), + TypeDUsine = SIMP(statut='o', typ= 'TXM', into = ['Turbine', 'Pompe', 'NonEnergetique']), + b_TypeDUsine_Turbine = BLOC( condition = 'TypeDUsine == "Turbine"', + CaracteristiquesTurbine=FACT( statut='o', + fr="Caractéristiques spécifiques aux turbines", DebitMaxPhysique = SIMP(typ='I', statut='o',defaut=100000, val_min=0), + TypeDeDeversement = SIMP(typ= 'TXM', into = ['CapaciteFixe', 'NonAutorise', 'DebitMaxGestion']), + b_Turbine_CapaciteFixe = BLOC( condition = 'TypeDeDeversement == "CapaciteFixe"', + Capacite = SIMP(typ='I', defaut=0, val_min=0), + ), + HauteurChute = SIMP(typ='R', defaut=0, statut='o', val_min=0), + Puissance = SIMP(typ='R', defaut=0,statut='o', val_min=0), + Debit = SIMP(typ='R', defaut=0, statut='o', val_min=0), + BandePrimaire = SIMP(typ='R', defaut=0 , statut='o', val_min=0), + BandeSecondaire = SIMP(typ='R', defaut=0, statut='o', val_min=0), + ), + ), # fin Turbine + b_TypeDUsine_Pompe = BLOC( condition = 'TypeDUsine == "Pompe"', + fr="Caractéristiques spécifiques aux pompes", + CaracteristiquesPompe=FACT( statut='o', + DebitMaxPhysique = SIMP(typ='I', statut='o',defaut=-100000, val_max=0), + HauteurChute = SIMP(typ='R', defaut=0, statut='o', val_min=0), + Puissance = SIMP(typ='R', defaut=0, statut='o', val_min=0), + Debit = SIMP(typ='R', defaut=0, statut='o', val_min=0), + ), + ), # fin Pompe + b_TypeDUsine_NonEnergetique = BLOC( condition = 'TypeDUsine == "NonEnergetique"', + CaracteristiquesNonEnergetique=FACT( statut='o', + DebitMaxPhysique = SIMP(typ='I', statut='o', defaut=100000, val_min=0), + ), + ), + b_TypeDUsine = BLOC( condition = 'TypeDUsine != None', + DelaiAval = SIMP(typ='I', statut='o',defaut=0, val_min=0), + UniteHauteurChute = SIMP(typ="TXM", statut='o', into=unitesChute, defaut="hm3"), + Interpolation = SIMP(typ="TXM", statut='o', into=["EnVolume", "EnCote"], defaut="EnCote"), + ReservoirAmont = SIMP(typ=reservoir,statut='o'), + b_DelaiAval_NonNul = BLOC( condition = "DelaiAval != 0", + ReservoirAval = SIMP(typ=reservoir,statut='o'), + ), + ), # fin bloc commun + ), # fin Usine + + ), # Usines +) diff --git a/testFlask/cata_Vallee.py b/testFlask/cata_Vallee.py deleted file mode 100644 index 988822de..00000000 --- a/testFlask/cata_Vallee.py +++ /dev/null @@ -1,104 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright (C) 2008-2018 EDF R&D -# -# This file is part of SALOME ADAO module -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -# -# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -import os -from Accas import OPER, BLOC, FACT, SIMP, ASSD, JDC_CATA, VerifTypeTuple, Matrice, UserASSD -from Extensions.i18n import tr -import types -monFichier = os.path.abspath(__file__) - -JdC = JDC_CATA( - code='Morgane', - fr = "Modèle physique d'une vallée", -) -VERSION_CATALOGUE = 'V_0' - -class vallee(ASSD) : pass -class usine(UserASSD) : pass -class reservoir(UserASSD) : pass - -unitesChute=['hm3','m3'] - -Vallee=OPER(nom="Vallee", sd_prod=vallee, - fr="Elément défini pour éventuellement contenir la définition des vallées de manière autonome. Les contraintes sont définies au niveau de l'élément et doivent donc être répétées si le type est utilisé ailleurs", - Reservoirs=FACT(statut='o', - Reservoir = FACT ( statut ='o', max='**', - NomReservoir = SIMP(statut='o', typ=(reservoir,'createObject'),), - TypeReservoir = SIMP(statut='o', typ= 'TXM', into = ['Lac', 'Eclusee',]), - Volume = SIMP(statut='o', typ= 'R', defaut=0, val_min=0,), - Surface = SIMP(statut='o', typ= 'R'), - CotesVolume = FACT(statut='f', - fr="Si, quelque part dans l'étude (usine ou réservoir), il y a des cotes (ie on travaille en mètres), il faut les cotes volumes car le coeur de calcul travaille en volume", - CoteVolume = FACT (statut='o', max='**', - Cote = SIMP(statut='o', typ='R', defaut=0, val_min=0), - Volume = SIMP(statut='o', typ='R', defaut=0, val_min=0), - Surface = SIMP(statut='o', typ='R', defaut=0, val_min=0), - ), - ), - ), - ), # Reservoirs - - Usines = FACT(statut ='o', - fr="Attention, l'ordre des usines a une importance", - Usine = FACT ( statut ='o', max='**', - fr="Les usines sont des turbines, des pompes ou des non énergétiques. Leur description dépend de ce type", - NomDUsine = SIMP(statut='o', typ=(usine,'createObject'),), - TypeDUsine = SIMP(statut='o', typ= 'TXM', into = ['Turbine', 'Pompe', 'NonEnergetique']), - b_TypeDUsine_Turbine = BLOC( condition = 'TypeDUsine == "Turbine"', - CaracteristiquesTurbine=FACT( statut='o', - fr="Caractéristiques spécifiques aux turbines", DebitMaxPhysique = SIMP(typ='I', statut='o',defaut=100000, val_min=0), - TypeDeDeversement = SIMP(typ= 'TXM', into = ['CapaciteFixe', 'NonAutorise', 'DebitMaxGestion']), - b_Turbine_CapaciteFixe = BLOC( condition = 'TypeDeDeversement == "CapaciteFixe"', - Capacite = SIMP(typ='I', defaut=0, val_min=0), - ), - HauteurChute = SIMP(typ='R', defaut=0, statut='o', val_min=0), - Puissance = SIMP(typ='R', defaut=0,statut='o', val_min=0), - Debit = SIMP(typ='R', defaut=0, statut='o', val_min=0), - BandePrimaire = SIMP(typ='R', defaut=0 , statut='o', val_min=0), - BandeSecondaire = SIMP(typ='R', defaut=0, statut='o', val_min=0), - ), - ), # fin Turbine - b_TypeDUsine_Pompe = BLOC( condition = 'TypeDUsine == "Pompe"', - fr="Caractéristiques spécifiques aux pompes", - CaracteristiquesPompe=FACT( statut='o', - DebitMaxPhysique = SIMP(typ='I', statut='o',defaut=-100000, val_max=0), - HauteurChute = SIMP(typ='R', defaut=0, statut='o', val_min=0), - Puissance = SIMP(typ='R', defaut=0, statut='o', val_min=0), - Debit = SIMP(typ='R', defaut=0, statut='o', val_min=0), - ), - ), # fin Pompe - b_TypeDUsine_NonEnergetique = BLOC( condition = 'TypeDUsine == "NonEnergetique"', - CaracteristiquesNonEnergetique=FACT( statut='o', - DebitMaxPhysique = SIMP(typ='I', statut='o', defaut=100000, val_min=0), - ), - ), - b_TypeDUsine = BLOC( condition = 'TypeDUsine != None', - DelaiAval = SIMP(typ='I', statut='o',defaut=0, val_min=0), - UniteHauteurChute = SIMP(typ="TXM", statut='o', into=unitesChute, defaut="hm3"), - Interpolation = SIMP(typ="TXM", statut='o', into=["EnVolume", "EnCote"], defaut="EnCote"), - ReservoirAmont = SIMP(typ=reservoir,statut='o'), - b_DelaiAval_NonNul = BLOC( condition = "DelaiAval != 0", - ReservoirAval = SIMP(typ=reservoir,statut='o'), - ), - ), # fin bloc commun - ), # fin Usine - - ), # Usines -) diff --git a/testFlask/cata_Vallee.py b/testFlask/cata_Vallee.py new file mode 120000 index 00000000..f0fc7c6c --- /dev/null +++ b/testFlask/cata_Vallee.py @@ -0,0 +1 @@ +../WebTest/cata_Vallee.py \ No newline at end of file diff --git a/testFlask/mdm.py b/testFlask/mdm.py index b51926fa..73a58e24 100755 --- a/testFlask/mdm.py +++ b/testFlask/mdm.py @@ -4,6 +4,7 @@ import sys sys.path.append('/home/eric/FLASK/eficas.eecj.git/testFlask') #TODO : supprimer from connectEficas import accasConnecteur +#code='Morgane' code='Essai' from flask import Flask, request, render_template, url_for, jsonify, make_response, session, g, Response @@ -46,155 +47,6 @@ app.config['MAX_CONTENT_LENGTH'] = 50 * 1024 * 1024 ALLOWED_EXTENSIONS = set(['py','comm','txt', 'gif', 'png', 'jpg', 'jpeg', 'bmp', 'rar', 'zip', '7zip', 'doc', 'docx']) IGNORED_FILES = set(['.gitignore']) -#TODO: -#from fileManagement import * - -def allowed_file(filename): - return '.' in filename and \ - filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS - - -def gen_file_name(filename): - """ - If file was exist already, rename it and return a new name - """ - - i = 1 - while os.path.exists(os.path.join(app.config['UPLOAD_FOLDER'], filename)): - name, extension = os.path.splitext(filename) - filename = '%s_%s%s' % (name, str(i), extension) - i += 1 - - return filename - - -def create_thumbnail(image): - try: - base_width = 80 - img = Image.open(os.path.join(app.config['UPLOAD_FOLDER'], image)) - w_percent = (base_width / float(img.size[0])) - h_size = int((float(img.size[1]) * float(w_percent))) - img = img.resize((base_width, h_size), PIL.Image.ANTIALIAS) - img.save(os.path.join(app.config['THUMBNAIL_FOLDER'], image)) - - return True - - except: - print(traceback.format_exc()) - return False - - -@app.route("/upload", methods=['GET', 'POST']) -def upload(): - if request.method == 'POST': - files = request.files['file'] - - if files: - filename = secure_filename(files.filename) - filename = gen_file_name(filename) - mime_type = files.content_type - - if not allowed_file(files.filename): - result = uploadfile(name=filename, type=mime_type, size=0, not_allowed_msg="File type not allowed") - - else: - # save file to disk - uploaded_file_path = os.path.join(app.config['UPLOAD_FOLDER'], filename) - files.save(uploaded_file_path) - - # create thumbnail after saving - if mime_type.startswith('image'): - create_thumbnail(filename) - - # get file size after saving - size = os.path.getsize(uploaded_file_path) - - # return json for js call back - result = uploadfile(name=filename, type=mime_type, size=size) - - return simplejson.dumps({"files": [result.get_file()]}) - - if request.method == 'GET': - # get all file in ./data directory - files = [f for f in os.listdir(app.config['UPLOAD_FOLDER']) if os.path.isfile(os.path.join(app.config['UPLOAD_FOLDER'],f)) and f not in IGNORED_FILES ] - - file_display = [] - - for f in files: - size = os.path.getsize(os.path.join(app.config['UPLOAD_FOLDER'], f)) - file_saved = uploadfile(name=f, size=size) - file_display.append(file_saved.get_file()) - - return simplejson.dumps({"files": file_display}) - - return redirect(url_for('index')) - - - -@app.route("/delete/", methods=['DELETE']) -def delete(filename): - file_path = os.path.join(app.config['UPLOAD_FOLDER'], filename) - file_thumb_path = os.path.join(app.config['THUMBNAIL_FOLDER'], filename) - - if os.path.exists(file_path): - try: - os.remove(file_path) - - if os.path.exists(file_thumb_path): - os.remove(file_thumb_path) - - return simplejson.dumps({filename: 'True'}) - except: - return simplejson.dumps({filename: 'False'}) - - -# serve static files -@app.route("/thumbnail/", methods=['GET']) -def get_thumbnail(filename): - return send_from_directory(app.config['THUMBNAIL_FOLDER'], filename=filename) - - -@app.route("/data/", methods=['GET']) -def get_file(filename): - return send_from_directory(os.path.join(app.config['UPLOAD_FOLDER']), filename=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 -# uploadRequest=json.dumps([req],indent=4); #TODO : remove indent if not DEBUG -# pprint(uploadRequest); - -# return make_response(json.dumps( {'source':node, 'changeIsAccepted' : changeDone, 'message': message} )) -# # Return a string along with an HTTP status code -# # return "JSON received!", 200 -# else: -# print(request) -# files = request.files['files'] -# if files: -# result=catalogs.save(files) -# return make_response(json.dumps( {"files": ["coucou"]} )) -# # if request.method == 'POST' and 'files' in request.files: - - -# # 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) - -# For example, you may want to override how request parameters are handled to preserve their order: -# from flask import Flask, Request -# from werkzeug.datastructures import ImmutableOrderedMultiDict -# class MyRequest(Request): -# """Request subclass to override request parameter storage""" -# parameter_storage_class = ImmutableOrderedMultiDict -# class MyFlask(Flask): -# """Flask subclass using the custom request class""" -# request_class = MyReq ### Server Side Event config app.config["REDIS_URL"] = "redis://localhost" @@ -254,119 +106,6 @@ def afficheAlerte(titre, message): # sse.publish({"message": "Hello!"}, type='update') # return "Message sent!" -@app.route('/') -def index(): - tree4treeview = """ [ - { - "text": "Parent 1", - "nodes": [ - { - "text": "Child 1.1", - "nodes": [ - { - "text": "Grandchild 1.1" - }, - { - "text": "Grandchild 1.2" - } - ] - }, - { - "text": "Child 1.2", - "nodes": [ - { - "text": "Grandchild 1.1" - }, - { - "text": "Grandchild 1.2" - } - ] - }, - { - "text": "Child 2" - } - ] - }, - { - "text": "Parent 2" - }, - { - "text": "Parent 3", - "nodes": [{"text":"3.5"}] - }, - { - "txt": "Parent 4" - }, - { - "text": "Parent 5" - } - ] - """.replace('\n','') - - treeB = """ [ - { - "nodes": [ - { - "text": "Child 1.1", - "nodes": [ - { - "text": "Grandchild 1.1" - }, - { - "text": "Grandchild 1.2" - } - ] - } - ] - } - ] - """.replace('\n','') - - - tree4Fancy = """ [ - {"title": "Node 1", "key": "1"}, - {"title": "Folder 2", "key": "2", "folder": true, "children": [ - {"title": "Node 2.1", "key": "3"}, - {"title": "Node 2.2", "key": "4"} - ]} - ] - """.replace('\n','') - - print("treeB : %s"%treeB); - - dictC={'nodes': [{'text': 'Child 1.1', 'nodes': [{'text': 'Grandchild 1.1'}, {'text': 'Grandchild 1.2'}]}]} - treeC=[dictC] - - # print("mytree : %s"%mytree); - mcTraite={'MonProc2': {'s1': ('I', 2), 'F2': {'s2': ('I', 3), 'F3': {'s3': ('I', 4)}}}}; - - monConnecteur.litFichierComm('../WebTest/web_tres_simple_avec_2Fact.comm') - #monConnecteur.litFichierComm('../WebTest/edg_REP1300_FULL_PN.comm') - #myTreeDico=monConnecteur.getDicoObjetsCompletsPourTree(monConnecteur.monEditeur.tree.racine) - myFancyTreeDico=monConnecteur.getDicoForFancy(monConnecteur.monEditeur.tree.racine) - print (myFancyTreeDico) - - #myTreeJS=json.dumps([myTreeDico]) - myFancyTreeJS=json.dumps([myFancyTreeDico]) - myFancyTreeJS=json.dumps([myFancyTreeDico],indent=4) #TODO : remove indent if not DEBUG - - print("---- myFancyTreeDico ----") - pprint(myFancyTreeDico) - print("---- myFancyTreeJS ----") - pprint( myFancyTreeJS) - - return render_template('commandes_2.html', - titre=code, - listeCommandes = monConnecteur.getListeCommandes(), - # profondeur=4, - mcTraite={'MonProc2': {'s1': ('I', 2), 'F2': {'s2': ('I', 3), 'F3': {'s3': ('I', 4)}}}}, - mcTraiteJson=json.dumps(mcTraite), - tree=myFancyTreeJS, - # tree=tree4Fancy, - # tree=myTreeJS - # tree='['+myTreeJS+']' - ) - # etape = str(escape(request.args.get("etape", ""))) ## WebApp -> Eficas : # Pour SIMP : Ajoute, Supprime (MC facultatif), Change la valeur @@ -404,6 +143,32 @@ def updateSimp(): return "Request was not JSON", 400 #return make_response(jsonify({"message": "Request body must be JSON"}), 400) +@app.route("/updateSDName", methods=['POST']) +def updateSDName(): + # 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(req) + print(req['id']) + id=req['id'];value=req['value'] + # id, value = req.values() # Dangereux correspondance implicite + value = str(value) #On peut écrire Pi + rId,message,changeDone = monConnecteur.updateSDName(id,value); + assert(rId==id) + #changeDone = True + print ("changeDone : ",changeDone) + + #return make_response(json.dumps( {'id':id , 'changeIsAccepted' : changeDone, 'message': message} )) + return make_response(json.dumps( {'changeIsAccepted' : changeDone, 'message': message} )) + # Return a string along with an HTTP status code + # return "JSON received!", 200 + 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("/removeNode", methods=['POST']) def removeNode(): @@ -446,6 +211,41 @@ def appendChild(): return "Request was not JSON", 400 #return make_response(jsonify({"message": "Request body must be JSON"}), 400) +@app.route('/') +def index(): + + # tree4Fancy = """ [ + # {"title": "Node 1", "key": "1"}, + # {"title": "Folder 2", "key": "2", "folder": true, "children": [ + # {"title": "Node 2.1", "key": "3"}, + # {"title": "Node 2.2", "key": "4"} + # ]} + # ] + # """.replace('\n','') + + + monConnecteur.litFichierComm('../WebTest/web_tres_simple_avec_2Fact.comm') + #monConnecteur.litFichierComm('../WebTest/edg_REP1300_FULL_PN.comm') + myFancyTreeDico=monConnecteur.getDicoForFancy(monConnecteur.monEditeur.tree.racine) + #print (myFancyTreeDico) + + #myFancyTreeJS=json.dumps([myFancyTreeDico]) + myFancyTreeJS=json.dumps([myFancyTreeDico],indent=4) #TODO : remove indent if not DEBUG + + print("---- myFancyTreeDico ----") + pprint(myFancyTreeDico) + print("---- myFancyTreeJS ----") + pprint( myFancyTreeJS) + + return render_template('commandes_2.html', + titre=code, + listeCommandes = monConnecteur.getListeCommandes(), + tree=myFancyTreeJS, + # tree=tree4Fancy, + ) + # etape = str(escape(request.args.get("etape", ""))) + + @app.route("/forward/", methods=['POST']) def move_forward(): @@ -484,6 +284,156 @@ def json_example(): return make_response(jsonify({"message": "Request body must be JSON"}), 400) +#TODO: +#from fileManagement import * + +def allowed_file(filename): + return '.' in filename and \ + filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS + + +def gen_file_name(filename): + """ + If file was exist already, rename it and return a new name + """ + + i = 1 + while os.path.exists(os.path.join(app.config['UPLOAD_FOLDER'], filename)): + name, extension = os.path.splitext(filename) + filename = '%s_%s%s' % (name, str(i), extension) + i += 1 + + return filename + + +def create_thumbnail(image): + try: + base_width = 80 + img = Image.open(os.path.join(app.config['UPLOAD_FOLDER'], image)) + w_percent = (base_width / float(img.size[0])) + h_size = int((float(img.size[1]) * float(w_percent))) + img = img.resize((base_width, h_size), PIL.Image.ANTIALIAS) + img.save(os.path.join(app.config['THUMBNAIL_FOLDER'], image)) + + return True + + except: + print(traceback.format_exc()) + return False + + +@app.route("/upload", methods=['GET', 'POST']) +def upload(): + if request.method == 'POST': + files = request.files['file'] + + if files: + filename = secure_filename(files.filename) + filename = gen_file_name(filename) + mime_type = files.content_type + + if not allowed_file(files.filename): + result = uploadfile(name=filename, type=mime_type, size=0, not_allowed_msg="File type not allowed") + + else: + # save file to disk + uploaded_file_path = os.path.join(app.config['UPLOAD_FOLDER'], filename) + files.save(uploaded_file_path) + + # create thumbnail after saving + if mime_type.startswith('image'): + create_thumbnail(filename) + + # get file size after saving + size = os.path.getsize(uploaded_file_path) + + # return json for js call back + result = uploadfile(name=filename, type=mime_type, size=size) + + return simplejson.dumps({"files": [result.get_file()]}) + + if request.method == 'GET': + # get all file in ./data directory + files = [f for f in os.listdir(app.config['UPLOAD_FOLDER']) if os.path.isfile(os.path.join(app.config['UPLOAD_FOLDER'],f)) and f not in IGNORED_FILES ] + + file_display = [] + + for f in files: + size = os.path.getsize(os.path.join(app.config['UPLOAD_FOLDER'], f)) + file_saved = uploadfile(name=f, size=size) + file_display.append(file_saved.get_file()) + + return simplejson.dumps({"files": file_display}) + + return redirect(url_for('index')) + + + +@app.route("/delete/", methods=['DELETE']) +def delete(filename): + file_path = os.path.join(app.config['UPLOAD_FOLDER'], filename) + file_thumb_path = os.path.join(app.config['THUMBNAIL_FOLDER'], filename) + + if os.path.exists(file_path): + try: + os.remove(file_path) + + if os.path.exists(file_thumb_path): + os.remove(file_thumb_path) + + return simplejson.dumps({filename: 'True'}) + except: + return simplejson.dumps({filename: 'False'}) + + +# serve static files +@app.route("/thumbnail/", methods=['GET']) +def get_thumbnail(filename): + return send_from_directory(app.config['THUMBNAIL_FOLDER'], filename=filename) + + +@app.route("/data/", methods=['GET']) +def get_file(filename): + return send_from_directory(os.path.join(app.config['UPLOAD_FOLDER']), filename=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 +# uploadRequest=json.dumps([req],indent=4); #TODO : remove indent if not DEBUG +# pprint(uploadRequest); + +# return make_response(json.dumps( {'source':node, 'changeIsAccepted' : changeDone, 'message': message} )) +# # Return a string along with an HTTP status code +# # return "JSON received!", 200 +# else: +# print(request) +# files = request.files['files'] +# if files: +# result=catalogs.save(files) +# return make_response(json.dumps( {"files": ["coucou"]} )) +# # if request.method == 'POST' and 'files' in request.files: + + +# # 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) + +# For example, you may want to override how request parameters are handled to preserve their order: +# from flask import Flask, Request +# from werkzeug.datastructures import ImmutableOrderedMultiDict +# class MyRequest(Request): +# """Request subclass to override request parameter storage""" +# parameter_storage_class = ImmutableOrderedMultiDict +# class MyFlask(Flask): +# """Flask subclass using the custom request class""" +# request_class = MyReq + if __name__ == "__main__": app.run(host="localhost", port=8321, debug=True) diff --git a/testFlask/prefs_Morgane.py b/testFlask/prefs_Morgane.py new file mode 100644 index 00000000..e09c7313 --- /dev/null +++ b/testFlask/prefs_Morgane.py @@ -0,0 +1,40 @@ +# -*- coding: utf-8 -*- +# maConfiguration MANAGEMENT OF EDF VERSION +# ====================================================================== +# COPYRIGHT (C) 2007-2021 EDF R&D +# THIS PROGRAM IS FREE SOFTWARE; YOU CAN REDISTRIBUTE IT AND/OR MODIFY +# IT UNDER THE TERMS OF THE GNU GENERAL PUBLIC LICENSE AS PUBLISHED BY +# THE FREE SOFTWARE FOUNDATION; EITHER VERSION 2 OF THE LICENSE, OR +# (AT YOUR OPTION) ANY LATER VERSION. +# +# THIS PROGRAM IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT +# WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF +# MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE GNU +# GENERAL PUBLIC LICENSE FOR MORE DETAILS. +# +# YOU SHOULD HAVE RECEIVED A COPY OF THE GNU GENERAL PUBLIC LICENSE +# ALONG WITH THIS PROGRAM; IF NOT, WRITE TO EDF R&D CODE_ASTER, +# 1 AVENUE DU GENERAL DE GAULLE, 92141 CLAMART CEDEX, FRANCE. +# +# +# ====================================================================== + +import os,sys +# repIni sert a localiser le fichier editeur.ini +# Obligatoire +repIni=os.path.dirname(os.path.abspath(__file__)) +INSTALLDIR=os.path.join(repIni,'..') +sys.path[:0]=[INSTALLDIR] + + +# lang indique la langue utilisee pour les chaines d'aide : fr ou ang +lang='ang' + +# Codage des strings qui accepte les accents (en remplacement de 'ascii') +encoding='iso-8859-1' +code = 'Morgane' + +# +catalogues=( + ('Morgane','Morgane',os.path.join(repIni,'cata_Vallee.py'),'python','python'), +) diff --git a/testFlask/templates/base.html b/testFlask/templates/base.html index 95b50ed8..0b362bbe 100644 --- a/testFlask/templates/base.html +++ b/testFlask/templates/base.html @@ -61,6 +61,15 @@ + + + + + + + + + diff --git a/testFlask/templates/commandes_2.html b/testFlask/templates/commandes_2.html index 1427f432..0a5b86f4 100644 --- a/testFlask/templates/commandes_2.html +++ b/testFlask/templates/commandes_2.html @@ -2,17 +2,18 @@ {% block content %} - - - - - - - - - + + + + + + + + + + - + @@ -101,7 +102,36 @@ + +
+ @@ -138,9 +168,10 @@ $(function () { }); }); -//$.ui.fancytree.debugLevel=4; // Set the fancyTree debug level +// if tree.options.debug is null: use global setting $.ui.fancytree.debugLevel) +// $.ui.fancytree.debugLevel=4; // Set the fancyTree debug level -//Créer une fonction pour désactiver toutes les classes d'alert pour positionner une seule +//Créer une fonction pour désactiver toutes les classes d'alert et pour en positionner une seule let treeMessage=function(msgCssSelStr,messageClass,message) { const messageClasses = new Set(["alert-success","alert-info","alert-warning","alert-danger"]); if (messageClasses.has(messageClass)) { @@ -154,6 +185,7 @@ let treeMessage=function(msgCssSelStr,messageClass,message) { $.ui.fancytree.info(message); // debugLevel >= 3 } else { console.debug(message); // debugLevel >= 4 + $.ui.fancytree.debug(message); // debugLevel >= 4 }; $(msgCssSelStr).text(message); } else { @@ -331,12 +363,12 @@ source.addEventListener('message', function(event) { treeMessage(_msgCssSelStr,"alert-danger",msgerror); return; }; - console.log("------------- message 2a: "+ node.data.title); - console.log("------------- message 2b: "+ info.title); + // console.log("------------- message 2a: "+ node.data.title); + // console.log("------------- message 2b: "+ info.title); // En fait, il faut que fancytree trie les propriétés qui l'interesse de celles qui vont dans data // Object.assign(node.data,info); //merge new options to node.data node.fromDict(info); - console.log("------------- message 2c: "+ node.data.title); + // console.log("------------- message 2c: "+ node.data.title); node.render(true,false); //force rendering the node (not parents nor descendants) //node.renderStatus(); //CSS element updates only }, false); @@ -420,10 +452,6 @@ function getTree1() { } - // function getTree2() { - // // Some logic to retrieve, or generate tree structure - // return {{ mcTraiteJson|tojson }}; - // } // $("#tree1").fancytree({ source: [ {title: "Node 1", key: "1000"},{title: "Folder 2", key: "2", folder: true, children: [ {title: "Node 2.1", key: "3000"},{title: "Node 2.2", key: "44"} ]} ], }) @@ -460,9 +488,10 @@ function iconRendering(event, data) { $(function(){ $("#tree1").fancytree({ //focusOnSelect:true, - debug:4, + debug:4, //if null: use global setting $.ui.fancytree.debugLevel + debuLevel:4, //if null: use global setting $.ui.fancytree.debugLevel //extensions: ["dnd5", "edit", "glyph", "wide", "table", "gridnav"], - extensions: [ "glyph", "table", "ariagrid"], + extensions: [ "glyph", "table", "ariagrid"], // https://github.com/mar10/fancytree/wiki/ExtTable //extensions: [ "glyph", "table", "gridnav"], checkbox: true, // Activate the use of checkboxes next to the nodes @@ -505,7 +534,7 @@ $(function(){ }, gridnav: { autofocusInput: true, // Focus first embedded input if node gets activated - handleCursorKeys: true // Allow UP/DOWN in inputs to move to prev/next node + handleCursorKeys: false // Allow UP/DOWN in inputs to move to prev/next node }, ariagrid: { cellFocus: 'allow' @@ -519,7 +548,7 @@ $(function(){ // data.result = {url: "ajax-sub2.json", debugDelay: 1000}; //} // renderStatusColumns: Pour le CSS - renderColumns: function(event, data) { + renderColumns: function(event, data) { //TODO : use createNode event to avaoid recreating content when rendering // Pour tester ds la console : //var tree=$.ui.fancytree.getTree("#tree1") @@ -532,12 +561,12 @@ $(function(){ const node = data.node, $tdList = $(node.tr).find(">td"); - const classeAccas = node.data.classeAccas; + const classeAccas = node.data.classeAccas; //TODO : Utiliser les types fancytree const validite = node.data.validite; const wValue = node.data.wValue; const statut = node.data.statut; - const cmdName = node.data.nomCommande; // undefined if classeAccas != 'MCFACT' - const repeatable = node.data.repetable; // ?? undefined if classeAccas != 'MCFACT' ?? + const cmdName = node.data.nomCommande; // undefined if classeAccas != 'MCFACT' + const repeatable = node.data.repetable; // ?? undefined if classeAccas != 'MCFACT' ?? const infoOptionnels = node.data.infoOptionnels; const key = node.key; const name = node.title; @@ -573,13 +602,30 @@ $(function(){ "
"+ "
" + ""+ + + wValue + //TODO:intosugg + "' value='"+wValue+"' required>"+ + // ""+ + "
"+ "
"+ - "" + "" ) .addClass(_attr) .find("input").css('color','black'); //TODO : A placer ds le CSS + // const container = document.getElementById('handsontable_'+key); + // const hot = new Handsontable(container, { + // data: handsontable_data0, + // colHeaders: false, + // height: 'auto', + // width: 'auto', + // minSpareRows: 1, + // licenseKey: 'non-commercial-and-evaluation' + // }); + // hot.render(); + // hot.addHook('afterCreateRow', (row, amount) => { + // console.log(`${amount} row(s) were created, starting at index ${row}`); + // }); }; // Not classeAccas == "MCSIMP" @@ -676,7 +722,7 @@ $(function(){ let buildOptionalTreeSrc=function(node) { if ( node == null ) return []; - let parentList = node.getParentList(false,true); // default : (false,false)==(rootNode exclus, not self) + let parentList = node.getParentList(false,hasOpt(node)); // default : (false,false)==(rootNode exclus, not self) if ( parentList.length > 0 ) { parentList=parentList.slice(1);}; // The first node is the current dataset name node // La construction des optionals en suivant les parents fonctionnent car les SIMP ne portent pas les optionnals // [ {title: "Node 1"}, {title: "Folder 2", children: [ {title: "Node 2.1"}, {title: "Node 2.2"} ]} ] @@ -750,6 +796,7 @@ $(function(){ // }, defaultGridAction: function( event, data ) { //(used by ext-aria) The user hit enter on the active row or cell. + //return true; const node = data.node // var rValue,rValidite,rChangeIsAccepted const _msgCssSelStr='#tree1-messages'; //TODO: A déplacer @@ -763,7 +810,6 @@ $(function(){ // Return false to prevent default // data.activeTd contains the currently active element or null // data.colIdx contains the 0-based column index or -1 - // console.log("event.type, data :"+event.type+" , "+data); if( !data.activeTd ) { alert( "Custom default action for row: " + data.node.title ); // we don't return false, so default action is applied: @@ -781,7 +827,7 @@ $(function(){ //node.fromDict() //source=JSON.parse(getTree1()) if ( changeIsAccepted ) { - // $.ui.fancytree.assert(value == wValue); il faut gérer les représentations des types pour activer cet assert + // $.ui.fancytree.assert(value == wValue); il faut gérer les représentations des types pour activer cet assert (ex: string vs int) node.data.wValue = wValue node.data.validite = validite treeMessage(_msgCssSelStr,"alert-success","Changing SIMP "+node.title+" value to "+value+" has been accepted."); @@ -843,6 +889,15 @@ $(function(){ keydown: function(event, data) { console.log("event.type, data :"+event.type+" , "+data); }, + // renderColumns: function(event, data) { + // console.log("event.type, data :"+event.type+" , "+data); + // }, + renderStatusColumns: function(event, data) { + console.log("event.type, data :"+event.type+" , "+data); + }, + renderNode: function(event, data) { + console.log("event.type, data :"+event.type+" , "+data); + }, }); }); @@ -908,3 +963,7 @@ $(function(){ // optTree=$optTree.fancytree() // #var optTree=$.ui.fancytree.getTree("#bebe") // optTree.expandAll() + +//TRICKS : +// Tester si un objet existe : +// if (typeof myObj !== "undefined" && myObj !== null) -- 2.39.2