From 4e0e577cd3ca07c6498d6fcbefc93938dbbdbea8 Mon Sep 17 00:00:00 2001
From: Armand Bahi <armand.bahi@veremes.com>
Date: Thu, 22 Nov 2018 15:17:12 +0100
Subject: [PATCH] Squashed 'src/vitis/' changes from 940a5919d..ad685c897
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

ad685c897 Merge branch 'next_version' into 'next_app_vmap'
4a400f14c Merge branch 'next_app_dtnet' into 'next_version'
dc9e09bb2 Merge branch 'next_app_vmap' into 'next_version'
ed3718efb Next app vmap
6909aeec2 Correctif sur la concaténation de filtres
68d6ee11f Retouche attribut comparator sur les formulaires de filtres
85bb73a6a Correction problèmes de chargement JS des sous formulaires
613ccca59 pull subtree
7755613b5 Squashed 'src/module_cadastre/' changes from 66dbfede..5883a499
51b130eab pull subtree
ec89ac3d3 Squashed 'src/module_cadastreV2/' changes from 66dbfede..bc664f7f
5b7a10764 pull subtree
924126125 Squashed 'src/module_anc/' changes from 66dbfede..24e0fb69
b9ae98075 pull subtree
90da1776c Squashed 'src/module_vm4ms/' changes from 66dbfede..16f9769a
4f5cf2209 pull subtree
116e02109 Squashed 'src/module_vmap/' changes from 66dbfede..2b3157a0
bf01f3283 pull subtree
f0020699a Correction problèmes chargement JS sous formulaires
07f786fb7 update colonne version pour accepter les version de plus de 10 caractères
c2776a819 Merge remote-tracking branch 'origin/next_version' into next_version
f29a96e0b Review Checkbox CSS
f4a1833bc Review Checkbox CSS
ce3bb9c99 Resolve "[Studio] suppressions des différents formulaires"
b2615442f pull subtree
914a1b6ae pull subtree
7facefc72 Merge branch 'master' into next_version
7fbff5c81 Merge remote-tracking branch 'origin/master'
65d69a474 Remove auto pull/push subtrees
02633d0cf Remove auto pull/push subtrees
5a8cfb322 Pull/push_subtrees.sh
2fb6e11bf use next_app_vmap branches
4cbf5a6f8 Merge branch 'master'
c64422b20 Merge branch 'master'
3097ea44e Merge branch 'cherry-pick-08ef8c91' into 'next_version'
1a3e25095 Merge branch 'bug/1-cadastre-recherche-attributaire-la-selection-reste-en-memoire-quand-on-filtre-la-liste-des-parcelles' into 'master'
08ef8c918 Merge branch 'bug/1-cadastre-recherche-attributaire-la-selection-reste-en-memoire-quand-on-filtre-la-liste-des-parcelles' into 'master'
731fb56e4 Merge branch 'bug/1-cadastre-recherche-attributaire-la-selection-reste-en-memoire-quand-on-filtre-la-liste-des-parcelles' into 'master'
ef0c46d21 Bug/1 cadastre recherche attributaire la selection reste en memoire quand on filtre la liste des parcelles
7fd95b0d7 Replace bootstrapTable getAllSelections by getSelections
173760d70 Merge branch 'master' into bug/1-cadastre-recherche-attributaire-la-selection-reste-en-memoire-quand-on-filtre-la-liste-des-parcelles
4613f700f link subtrees on branch app_vmap
6a47c43a9 Rename pull.sh into pull_subtrees.sh
591f4ecd6 pull subtree
77845c681 Squashed 'src/module_vmap/' changes from 3e46450b..fb263937
475f62184 pull subtree
4b44e6b9f Squashed 'src/vitis/' changes from 12a22d70..4398b26d
4398b26d4 Merge branch 'bug/4-formreader-champs-date-non-pris-en-compte-si-on-met-la-date-du-jour-en-insertion' into 'master'
d17933b98 Edit datetime picker event
b3b6ec068 Merge branch '1-js-sous-formulaire' into 'master'
41a15530c Load BO Javascript on subforms
376432737 Merge remote-tracking branch 'origin/master'
e058ef8f9 Resolve grunt links
4f4bf75c2 Correct grunt problems
dca067bb4 Merge branch 'dev_master' into 'master'
837046c7e Dev master
82a645db6 Update properties.json
5d57e51c8 Update conf/properties.json
ee905c134 Resolve web services update problem
54bd17752 Minify JS after updating files
c35cc38d5 Merge branch 'master' of gitlab.veremes.net:Development/vitis_apps/application/vmap
6a7cf62ca Minify JS after updating files
7b0e04e07 Minify JS after updating files
479d78536 Add install/update files for windows
78a320a03 pull subtree
e2a617e77 Squashed 'src/module_cadastreV2/' changes from 8158b9a2..895d7e3b
926bff66a Utilisation des utils sans avoir besoin de linxml2
3df5e36a4 Squashed 'src/module_vmap/' changes from 98047575..3e46450b
0852ad92b pull subtree
9f1318703 Utilisation des utils sans avoir besoin de libxml2
1a61e637b Merge branch 'master' of gitlab.veremes.net:Development/vitis_apps/application/vmap
03a5dfe3c Update pull/push_subtrees.sh to use the current version of subtrees
51f83a0be Add windows install files
457792c69 pull subtree
0bf9c2cc9 Squashed 'src/module_cadastre/' changes from a36394b9..1c340f7e
b5c65a645 pull subtree
5e944c4a8 Squashed 'src/vitis/' changes from 7b55e67..12a22d7
85f07d4a5 Update init_symlinks
896a06b78 pull subtree
e9dfdcbc8 Squashed 'src/module_anc/' changes from 8bb35778..68cd7130
393551e31 pull subtree
5cd5ab056 Squashed 'src/module_vmap/' changes from e7dabee..9804757
19925d4f8 pull subtree
df4164395 Squashed 'src/vitis/' changes from 7a1818a..7b55e67
59e770c13 pull subtree
77582f184 Update gitignore
aa4b71d80 Remvove web_service from parent
99dab6419 Update gitignore
7e0d02d6c Update Readme
74b02e3f0 Merge branch 'master' of gitlab.veremes.net:Development/vitis_apps/application/vmap
05269f929 Modify symlinks strategy
577d76547 Modify symlinks strategy
3c521a9ea Modify symlinks strategy
cf8ebcdc5 Update symlinks strategy
b93b890cb Modify symlinks strategy
139ee7e44 Modify symlinks strategy
3427147f5 Squashed 'src/module_cadastre/' changes from ee26cf16..a36394b9
54df607da pull subtree
3ce44dcc5 Squashed 'src/module_anc/' changes from 4321adc4..8bb35778
1056cb48b pull subtree
278331d3b pull subtree
a0cda927a Squashed 'src/module_vm4ms/' changes from 373ef426..4d95a3da
1b6864ef4 add subtree
9d999ac0d add subtree
df88c9555 Squashed 'src/module_cadastre/' content from commit 0bb9b2fa9
2b0c911ed Squashed 'src/module_cadastre/' content from commit 0bb9b2fa9
e2a23cafd add subtree
e0e437ec7 Squashed 'src/module_cadastreV2/' content from commit b442386a7
4fa86e720 add subtree
6b7d2e6a1 Squashed 'src/module_anc/' content from commit 24e0fb694
1af7f5c48 add subtree
2e8e909ba Squashed 'src/module_vm4ms/' content from commit 16f9769a7
5f3241aec add subtree
a0825d63e Squashed 'src/module_vmap/' content from commit ce9e639a
3f3d51c30 add subtree
41d5aec2e Squashed 'src/closure/' content from commit 622066db
d661316e7 add subtree
91cd365c7 add subtree
7c3aef172 Squashed 'src/vitis/' content from commit 355b5f8b
e8597475d Reset sources
8fe041e4f Merge branch 'master' into next_version
0c3ac326c Change dependency.xml

