]> SALOME platform Git repositories - tools/eficas.git/commitdiff
Salome HOME
Première version avec gestio des fichiers
authorEric Fayolle <eric.fayolle@edf.fr>
Thu, 3 Feb 2022 14:22:36 +0000 (15:22 +0100)
committerEric Fayolle <eric.fayolle@edf.fr>
Thu, 3 Feb 2022 14:22:36 +0000 (15:22 +0100)
testFlask/lib/__init__.py [new file with mode: 0644]
testFlask/lib/upload_file.py [new file with mode: 0644]
testFlask/mdm.py
testFlask/static/jQuery-File-Upload [new submodule]
testFlask/templates/base.html
testFlask/templates/commandes_2.html
testFlask/templates/commands_menu.html
testFlask/templates/file_management.html [new file with mode: 0644]
testFlask/templates/file_management_menu.html [new file with mode: 0644]
testFlask/templates/main_menu.html [new file with mode: 0644]

diff --git a/testFlask/lib/__init__.py b/testFlask/lib/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/testFlask/lib/upload_file.py b/testFlask/lib/upload_file.py
new file mode 100644 (file)
index 0000000..e768b8d
--- /dev/null
@@ -0,0 +1,67 @@
+import os
+
+class uploadfile():
+    def __init__(self, name, type=None, size=None, not_allowed_msg=''):
+        self.name = name
+        self.type = type
+        self.size = size
+        self.not_allowed_msg = not_allowed_msg
+        self.url = "data/%s" % name
+        self.thumbnail_url = "thumbnail/%s" % name
+        self.delete_url = "delete/%s" % name
+        self.delete_type = "DELETE"
+
+
+    def is_image(self):
+        fileName, fileExtension = os.path.splitext(self.name.lower())
+
+        if fileExtension in ['.jpg', '.png', '.jpeg', '.bmp']:
+            return True
+
+        return False
+
+
+    def get_file(self):
+        if self.type != None:
+            # POST an image
+            if self.type.startswith('image'):
+                return {"name": self.name,
+                        "type": self.type,
+                        "size": self.size, 
+                        "url": self.url, 
+                        "thumbnailUrl": self.thumbnail_url,
+                        "deleteUrl": self.delete_url, 
+                        "deleteType": self.delete_type,}
+            
+            # POST an normal file
+            elif self.not_allowed_msg == '':
+                return {"name": self.name,
+                        "type": self.type,
+                        "size": self.size, 
+                        "url": self.url, 
+                        "deleteUrl": self.delete_url, 
+                        "deleteType": self.delete_type,}
+
+            # File type is not allowed
+            else:
+                return {"error": self.not_allowed_msg,
+                        "name": self.name,
+                        "type": self.type,
+                        "size": self.size,}
+
+        # GET image from disk
+        elif self.is_image():
+            return {"name": self.name,
+                    "size": self.size, 
+                    "url": self.url, 
+                    "thumbnailUrl": self.thumbnail_url,
+                    "deleteUrl": self.delete_url, 
+                    "deleteType": self.delete_type,}
+        
+        # GET normal file from disk
+        else:
+            return {"name": self.name,
+                    "size": self.size, 
+                    "url": self.url, 
+                    "deleteUrl": self.delete_url, 
+                    "deleteType": self.delete_type,}
index 236ba8637e8a14bd914552c1552876e535522cd8..5fd67d99583af96630d5c9e9f51dd7cb3213344c 100755 (executable)
@@ -7,36 +7,181 @@ from connectEficas import accasConnecteur
 code='Essai'
 
 from flask import Flask, request, render_template, url_for, jsonify, make_response, session, g, Response
-# from flask import Flask, request, render_template, url_for, json, jsonify
+
+# File management
+from flask import redirect, send_from_directory
+from werkzeug.utils  import secure_filename
+from lib.upload_file import uploadfile
+import PIL
+from PIL import Image
+import simplejson
+import traceback
+
+# from flask import ?? json, jsonify ??
 import json
 import os
 from   pprint      import pprint
-#from   forms       import BasicForm
+#from   forms       import BasicForm  #Essais WtForms
 from   collections import OrderedDict
 from   markupsafe  import escape
 
+# Flask management of Server Side Event
 from flask_sse import sse
-from flask_uploads import UploadSet, configure_uploads, IMAGES 
+from flask_uploads import UploadSet, configure_uploads, IMAGES 
 
 app = Flask(__name__)
 
-CATALOGS_EXT=("py",)
-catalogs = UploadSet("catalogs",CATALOGS_EXT)
-app.config["UPLOADED_CATALOGS_DEST"] = "data/catalogs"
-app.config["SECRET_KEY"]             = os.urandom(24)
+# CATALOGS_EXT=("py","jpg") #TODO : supprimer jpg pour test
+# catalogs = UploadSet("catalogs",CATALOGS_EXT)
+# app.config["UPLOADED_CATALOGS_DEST"] = "data/catalogs"
+# app.config["SECRET_KEY"]             = os.urandom(24)
+
+# configure_uploads(app, catalogs)
+
+app.config['SECRET_KEY']         = 'hard to guess string'
+app.config['UPLOAD_FOLDER']      = 'data/'
+app.config['THUMBNAIL_FOLDER']   = 'data/thumbnail/'
+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'])
+
+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
 
 
-configure_uploads(app, catalogs)
+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))
 
-@app.route("/upload", methods=['POST'])
+        return True
+
+    except:
+        print(traceback.format_exc())
+        return False
+
+
+@app.route("/upload", methods=['GET', 'POST'])
 def upload():
-    if request.method == 'POST' and 'catalogFile' in request.files:
-        catalogs.save(request.files['catalogFile'])
-        # flash("Catalog saved successfully.")
-    #     return render_template('upload.html')
-    # return render_template('upload.html')
-    return "upload returns", 200
+    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/<string:filename>", 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/<string:filename>", methods=['GET'])
+def get_thumbnail(filename):
+    return send_from_directory(app.config['THUMBNAIL_FOLDER'], filename=filename)
+
+
+@app.route("/data/<string:filename>", 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
@@ -48,6 +193,13 @@ def upload():
 #     """Flask subclass using the custom request class"""
 #     request_class = MyReq
 
+### Server Side Event config
+app.config["REDIS_URL"] = "redis://localhost"
+#app.config["REDIS_URL"] = "redis://:password@localhost"
+#TODO: personaliser l'url en fonction de la session utilisateur
+app.register_blueprint(sse, url_prefix='/stream')
+
+### Eficas Connector
 def createConnecteur(app):
     monConnecteur=accasConnecteur(code, langue='ang',appWeb=app)
     return monConnecteur
@@ -55,12 +207,6 @@ def createConnecteur(app):
 monConnecteur=createConnecteur(app)
 print (monConnecteur.getListeCommandes())
 
-#Server Side Event config
-app.config["REDIS_URL"] = "redis://localhost"
-#app.config["REDIS_URL"] = "redis://:password@localhost"
-#TODO: personaliser l'url en fonction de la session utilisateur
-app.register_blueprint(sse, url_prefix='/stream')
-
 def fromConnecteur(maFonction,*args,**kwargs):
   #print ('dans fromConnecteur: ', maFonction)
   fnct=globals()[maFonction]
diff --git a/testFlask/static/jQuery-File-Upload b/testFlask/static/jQuery-File-Upload
new file mode 160000 (submodule)
index 0000000..0e92a4d
--- /dev/null
@@ -0,0 +1 @@
+Subproject commit 0e92a4d4613d4ed5231ee0d8513519f2e04f99ba
index 8e116197d9c5cbfeab67e7503afdc6734ec34e67..58569be598df50183138e8c99865b264016c13c8 100644 (file)
@@ -1,6 +1,7 @@
 <!doctype html>
 <html lang="en" >
   <head>
+    {% block head %}
     <title>{% block title %} MDM {{titre}} {% endblock %}</title>
     <meta charset="utf-8">
 
     <script src="{{ url_for('static', filename='jquery.fancytree/dist/modules/jquery.fancytree.ariagrid.js') }}"></script>
     
     <link rel="stylesheet" href="{{ url_for('static', filename= 'css/style.css') }}">
+
+    <!-- CSS to style the file input field as button and adjust the Bootstrap progress bars -->
+    <link rel="stylesheet" href="{{ url_for('static', filename='jQuery-File-Upload/css/jquery.fileupload.css') }}">
+    <link rel="stylesheet" href="{{ url_for('static', filename='jQuery-File-Upload/css/jquery.fileupload-ui.css') }}">
+    <script src={{ url_for('static', filename='jQuery-File-Upload/js/jquery.iframe-transport.js')}}></script>
+    <script src={{ url_for('static', filename='jQuery-File-Upload/js/jquery.fileupload.js')}}></script>
     
     <meta name="description" content={{description}}>
     <!-- <link rel="shortcut icon" href="../images/favicon-32x32.png"> -->
@@ -87,7 +94,7 @@
     <!--   text-overflow: ellipsis; -->
     <!--   } -->
     <!-- </style> -->