git-subtree-dir: src/vitis
git-subtree-split: ad685c897c22bd6c274cd6e485fb5cbd9db8e136
---
 client/javascript/app/script_client.js        |  85 +++++-----
 .../externs/formReader/formReaderDrtv.js      |   7 +-
 .../externs/formReader/formReaderSrvc.js      |  30 +++-
 .../studio/javascript/app/JsonLoader.js       | 153 ++++++++++--------
 .../externs/studio/lang/lang-en.json          |  10 +-
 .../externs/studio/lang/lang-fr.json          |  10 +-
 .../externs/studio/less/studio.less           |  46 ++----
 .../externs/studio/templates/JsonLoader.html  |  22 ++-
 client/less/main.less                         |  21 +++
 vas/sql/sqlQueries.xml                        |   2 +-
 10 files changed, 238 insertions(+), 148 deletions(-)

diff --git a/client/javascript/app/script_client.js b/client/javascript/app/script_client.js
index 02bda1b1..d139ae71 100644
--- a/client/javascript/app/script_client.js
+++ b/client/javascript/app/script_client.js
@@ -875,52 +875,53 @@ vitisApp.on('appInitCtrlLoaded', function () {
 
             if (typeof (sValue) !== "undefined" && (sValue.toString()) !== "") {
                 if (goog.isDefAndNotNull(oFormElement["comparator"])) {
-                    if (goog.isDefAndNotNull(oFormElement["comparator"]["formater"])) {
-                        sValue = oFormElement["comparator"]["formater"].replace(/<VALUE_TO_REPLACE>/g, sValue);
+                    var aOperators = [];
+                    for (var j = 0;j < oFormElement["comparator"].length;j++){
+                        if(goog.isObject(oFormElement["comparator"][j])){
+                            var oOperator = {};
+                            if (goog.isDefAndNotNull(oFormElement["comparator"][j]["formater"])) {
+                                sValue = oFormElement["comparator"][j]["formater"].replace(/<VALUE_TO_REPLACE>/g, sValue);
+                            }
+
+                            if(goog.isArray(oFormElement["comparator"][j]["compare_operator"])){
+                                oOperator["relation"] = (goog.isDefAndNotNull(oFormElement["comparator"][j]["relation"]) ? oFormElement["comparator"][j]["relation"] : "AND");
+                                oOperator["operators"] = [];
+                                for (var k = 0; k < oFormElement["comparator"][j]["compare_operator"].length; k++){
+                                    oOperator["operators"].push({
+                                        "column": (goog.isArray(oFormElement["comparator"][j]["column"]) ? oFormElement["comparator"][j]["column"][k] : oFormElement["name"]),
+                                        "compare_operator": oFormElement["comparator"][j]["compare_operator"][k],
+                                        "value": sValue
+                                    });
+                                }
+                            }else{
+                                oOperator["column"] = (goog.isDefAndNotNull(oFormElement["comparator"][j]["column"]) ? oFormElement["comparator"][j]["column"] : oFormElement["name"]);
+                                oOperator["compare_operator"] = oFormElement["comparator"][j]["compare_operator"];
+                                oOperator["value"] = sValue;
+                            }
+
+                            if(goog.isDefAndNotNull(oFormElement["comparator"][j]["compare_operator_options"])){
+                                oOperator["compare_operator_options"] = oFormElement["comparator"][j]["compare_operator_options"];
+                            }
+
+                            aOperators.push(oOperator);
+                        }else{
+                            // deprecated branch
+                            console.warn("This use of compare attribute is deprecated in json form")
+                            aOperators.push({
+                                "column": (goog.isDefAndNotNull(oFormElement["attrToCompare"]) ? oFormElement["attrToCompare"][j] : oFormElement["name"]),
+                                "compare_operator": oFormElement["comparator"][j],
+                                "value": sValue
+                            });
+                        }
                     }
-                    //
-                    for (var j = 0; j < oFormElement["comparator"].length; j++) {
+                    if(goog.isDefAndNotNull(oFormElement["comparator_relation"])){
                         oFilter["operators"].push({
-                            "column": (goog.isDefAndNotNull(oFormElement["attrToCompare"]) ? oFormElement["attrToCompare"][j] : oFormElement["name"]),
-                            "compare_operator": oFormElement["comparator"][j],
-                            "value": sValue
+                            "relation": oFormElement["comparator_relation"],
+                            "operators": aOperators
                         });
+                    }else{
+                        oFilter["operators"] = oFilter["operators"].concat(aOperators);
                     }
-                    /*
-                    oFormElement["comparator"]["value"] = sValue;
-                    oFilter["operators"].push(oFormElement["comparator"]);
-                    
-                     for (var j = 0; j < oFormElement["comparator"].length; j++) {
-                     var sFormElement = "";
-                     if (goog.isDefAndNotNull(oFormElement["attrToCompare"])) {
-                     sFormElement = (goog.isDefAndNotNull(oFormElement["attrToCompare"][j]) ? oFormElement["attrToCompare"][j] : oFormElement["name"]);
-                     } else {
-                     sFormElement = oFormElement["name"];
-                     }
-                     var bIsNotNumber = true;
-                     if (goog.isDefAndNotNull(oFormElement["NaNForced"])) {
-                     bIsNotNumber = (goog.isDefAndNotNull(oFormElement["NaNForced"][j]) ? oFormElement["NaNForced"][j] : isNaN(sValue));
-                     } else {
-                     bIsNotNumber = isNaN(sValue);
-                     }
-                     switch (oFormElement["comparator"][j]) {
-                     case 'LIKE' :
-                     oFilter.push('lower("' + sFormElement + '") LIKE lower(\'%' + sValue + '%\')');
-                     break;
-                     case 'SQL' :
-                     oFilter.push(sFormElement.replace(/<VALUE_TO_REPLACE>/g, sValue));
-                     break;
-                     // ajouter d'autre comparateur si besoin ex: BETWEEN ______ AND ______
-                     default:
-                     // = < <= > >= basique
-                     if (bIsNotNumber) {
-                     sValue = "'" + sValue + "'";
-                     }
-                     oFilter.push(sFormElement + oFormElement["comparator"][j] + sValue);
-                     break;
-                     }
-                     }
-                     */
                 } else {
                     if (oFormElement["type"] == "text") {
                         oFilter["operators"].push({
diff --git a/client/javascript/externs/formReader/formReaderDrtv.js b/client/javascript/externs/formReader/formReaderDrtv.js
index 6634f5d4..48e7a37a 100644
--- a/client/javascript/externs/formReader/formReaderDrtv.js
+++ b/client/javascript/externs/formReader/formReaderDrtv.js
@@ -2156,8 +2156,8 @@ formReader.appSubformGridDrtv = function ($timeout, $translate, propertiesSrvc,
 
                                     // Récupère lélément en sélectionné
                                     formReaderService['getWebServiceData'](oFormWebService).then(function (aResult) {
-
                                         var oSubformDefinition = aResult[0]['bo_json_form'];
+                                        var sSubformJSDefinition = aResult[0]['bo_json_form_js'];
                                         var oSubformValues = {};
                                         var sModalId = 'formreader_' + scope['sFormUniqueName'] + '_grid_subform_modal';
 
@@ -2224,7 +2224,7 @@ formReader.appSubformGridDrtv = function ($timeout, $translate, propertiesSrvc,
                                             }
                                         });
 
-                                        formReaderService['showModalSubform'](sModalId, oSubformScope, oSubformDefinition, sSubformDefinitionName, oSubformValues);
+                                        formReaderService['showModalSubform'](sModalId, oSubformScope, oSubformDefinition, sSubformDefinitionName, oSubformValues, sSubformJSDefinition);
                                     });
                                 };
 
@@ -2252,6 +2252,7 @@ formReader.appSubformGridDrtv = function ($timeout, $translate, propertiesSrvc,
                         };
                         var sModalId = 'formreader_' + scope['sFormUniqueName'] + '_grid_subform_modal';
                         var oSubformDefinition = oBusinessObject['json_form'][0];
+                        var sSubformJSDefinition = oBusinessObject['json_form_js'];
                         var sSubformDefinitionName = 'insert';
 
                         // Grise le champ contenant la valeur du parent
@@ -2293,7 +2294,7 @@ formReader.appSubformGridDrtv = function ($timeout, $translate, propertiesSrvc,
                                 });
                             });
                         };
-                        formReaderService['showModalSubform'](sModalId, oSubformScope, oSubformDefinition, sSubformDefinitionName, oSubformValues);
+                        formReaderService['showModalSubform'](sModalId, oSubformScope, oSubformDefinition, sSubformDefinitionName, oSubformValues, sSubformJSDefinition);
                     };
 
                     /**
diff --git a/client/javascript/externs/formReader/formReaderSrvc.js b/client/javascript/externs/formReader/formReaderSrvc.js
index 6ca6ef29..613652f9 100644
--- a/client/javascript/externs/formReader/formReaderSrvc.js
+++ b/client/javascript/externs/formReader/formReaderSrvc.js
@@ -1230,15 +1230,15 @@ formReader.formReaderService = function ($translate, $rootScope, $q, $log, $time
          * @param {object} oSubformDefinition
          * @param {object} oSubformDefinitionName
          * @param {object} oSubformValues
+         * @param {string|null} sSubformJSDefinition
          */
-        "showModalSubform": function (sModalId, oSubformScope, oSubformDefinition, oSubformDefinitionName, oSubformValues) {
+        "showModalSubform": function (sModalId, oSubformScope, oSubformDefinition, oSubformDefinitionName, oSubformValues, sSubformJSDefinition) {
             $log.log("showModalSubform");
 
             var sToken = this['sToken'];
             var oProperties = this['oProperties'];
 
-            if (goog.isDefAndNotNull(oSubformScope['loadSubForm'])) {
-
+            var loadForm = function(){
                 oSubformScope['loadSubForm']({
                     'sFormDefinitionName': oSubformDefinitionName,
                     'oFormDefinition': oSubformDefinition,
@@ -1246,6 +1246,30 @@ formReader.formReaderService = function ($translate, $rootScope, $q, $log, $time
                     'oProperties': oProperties,
                     'sToken': sToken
                 });
+            }
+
+            if (goog.isDefAndNotNull(oSubformScope['loadSubForm'])) {
+
+                if (goog.isDefAndNotNull(sSubformJSDefinition)) {
+                    var sUrl = sSubformJSDefinition;
+                    oVmap.log("initHtmlForm : javascript assoc. to : " + sUrl);
+                    loadExternalJs([sUrl], {
+                        "callback": function () {
+                            loadForm();
+                            try {
+                                if (goog.isDef(constructor_form)) {
+                                    constructor_form(oSubformScope, sUrl);
+                                }
+                            } catch (e) {
+                                oVmap.log("constructor_form does not exist");
+                            }
+                        },
+                        "async": true,
+                        "scriptInBody": true
+                    });
+                } else {
+                    loadForm();
+                }
 
                 $('#' + sModalId).modal('show');
             }
diff --git a/client/javascript/externs/studio/javascript/app/JsonLoader.js b/client/javascript/externs/studio/javascript/app/JsonLoader.js
index 8dd8de68..ff0407e2 100755
--- a/client/javascript/externs/studio/javascript/app/JsonLoader.js
+++ b/client/javascript/externs/studio/javascript/app/JsonLoader.js
@@ -248,7 +248,7 @@ nsVFB.JsonLoader.prototype.jsonLoaderController.prototype.requestToJson = functi
                             cmd = "Perso_Reset";
                             break;
                     }
-                    this_.putRequest(cmd, undefined, function (data) {
+                    this_.putRequest(cmd, this_.$scope_["FormSelected"], undefined, function (data) {
 
                         // Cas d'erreur du put
                         if (goog.isDefAndNotNull(data['errorMessage'])) {
@@ -584,18 +584,6 @@ nsVFB.JsonLoader.prototype.jsonLoaderController.prototype.save = function (succe
     oVFB.unselectAll();
     tmp = oVFB.cleanFormToSave(tmp);
 
-    /*if ($("#boolean-JS-include").prop("checked")) {
-     tmp[this_.$rootScope_["selected_form_type"]]["javascript"] = true;
-     } else {
-     tmp[this_.$rootScope_["selected_form_type"]]["javascript"] = false;
-     }
-
-     if ($("#boolean-CSS-include").prop("checked")) {
-     tmp[this_.$rootScope_["selected_form_type"]]["style"] = true;
-     } else {
-     tmp[this_.$rootScope_["selected_form_type"]]["style"] = false;
-     }*/
-
     if (this['applicationName'] === 'gtf') {
         tmp[this_.$rootScope_["selected_form_type"]]["name"] = "WSubform";
         tmp["display"] = tmp[this_.$rootScope_["selected_form_type"]];
@@ -623,7 +611,7 @@ nsVFB.JsonLoader.prototype.jsonLoaderController.prototype.save = function (succe
     oVFB.valid = this.isValid(tmp);
 
     if (oVFB.valid && tmp !== null) {
-        this_.putRequest("Perso_Save", data, success, error);
+        this_.putRequest("Perso_Save", this_.$scope_["FormSelected"], data, success, error);
     } else {
         $["notify"](this_.$scope_["text"]["Loader"]["Notify"]["Validation_Error"] + ': ' + oVFB.aNotValid, {"className": "error", "autoHideDelay": oVFB.TimeNotify_});
     }
@@ -646,18 +634,6 @@ nsVFB.JsonLoader.prototype.jsonLoaderController.prototype.publish = function ()
     // Supprime les elements selectionnés
     oVFB.unselectAll();
 
-    /*if ($("#boolean-JS-include").prop("checked")) {
-     tmp[this_.$rootScope_["selected_form_type"]]["javascript"] = true;
-     } else {
-     tmp[this_.$rootScope_["selected_form_type"]]["javascript"] = false;
-     }
-
-     if ($("#boolean-CSS-include").prop("checked")) {
-     tmp[this_.$rootScope_["selected_form_type"]]["style"] = true;
-     } else {
-     tmp[this_.$rootScope_["selected_form_type"]]["style"] = false;
-     }*/
-
     if (this['applicationName'] === 'gtf') {
         tmp[this_.$rootScope_["selected_form_type"]]["name"] = "WSubform";
         tmp["display"] = tmp[this_.$rootScope_["selected_form_type"]];
@@ -669,7 +645,6 @@ nsVFB.JsonLoader.prototype.jsonLoaderController.prototype.publish = function ()
     data.append("Css", oVFB.getCss());
 
     var success = function () {
-//        $["notify"](this_.$scope_["text"]["Loader"]["Notify"]["SaveData"], {"className": "success", "autoHideDelay": oVFB.TimeNotify_});
         var data = "";
         var success = function () {
             this_.requestToJson();
@@ -679,17 +654,16 @@ nsVFB.JsonLoader.prototype.jsonLoaderController.prototype.publish = function ()
             $["notify"](this_.$scope_["text"]["Loader"]["Notify"]["Publish_Error"] + status, {"className": "error", "autoHideDelay": oVFB.TimeNotify_});
         };
 
-        this_.putRequest(this_.$scope_["FormSelected"] + "_Published", data, success, error);
+        this_.putRequest(this_.$scope_["FormSelected"] + "_Published", this_.$scope_["FormSelected"], data, success, error);
     };
     var error = function (data, status) {
         $["notify"](this_.$scope_["text"]["Loader"]["Notify"]["SaveData_Error"] + status, {"className": "error", "autoHideDelay": oVFB.TimeNotify_});
     };
     if (oVFB.valid) {
         if (this_.$scope_["FormSelected"] != "Default") {
-            this_.putRequest("Perso_Save", data, success, error);
+            this_.putRequest("Perso_Save", this_.$scope_["FormSelected"], data, success, error);
         } else {
-            this_.putRequest("Default_Published", data, success, error);
-
+            this_.putRequest("Default_Published", this_.$scope_["FormSelected"], data, success, error);
         }
     } else {
         $["notify"](this_.$scope_["text"]["Loader"]["Notify"]["Validation_Error"], {"className": "error", "autoHideDelay": oVFB.TimeNotify_});
@@ -763,7 +737,7 @@ nsVFB.JsonLoader.prototype.jsonLoaderController.prototype.reset = function () {
                 var error = function (data, status) {
                     $["notify"](this_.$scope_["text"]["Loader"]["Notify"]["Reset_Error"] + status, {"className": "error", "autoHideDelay": oVFB.TimeNotify_});
                 };
-                this_.putRequest(this_.$scope_["FormSelected"] + "_Reset", data, success, error);
+                this_.putRequest(this_.$scope_["FormSelected"] + "_Reset", this_.$scope_["FormSelected"], data, success, error);
             }
         }
     });
@@ -771,14 +745,63 @@ nsVFB.JsonLoader.prototype.jsonLoaderController.prototype.reset = function () {
     oVFB.studioMainController.prototype.moveBootboxModalToStudioContainer(oModal);
 };
 
+/**
+ * Remove the published form on the server
+ *
+ * @export
+ */
+nsVFB.JsonLoader.prototype.jsonLoaderController.prototype.deletePublishedForm = function () {
+    oVFB.log('nsVFB.JsonLoader.jsonLoaderController.deletePublishedForm');
+
+    var this_ = this;
+    var oModal = bootbox.confirm('<h4>' + this["text"]["InfoBulle"]["Published"]["DeletePublishedForm"] + ' ?</h4>', function (result) {
+        if (result === true) {
+            var data = "";
+            var success = function () {
+                $["notify"](this_.$scope_["text"]["Loader"]["Notify"]["Delete"], {"className": "success", "autoHideDelay": oVFB.TimeNotify_});
+                this_.requestToJson();
+            };
+            var error = function (data, status) {
+                $["notify"](this_.$scope_["text"]["Loader"]["Notify"]["Delete_Error"] + status, {"className": "error", "autoHideDelay": oVFB.TimeNotify_});
+            };
+            this_.putRequest('Published_Delete', 'Published', data, success, error);
+        }
+    });
+}
+
+/**
+ * Remove the form JS on the server
+ *
+ * @export
+ */
+nsVFB.JsonLoader.prototype.jsonLoaderController.prototype.deleteJS = function () {
+    oVFB.log('nsVFB.JsonLoader.jsonLoaderController.deleteJS');
+
+    var this_ = this;
+    var oModal = bootbox.confirm('<h4>' + this["text"]["InfoBulle"]["Perso"]["Delete_JS"] + ' ?</h4>', function (result) {
+        if (result === true) {
+            var data = "";
+            var success = function () {
+                $["notify"](this_.$scope_["text"]["Loader"]["Notify"]["Delete_JS"], {"className": "success", "autoHideDelay": oVFB.TimeNotify_});
+                this_.requestToJson();
+            };
+            var error = function (data, status) {
+                $["notify"](this_.$scope_["text"]["Loader"]["Notify"]["Delete_JS_Error"] + status, {"className": "error", "autoHideDelay": oVFB.TimeNotify_});
+            };
+            this_.putRequest('Delete_JS', this_.$scope_["FormSelected"], data, success, error);
+        }
+    });
+}
+
 /**
  * Make a put request on the server
  * @param {string} cmd command to load (Perso_Save, Perso_Published, Default_Published, Perso_Reset etc...)
+ * @param {string} sForm form to update
  * @param {object} data FormData to send
  * @param {function} functSuccess function to load in case of success
  * @param {function} functError function to load in case of error
  */
-nsVFB.JsonLoader.prototype.jsonLoaderController.prototype.putRequest = function (cmd, data, functSuccess, functError) {
+nsVFB.JsonLoader.prototype.jsonLoaderController.prototype.putRequest = function (cmd, sForm, data, functSuccess, functError) {
     oVFB.log('nsVFB.JsonLoader.prototype.jsonLoaderController.prototype.putRequest');
 
     var url = '';
@@ -810,15 +833,6 @@ nsVFB.JsonLoader.prototype.jsonLoaderController.prototype.putRequest = function
         'success': functSuccess,
         'error': functError
     });
-
-//    this.$http_({
-//        url: url,
-//        method: 'PUT',
-//        data: data,
-//        headers: {
-//            "Content-Type": "undefined"
-//        }
-//    }).success(functSuccess).error(functError);
 };
 
 /**
@@ -829,14 +843,34 @@ nsVFB.JsonLoader.prototype.jsonLoaderController.prototype.suggestGenerateForm =
     oVFB.log('nsVFB.JsonLoader.prototype.jsonLoaderController.prototype.suggestGenerateForm');
 
     var this_ = this;
-    var oModal = bootbox.confirm('<h4>' + this.$scope_['text']['Loader']['Notify']['generate_form'] + '</h4>', function (result) {
-        if (result === true) {
-            this_.suggestColumnsToGenerateForm();
-        } else {
-            this_['aSuggestedTableFields'] = [];
-            this_.generateFormByBusinessObject();
+    var oModal = bootbox['dialog']({
+        'message': '<h4>' + this.$scope_['text']['Loader']['Notify']['generate_form'] + '</h4>',
+        'buttons': {
+            'cancel': {
+                'label': this.$scope_['text']['Loader']['Cancel'],
+                'className': 'btn-default',
+                'callback': function(){
+                    this_.useEmptyForm();
+                }
+            },
+            'create_empty': {
+                'label': this.$scope_['text']['Loader']['CreateEmptyForm'],
+                'className': 'btn-primary',
+                'callback': function(){
+                    this_['aSuggestedTableFields'] = [];
+                    this_.generateFormByBusinessObject();
+                }
+            },
+            'generate_from_columns': {
+                'label': this.$scope_['text']['Loader']['GenerateForm'],
+                'className': 'btn-primary',
+                'callback': function(){
+                    this_.suggestColumnsToGenerateForm();
+                }
+            }
         }
     });
+
     // Déplace la popup dans l'élément principal du studio (sinon elle est masquée en mode plein écran).
     oVFB.studioMainController.prototype.moveBootboxModalToStudioContainer(oModal);
 };
@@ -860,10 +894,16 @@ nsVFB.JsonLoader.prototype.jsonLoaderController.prototype.useEmptyForm = functio
         'javascript': false,
         'name': 'custom-form',
         'nb_cols': 12,
-        'rows': [],
+        'rows': [{
+            'fields': []
+        }],
         'title': ''
     };
 
+    if (!goog.isArray(data)) {
+        data = [];
+    }
+
     data[0] = {
         'datasources': {}
     };
@@ -1017,7 +1057,7 @@ nsVFB.JsonLoader.prototype.jsonLoaderController.prototype.generateFormByBusiness
         var error = function (data, status) {
             $["notify"](this_.$scope_["text"]["Loader"]["Notify"]["Reset_Error"] + status, {"className": "error", "autoHideDelay": oVFB.TimeNotify_});
         };
-        this_.putRequest(this_.$scope_["FormSelected"] + "_Reset", {"field": sFieldsToUse, "label": afieldsLabel}, success, error);
+        this_.putRequest(this_.$scope_["FormSelected"] + "_Reset", this_.$scope_["FormSelected"], {"field": sFieldsToUse, "label": afieldsLabel}, success, error);
     } else {
 
         ajaxRequest({
@@ -1035,19 +1075,6 @@ nsVFB.JsonLoader.prototype.jsonLoaderController.prototype.generateFormByBusiness
                 $["notify"](this_.$scope_["text"]["Loader"]["Notify"]["CreateJson_Error"] + status, {"className": "error", "autoHideDelay": oVFB.TimeNotify_});
             }
         });
-
-//        this.$http_({
-//            url: url,
-//            method: 'POST',
-//            data: {
-//                'fields': sFieldsToUse,
-//                'label': afieldsLabel
-//            }
-//        }).success(function () {
-//            this_.requestToJson();
-//        }).error(function () {
-//            $["notify"](this_.$scope_["text"]["Loader"]["Notify"]["CreateJson_Error"] + status, {"className": "error", "autoHideDelay": oVFB.TimeNotify_});
-//        });
     }
 };
 
diff --git a/client/javascript/externs/studio/lang/lang-en.json b/client/javascript/externs/studio/lang/lang-en.json
index f33be9b3..b6d34b37 100755
--- a/client/javascript/externs/studio/lang/lang-en.json
+++ b/client/javascript/externs/studio/lang/lang-en.json
@@ -10,6 +10,8 @@
         "WabState": "State",
         "Validate": "Validate",
         "Cancel": "Cancel",
+        "GenerateForm": "Generate form",
+        "CreateEmptyForm": "Create empty form",
         "AddTab": "Add tab",
         "EditTab": "Edit",
         "RemoveTab": "Remove",
@@ -34,6 +36,7 @@
                 "Button_gtf": "FME generated form"
             },
             "Published": {
+                "DeletePublishedForm": "Delete published form",
                 "Button": "Used form",
                 "Button_gtf": "Used form"
             },
@@ -42,7 +45,8 @@
                 "Reload": "Reload files from server",
                 "Publish": "Publish the custom form",
                 "Reset": "Replace the custom form by the default form",
-                "Button": "Modification used form"
+                "Button": "Modification used form",
+                "Delete_JS": "Remove JavaScript"
             }
         },
         "Form": {
@@ -87,6 +91,10 @@
             "ProblemId": "ID problem, try again or contact an admin",
             "Reset": "Was reset",
             "Reset_Error": "Error while resetting : ",
+            "Delete": "Le formulaire a été supprimé",
+            "Delete_Error": "Erreur lors de la suppression du formulaire : ",
+            "Delete_JS": "JavaScript file deleted",
+            "Delete_JS_Error": "Erorr while deleting JavaScript file : ",
             "Publish": " Has been published",
             "PublishAndSave": " Has been published and saved",
             "Publish_Error": "Error while publishing : ",
diff --git a/client/javascript/externs/studio/lang/lang-fr.json b/client/javascript/externs/studio/lang/lang-fr.json
index 43a99c1e..ddaad289 100755
--- a/client/javascript/externs/studio/lang/lang-fr.json
+++ b/client/javascript/externs/studio/lang/lang-fr.json
@@ -10,6 +10,8 @@
         "WabState": "État wab",
         "Validate": "Valider",
         "Cancel": "Annuler",
+        "GenerateForm": "Générer un formulaire",
+        "CreateEmptyForm": "Créer un formulaire vide",
         "AddTab": "Ajouter un onglet",
         "EditTab": "Éditer",
         "RemoveTab": "Supprimer",
@@ -34,6 +36,7 @@
                 "Button_gtf": "Afficher le formulaire par défaut"
             },
             "Published": {
+                "DeletePublishedForm": "Supprimer le formulaire publié",
                 "Button": "Afficher le formulaire par publié",
                 "Button_gtf": "Afficher le formulaire par publié"
             },
@@ -44,7 +47,8 @@
                 "Reset": "Remplacer le formulaire personnalisé par le formulaire par défaut",
                 "ResetWab": "Regénérer le formulaire depuis la base",
                 "Button": "Afficher le formulaire par personnalisé",
-                "Button_gtf": "Afficher le formulaire par personnalisé"
+                "Button_gtf": "Afficher le formulaire par personnalisé",
+                "Delete_JS": "Supprimer la partie JavaScript du formulaire"
             }
         },
         "Form": {
@@ -89,6 +93,10 @@
             "ProblemId": "Problème d'ID, réessayer ou contacter un administrateur",
             "Reset": " a été réinitialisé",
             "Reset_Error": "Erreur lors de la réinitialisation : ",
+            "Delete": "Le formulaire a été supprimé",
+            "Delete_Error": "Erreur lors de la suppression du formulaire : ",
+            "Delete_JS": "Le fichier JavaScript a été supprimé",
+            "Delete_JS_Error": "Erreur lors de la suppression du fichier JavaScript : ",
             "Publish": " a été publié",
             "PublishAndSave": " a été publié et sauvegardé",
             "Publish_Error": "Erreur lors de la publication : ",
diff --git a/client/javascript/externs/studio/less/studio.less b/client/javascript/externs/studio/less/studio.less
index 39431d7e..25844881 100755
--- a/client/javascript/externs/studio/less/studio.less
+++ b/client/javascript/externs/studio/less/studio.less
@@ -3,7 +3,7 @@ To change this license header, choose License Headers in Project Properties.
 To change this template file, choose Tools | Templates
 and open the template in the editor.
 */
-/* 
+/*
     Created on : 5 janv. 2016, 12:08:09
     Author     : a_borghi
 */
@@ -23,7 +23,7 @@ and open the template in the editor.
 //@import (less) '../css/lib/bootstrap/css/bootstrap.css';
 
 
-//définit la taille de la fenêtre 
+//définit la taille de la fenêtre
 .app_window{
     /*Skin scrollBar*/
     ::-webkit-scrollbar {
@@ -39,11 +39,11 @@ and open the template in the editor.
     ::-webkit-scrollbar-thumb {
         -webkit-border-radius: 10px;
         border-radius: 10px;
-        background: @studio-color-purple; 
-        -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.5); 
+        background: @studio-color-purple;
+        -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.5);
     }
     ::-webkit-scrollbar-thumb:window-inactive {
-        background: @studio-color-purple; 
+        background: @studio-color-purple;
     }
 
     input[type=number]::-webkit-outer-spin-button,
@@ -61,7 +61,7 @@ and open the template in the editor.
 
 /*Laisse une marge sous un composant*/
 .element-margin {
-    margin-bottom: 10px; 
+    margin-bottom: 10px;
 }
 
 //align un div sur la droite avec une petite marge
@@ -199,19 +199,14 @@ and open the template in the editor.
 }
 
 // rend un élément non selectable
-.unselectable { 
-    -moz-user-select: none; 
-    -khtml-user-select: none; 
-    -webkit-user-select: none; 
-    -o-user-select: none; 
-}
-
-// décalage pour les checkbox et radio 
-.checkbox_margin {
-    margin-left: 30px;
+.unselectable {
+    -moz-user-select: none;
+    -khtml-user-select: none;
+    -webkit-user-select: none;
+    -o-user-select: none;
 }
 
-// Permet à code Mirror de prendre toute la place dans la div 
+// Permet à code Mirror de prendre toute la place dans la div
 .CodeMirror {
     border: 1px solid #eee;
     height: auto;
@@ -241,7 +236,7 @@ and open the template in the editor.
 }
 
 .invalid_input{
-    background-color: rgba(255,0,0,0.5); 
+    background-color: rgba(255,0,0,0.5);
 }
 
 /*th, td{
@@ -343,15 +338,6 @@ and open the template in the editor.
     font-size:11px
 }
 
-.checkbox label::before, .checkbox label::after{
-    width:13px;
-    height: 13px;
-}
-
-.checkbox {
-    padding-left: 12px;
-}
-
 .collapser-form-wab-modal{
     font-size: 40px;
     padding-top: 10px;
@@ -359,8 +345,8 @@ and open the template in the editor.
 }
 
 .transition-form-wab-collapser{
-    transition: width 0.5s; 
-    //transition: display 1s; 
+    transition: width 0.5s;
+    //transition: display 1s;
 }
 .form-tools-tree-container{
     overflow-y: auto;
@@ -381,4 +367,4 @@ and open the template in the editor.
     background-color: initial;
     top: initial;
     //border: initial;
-}
\ No newline at end of file
+}
diff --git a/client/javascript/externs/studio/templates/JsonLoader.html b/client/javascript/externs/studio/templates/JsonLoader.html
index f5b18f1b..6e320cda 100755
--- a/client/javascript/externs/studio/templates/JsonLoader.html
+++ b/client/javascript/externs/studio/templates/JsonLoader.html
@@ -1,8 +1,4 @@
 <div class="panel panel-veremes" id="FilesURL">
-    <!--    <div class="panel-heading unselectable" ng-click="ctrl.resize()">{{::ctrl.text.Title}}
-            <span ng-if="collapsed" id="colapse_uploader_icon" class="fa fa-angle-right fa-lg" style="float:right"></span>
-            <span ng-if="!collapsed" id="colapse_uploader_icon" class="fa fa-angle-down fa-lg" style="float:right"></span>
-        </div>-->
     <div class="panel-heading unselectable">
         <!--Fichier-->
         <div class="btn-group dropdown margin-right-10">
@@ -50,6 +46,24 @@
                         {{::ctrl.text.InfoBulle.Perso.Publish}}
                     </a>
                 </li>
+                <li ng-hide="ctrl.buttonHide"
+                    ng-show="(FormSelected === 'Perso' || FormSelected === 'Published') && ctrl.applicationName === 'vmap'">
+                    <a title="{{::ctrl.text.InfoBulle.Published.Delete}}"
+                       href="javascript:void(0);"
+                       ng-click="ctrl.deletePublishedForm()">
+                        <span class="fa icon-trash" aria-hidden="true"></span>
+                        {{::ctrl.text.InfoBulle.Published.DeletePublishedForm}}
+                    </a>
+                </li>
+                <li ng-hide="ctrl.buttonHide"
+                    ng-show="(FormSelected === 'Perso' || FormSelected === 'Published') && ctrl.applicationName === 'vmap'">
+                    <a title="{{::ctrl.text.InfoBulle.Perso.Delete_JS}}"
+                       href="javascript:void(0);"
+                       ng-click="ctrl.deleteJS()">
+                        <span class="fa icon-trash" aria-hidden="true"></span>
+                        {{::ctrl.text.InfoBulle.Perso.Delete_JS}}
+                    </a>
+                </li>
                 <li ng-hide="ctrl.buttonHide" ng-show="FormSelected === 'Perso'">
                     <a title="{{::ctrl.text.InfoBulle.Perso.Reset}}"
                        href="javascript:void(0);"
diff --git a/client/less/main.less b/client/less/main.less
index d567b91f..56042ea6 100644
--- a/client/less/main.less
+++ b/client/less/main.less
@@ -1046,3 +1046,24 @@ div[data-app-html-form]>div[app-form-reader]>.modal>.modal-dialog{
 /*@supports (-ms-accelerator:true) and (not (color:unset)) {
   .selector { property:value; }
 }*/
+
+.checkbox {
+    padding-left: 12px;
+}
+
+.checkbox_margin {
+    margin-left: 30px;
+}
+
+.checkbox-inline label::before{
+    top: 3px;
+    left: 1px
+}
+.checkbox-inline label::after{
+    top: 2px;
+}
+
+.checkbox label::before, .checkbox label::after{
+    width:13px;
+    height: 13px;
+}
diff --git a/vas/sql/sqlQueries.xml b/vas/sql/sqlQueries.xml
index 4e745ccc..15c2ea3f 100644
--- a/vas/sql/sqlQueries.xml
+++ b/vas/sql/sqlQueries.xml
@@ -67,7 +67,7 @@
 				ALTER TABLE v_user OWNER TO u_vitis;
 				CREATE VIEW v_user_group AS SELECT user_group.group_id,    user_group.user_id   FROM ((user_group     LEFT JOIN "user" ON ((user_group.user_id = "user".user_id)))     LEFT JOIN "group" ON (("group".group_id = user_group.group_id)))  WHERE ((("user".login)::name)::text = ("current_user"())::text);
 				ALTER TABLE v_user_group OWNER TO u_vitis;
-				CREATE TABLE version (    version character varying(10) NOT NULL,    build integer NOT NULL,    date timestamp with time zone NOT NULL,    active boolean);
+				CREATE TABLE version (    version character varying(100) NOT NULL,    build integer NOT NULL,    date timestamp with time zone NOT NULL,    active boolean);
 				ALTER TABLE version OWNER TO u_vitis;
 				CREATE TABLE vm_application (    name character varying(100) NOT NULL);
 				ALTER TABLE vm_application OWNER TO u_vitis;
-- 
GitLab