-    
+    {% endblock head %}
   </head>
   
 <!-- .navbar.navbar-static-top + .navbar.navbar-static-top { -->
       #row-tree1-messages nav, #tree1-messages {
       margin-bottom: 0px;
       }
-
+      
+      #file_management {
+      z-index: 8500;
+      }
       
     </style>
 
-  <div class="container-fluid">
 
-    <div class="row" data-spy="affix" id="row-main_menu">
-      <nav class="navbar navbar-inverse flex-column flex-md-row">
-       
-       <div class="navbar-header">
-         <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#myNavbar">
-            <span class="icon-bar"></span>
-            <span class="icon-bar"></span>
-            <span class="icon-bar"></span>                        
-         </button>
-         <a class="navbar-brand" href="#">MDM/Eficas</a>
-       </div>
-
-       <div class="collapse navbar-collapse" id="myNavbar">
-       <ul class="nav navbar-nav">  
-         <!-- <\!-- Dropdown -\-> -->
-         <!-- <li class="nav-item dropdown"> -->
-         <!--   <a class="nav-link dropdown-toggle" href="#" id="navbardrop" data-toggle="dropdown"> -->
-          <!--     Dropdown link -->
-         <!--   </a> -->
-         <!--   <div class="dropdown-menu"> -->
-          <!--     <a class="dropdown-item" href="#">Link 1</a> -->
-          <!--     <a class="dropdown-item" href="#">Link 2</a> -->
-          <!--     <a class="dropdown-item" href="#">Link 3</a> -->
-         <!--   </div> -->
-         <!-- </li> -->
-         
-         <li class="dropdown">
-            <a class="nav-link dropdown-toggle" data-toggle="dropdown" href="#">File<span class="caret"></span></a>
-            <ul class="dropdown-menu">
-             <li class="dropdown-header">Server Side</li> 
-             <li class="dropdown-item">
-               <form method="POST" enctype="multipart/form-data" action="{{ url_for('upload') }}">
-                 <div class="form-group">
-                   <!-- <input type="file" style="position:relative;opacity:0;z-index:2;" name="Set_Catalog_name" -->
-                   <!--        id="Set_Catalog" onchange="$('button_Set_Catalog').value=value"></input> -->
-                   <!-- <input type="file" style="display:none;" name="Set_Catalog_name" id="Set_Catalog"></input> -->
-                   <!-- Essayer d'ajouter la classe navbar-btn -->
-                   <div class="input-group" >
-                     <!-- <span class="input-group-addon"><i class="glyphicon glyphicon-user"></i></span> -->
-                     <input type="file" class="form-control btn btn-primary" name="catalogFile"
-                            id="button_Set_Catalog">Set Catalog</input>
-                     <button type="submit">Submit</button>
-                     <!-- <button type="file" class="filestyle form-control btn btn-primary" name="toto" -->
-                     <!--        id="button_Set_Catalog">Set Catalog</button> -->
-                   </div>
-                   <!-- <div class="input-group-btn"> -->
-                   <!--   <button class="btn btn-default" type="submit">Set the current catalog</button> -->
-                   <!-- </div> -->
-                 </div> <!-- form-group -->
-                 <!-- </form> -->
-                 <!-- <form action=""> -->
-                 <!--  <div class="form-group"> -->
-                 <!--    <\!-- <label for="catalog">Set the current catalog </label> -\-> -->
-                 <!--    <button type="file" class="btn btn-default"  multiple="false" id="catalog" value="Set the current catalog"></button> -->
-                 <!--  </div> -->
-               </form>
-             </li> <!-- dropdown-item -->
-             <li role="presentation" class="divider"></li>
-             <li class="dropdown-header">Local Side</li> 
-              <li class="dropdown-item"><a class="nav-link" href="#">Set Catalog</a></li>
-              <li class="dropdown-item"><a class="nav-link" href="#">Open Dataset</a></li>
-            </ul> <!-- dropdown-menu -->
-         </li>   <!-- dropdown      -->
-         <li class="nav-item"><a class="nav-link" href="#">Editor</a></li>
-         <li class="nav-item"><a class="nav-link" href="#">Dataset</a></li>
-         <li class="nav-item"><a class="nav-link" href="#">Help</a></li>
-
-       </ul> <!-- nav navbar-nav -->
-
-       <form class="navbar-form navbar-right" action="">
-         <div class="form-group">
-            <input type="text" class="form-control" placeholder="Search"></input>
-         </div>
-         <button type="submit" class="btn btn-default">Submit</button>
-       </form>
-
-       </div> <!-- collapse -->
-       
-
-      </nav>
-    </div>
+  <div class="container-fluid">
 
+    {% block main_menu %} {% endblock %}
 
     {% block commands_menu %} {% endblock %}
 
+    {% block file_management %} {% endblock  %}
+
     {% block content %} {% endblock %}
 
   </div> <!-- container-fluid -->
-
+  
+  {% block scripts %}
+  {#{ super() }#}
+  {% endblock %}
+  
 </html>
 
 <!-- e=tree.findFirst((e)=>{return e.title == "param1";}) -->
index e6d216d8fe595eb73bcbeaed1050870f255d6166..258d73a8197ebdde774e4c8d76bdde2d7c9c88a7 100644 (file)
@@ -1,8 +1,7 @@
-{% extends 'commands_menu.html' %}
+{% extends 'file_management.html' %}
 
 {% block content %}
 
-
 <!--     {%- for key, value in mcTraite.items() recursive %} -->
 <!--   <h3>{{ key }} </h3> -->
 <!--   {%- if value %} -->
 
     <script>
 
+$(function () {
+      $('#formfileupload').fileupload({
+          dataType: 'json',
+          done: function (e, data) {
+              $.each(data.result.files, function (index, file) {
+                 <!-- $('<p></p>').text(file.name).appendTo(document.body); -->
+                 treeMessage("File :"+file.name+" has been successfully impoted","alert-success");
+              });
+          }
+      });
+ });
+
 //$.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 
@@ -162,7 +173,7 @@ function callService(serviceName, obj, callBack) {
        callBack(data);
     };
 
-    const url    = "{{ url_for('appendChild') }}";
+    const url    = "{{ url_for('appendChild') }}";          //PB   : Utilisation de url_for en dynamique
     const newurl = url.replace("appendChild", serviceName); //TODO : Trouver une meilleure solution !
     $.ajax({
         type           : "POST",
@@ -269,7 +280,7 @@ const source = new EventSource("{{ url_for('sse.stream') }}");
         const valid    = data.valid;
         const message  = "The server says " + data.message +" , id: "+id;
         const msgerror = "Event propageValid : can't find node with key :"+id;
-        const tree     = $.ui.fancytree.getTree(_treeCssSelStr);
+        const tree     = $.ui.fancytree.getTree(_treeCssSelStr); //TODO: event.tree ?
         
         treeMessage(_msgCssSelStr,"alert-info",message);
         // console.log("_tree : "+ _tree); //?Expliquer pourquoi null: à cause de $.?
@@ -831,8 +842,6 @@ $(function(){
          <!--   $('#search-output').html(''); -->
          <!-- }); -->
         
-       </script>
-
     </script>
 
 {% endblock %}
index eea5f8fa22399b5b777565fe492fc11ea0d39767..06721e991702b167010f1637a2408e44483a278c 100644 (file)
@@ -1,5 +1,4 @@
-{% extends 'base.html' %}
-
+{% extends 'main_menu.html' %}
 
 {% block commands_menu %}
 
diff --git a/testFlask/templates/file_management.html b/testFlask/templates/file_management.html
new file mode 100644 (file)
index 0000000..79f9277
--- /dev/null
@@ -0,0 +1,193 @@
+{% extends 'commands_menu.html' %}
+
+{% block file_management %}
+
+<!-- Modal -->
+<div id="file_management" class="modal fade" role="dialog">
+  <div class="modal-dialog">
+
+    <!-- Modal content-->
+    <div class="modal-content">
+      <div class="modal-header">
+        <button type="button" class="close" data-dismiss="modal">&times;</button>
+        <h4 class="modal-title">File Management</h4>
+      </div>
+      <div class="modal-body">
+        <!-- <p>Some text in the modal.</p> -->
+
+    <!-- The file upload form used as target for the file upload widget -->
+    <form id="fileupload" action="{{ url_for('upload') }}" method="POST" enctype="multipart/form-data">
+        <!-- Redirect browsers with JavaScript disabled to the origin page -->
+        <noscript><input type="hidden" name="redirect" value="{ url_for('mdm.html') }"></noscript>
+        <!-- The fileupload-buttonbar contains buttons to add/delete files and start/cancel the upload -->
+        <div class="row fileupload-buttonbar">
+            <div class="col-lg-7">
+                <!-- The fileinput-button span is used to style the file input field as button -->
+                <span class="btn btn-success fileinput-button">
+                    <i class="glyphicon glyphicon-plus"></i>
+                    <span>Add files...</span>
+                    <input type="file" name="file" multiple>
+                </span>
+                <button type="submit" class="btn btn-primary start">
+                    <i class="glyphicon glyphicon-upload"></i>
+                    <span>Start upload</span>
+                </button>
+                <button type="reset" class="btn btn-warning cancel">
+                    <i class="glyphicon glyphicon-ban-circle"></i>
+                    <span>Cancel upload</span>
+                </button>
+                <button type="button" class="btn btn-danger delete">
+                    <i class="glyphicon glyphicon-trash"></i>
+                    <span>Delete</span>
+                </button>
+                <input type="checkbox" class="toggle">
+                <!-- The global file processing state -->
+                <span class="fileupload-process"></span>
+            </div>
+            <!-- The global progress state -->
+            <div class="col-lg-5 fileupload-progress fade">
+                <!-- The global progress bar -->
+                <div class="progress progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100">
+                    <div class="progress-bar progress-bar-success" style="width:0%;"></div>
+                </div>
+                <!-- The extended global progress state -->
+                <div class="progress-extended">&nbsp;</div>
+            </div>
+        </div>
+        <!-- The table listing the files available for upload/download -->
+        <table role="presentation" class="table table-striped"><tbody class="files"></tbody></table>
+    </form>
+
+
+       
+      </div>
+      <div class="modal-footer">
+        <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
+      </div>
+    </div> <!-- Modal content-->
+
+  </div> <!-- modal-dialog -->
+</div> <!-- file_management -->
+
+
+{% raw %}
+<!-- The template to display files available for upload -->
+<script id="template-upload" type="text/x-tmpl">
+{% for (var i=0, file; file=o.files[i]; i++) { %}
+    <tr class="template-upload fade">
+        <td>
+            <span class="preview"></span>
+        </td>
+        <td>
+            <p class="name">{%=file.name%}</p>
+            <strong class="error text-danger"></strong>
+        </td>
+        <td>
+            <p class="size">Processing...</p>
+            <div class="progress progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0"><div class="progress-bar progress-bar-success" style="width:0%;"></div></div>
+        </td>
+        <td>
+            {% if (!i && !o.options.autoUpload) { %}
+                <button class="btn btn-primary start" disabled>
+                    <i class="glyphicon glyphicon-upload"></i>
+                    <span>Start</span>
+                </button>
+            {% } %}
+            {% if (!i) { %}
+                <button class="btn btn-warning cancel">
+                    <i class="glyphicon glyphicon-ban-circle"></i>
+                    <span>Cancel</span>
+                </button>
+            {% } %}
+        </td>
+    </tr>
+{% } %}
+</script>
+<!-- The template to display files available for download -->
+<script id="template-download" type="text/x-tmpl">
+{% for (var i=0, file; file=o.files[i]; i++) { %}
+    <tr class="template-download fade">
+        <td>
+            <span class="preview">
+                {% if (file.thumbnailUrl) { %}
+                    <a href="{%=file.url%}" title="{%=file.name%}" download="{%=file.name%}" data-gallery><img src="{%=file.thumbnailUrl%}"></a>
+                {% } %}
+            </span>
+        </td>
+        <td>
+            <p class="name">
+                {% if (file.url) { %}
+                    <a href="{%=file.url%}" title="{%=file.name%}" download="{%=file.name%}" {%=file.thumbnailUrl?'data-gallery':''%}>{%=file.name%}</a>
+                {% } else { %}
+                    <span>{%=file.name%}</span>
+                {% } %}
+            </p>
+            {% if (file.error) { %}
+                <div><span class="label label-danger">Error</span> {%=file.error%}</div>
+            {% } %}
+        </td>
+        <td>
+            <span class="size">{%=o.formatFileSize(file.size)%}</span>
+        </td>
+        <td>
+            {% if (file.deleteUrl) { %}
+                <button class="btn btn-danger delete" data-type="{%=file.deleteType%}" data-url="{%=file.deleteUrl%}"{% if (file.deleteWithCredentials) { %} data-xhr-fields='{"withCredentials":true}'{% } %}>
+                    <i class="glyphicon glyphicon-trash"></i>
+                    <span>Delete</span>
+                </button>
+                <input type="checkbox" name="delete" value="1" class="toggle">
+            {% } else { %}
+                <button class="btn btn-warning cancel">
+                    <i class="glyphicon glyphicon-ban-circle"></i>
+                    <span>Cancel</span>
+                </button>
+            {% } %}
+        </td>
+    </tr>
+{% } %}
+</script>
+{% endraw %}
+
+{% endblock file_management %}
+
+{% block scripts %}
+<!-- <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script> -->
+<!-- <\!-- The jQuery UI widget factory, can be omitted if jQuery UI is already included -\-> -->
+<!-- <script src="static/js/vendor/jquery.ui.widget.js"></script> -->
+<!-- <\!-- The Templates plugin is included to render the upload/download listings -\-> -->
+
+<script src="http://blueimp.github.io/JavaScript-Templates/js/tmpl.min.js"></script>
+<!-- The Load Image plugin is included for the preview images and image resizing functionality -->
+<script src="http://blueimp.github.io/JavaScript-Load-Image/js/load-image.all.min.js"></script>
+<!-- The Canvas to Blob plugin is included for image resizing functionality -->
+<script src="http://blueimp.github.io/JavaScript-Canvas-to-Blob/js/canvas-to-blob.min.js"></script>
+<!-- Bootstrap JS is not required, but included for the responsive demo navigation -->
+<!-- <script src="//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script> -->
+<!-- blueimp Gallery script -->
+<script src="http://blueimp.github.io/Gallery/js/jquery.blueimp-gallery.min.js"></script>
+<!-- The Iframe Transport is required for browsers without support for XHR file uploads -->
+
+<!-- <script src="static/jQuery-File-Upload/js/jquery.iframe-transport.js"></script> -->
+<!-- <\!-- The basic File Upload plugin -\-> -->
+<!-- <script src="static/jQuery-File-Upload/js/jquery.fileupload.js"></script> -->
+<!-- <\!-- The File Upload processing plugin -\-> -->
+
+<script src="static/jQuery-File-Upload/js/jquery.fileupload-process.js"></script>
+<!-- The File Upload image preview & resize plugin -->
+<script src="static/jQuery-File-Upload/js/jquery.fileupload-image.js"></script>
+<!-- The File Upload audio preview plugin -->
+<script src="static/jQuery-File-Upload/js/jquery.fileupload-audio.js"></script>
+<!-- The File Upload video preview plugin -->
+<script src="static/jQuery-File-Upload/js/jquery.fileupload-video.js"></script>
+<!-- The File Upload validation plugin -->
+<script src="static/jQuery-File-Upload/js/jquery.fileupload-validate.js"></script>
+<!-- The File Upload user interface plugin -->
+<script src="static/jQuery-File-Upload/js/jquery.fileupload-ui.js"></script>
+<!-- The main application script -->
+<script src="static/jQuery-File-Upload/js/main.js"></script> <!--TODO: à personaliser -->
+<!-- The XDomainRequest Transport is included for cross-domain file deletion for IE 8 and IE 9 -->
+<!--[if (gte IE 8)&(lt IE 10)]>
+<script src="js/cors/jquery.xdr-transport.js"></script>
+<![endif]-->
+{% endblock %}
+
diff --git a/testFlask/templates/file_management_menu.html b/testFlask/templates/file_management_menu.html
new file mode 100644 (file)
index 0000000..29afa6b
--- /dev/null
@@ -0,0 +1,26 @@
+{% extends commands_menu.html' %}
+
+{% block file_management %}
+
+<!-- Modal -->
+<div id="myModal" class="modal fade" role="dialog">
+  <div class="modal-dialog">
+
+    <!-- Modal content-->
+    <div class="modal-content">
+      <div class="modal-header">
+        <button type="button" class="close" data-dismiss="modal">&times;</button>
+        <h4 class="modal-title">Modal Header</h4>
+      </div>
+      <div class="modal-body">
+        <p>Some text in the modal.</p>
+      </div>
+      <div class="modal-footer">
+        <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
+      </div>
+    </div>
+
+  </div>
+</div>
+
+{% endblock file_management %}
diff --git a/testFlask/templates/main_menu.html b/testFlask/templates/main_menu.html
new file mode 100644 (file)
index 0000000..4458abd
--- /dev/null
@@ -0,0 +1,55 @@
+{% extends 'base.html' %}
+
+{% block main_menu %}
+
+    <div class="row" data-spy="affix" id="row-main_menu">
+      <nav class="navbar navbar-inverse flex-column flex-md-row">
+       
+       <div class="navbar-header">
+         <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#myNavbar">
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>                        
+         </button>
+         <a class="navbar-brand" href="#">MDM/Eficas</a>
+       </div>
+
+       <div class="collapse navbar-collapse" id="myNavbar">
+       <ul class="nav navbar-nav">
+         
+         <li class="dropdown">
+            <a class="nav-link dropdown-toggle" data-toggle="dropdown" href="#">File<span class="caret"></span></a>
+            <ul class="dropdown-menu">
+             <li class="dropdown-header">Server Side</li> 
+             <li class="dropdown-item">
+
+               <button type="button" class="btn btn-success" data-toggle="modal" data-target="#file_management">File Management</button>
+       
+             </li> <!-- dropdown-item -->
+             <li role="presentation" class="divider"></li>
+             <li class="dropdown-header">Local Side</li> 
+              <li class="dropdown-item"><a class="nav-link" href="#">Set Catalog</a></li>
+              <li class="dropdown-item"><a class="nav-link" href="#">Open Dataset</a></li>
+            </ul> <!-- dropdown-menu -->
+         </li>   <!-- dropdown      -->
+         <li class="nav-item"><a class="nav-link" href="#">Editor</a></li>
+         <li class="nav-item"><a class="nav-link" href="#">Dataset</a></li>
+         <li class="nav-item"><a class="nav-link" href="#">Help</a></li>
+
+       </ul> <!-- nav navbar-nav -->
+
+       <form class="navbar-form navbar-right" action="">
+         <div class="form-group">
+            <input type="text" class="form-control" placeholder="Search"></input>
+         </div>
+         <button type="submit" class="btn btn-default">Submit</button>
+       </form>
+
+       </div> <!-- collapse -->
+       
+
+      </nav>
+    </div>
+
+{% endblock %}
+