diff --git a/vmap/client/modules/vm4ms/CHANGE_LOG.txt b/vmap/client/modules/vm4ms/CHANGE_LOG.txt
new file mode 100755
index 0000000000000000000000000000000000000000..98d7e0f16e3048febd786e47e0972cd4166928c0
--- /dev/null
+++ b/vmap/client/modules/vm4ms/CHANGE_LOG.txt
@@ -0,0 +1,8 @@
+
+              +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+              +                                                                                   +
+              +             			 VEREMES - vm4ms change log 	            		      +
+              +                                                                                   +
+              +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+b21193|RELEASE	    |vm4ms|	Version 2017.01.00
\ No newline at end of file
diff --git a/vmap/client/modules/vm4ms/_install/dependency.xml b/vmap/client/modules/vm4ms/_install/dependency.xml
new file mode 100755
index 0000000000000000000000000000000000000000..d0d0e9f177b90c1d4bc7480f2c9eeceb82912d67
--- /dev/null
+++ b/vmap/client/modules/vm4ms/_install/dependency.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Module vMap -->
+<installer>
+	<dependenciesCollection>
+		<dependency>
+			<nature>core</nature>
+			<version>2018.05.00</version>
+		</dependency>
+		<dependency>
+			<nature>web_services</nature>
+			<name>vmap</name>
+			<version>2018.03.00</version>
+		</dependency>
+		<dependency>
+			<nature>web_services</nature>
+			<name>vm4ms</name>
+			<version>2018.03.00</version>
+		</dependency>
+	</dependenciesCollection>
+</installer>
diff --git a/vmap/client/modules/vm4ms/forms/configuration/configuration_vitis_configuration_vm4msConfig.json b/vmap/client/modules/vm4ms/forms/configuration/configuration_vitis_configuration_vm4msConfig.json
new file mode 100755
index 0000000000000000000000000000000000000000..9a349aea3271c57d61c9c8baf6b4a7a64c6326cb
--- /dev/null
+++ b/vmap/client/modules/vm4ms/forms/configuration/configuration_vitis_configuration_vm4msConfig.json
@@ -0,0 +1,126 @@
+{
+    "search": {},
+    "update": {
+        "name": "configuration_vm4ms_config_update_form",
+        "title": "",
+        "input_size": "xs",
+        "event": "updateVm4msProperties()",
+        "nb_cols": 12,
+        "rows": [
+            {
+                "fields": [
+                    {
+                        "type": "title",
+                        "label": "TITLE_PROPERTIES_CONFIGURATION_CONFIGURATION_VM4MS_CONFIG",
+                        "name":"title_properties",
+                        "nb_cols": 7
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "text",
+                        "name": "mapserver_alias",
+                        "label": "FORM_MAPSERVER_ALIAS_CONFIGURATION_CONFIGURATION_VM4MS_CONFIG",
+                        "required": true,
+                        "nb_cols": 5
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type":"select",
+                        "name":"test_wms_service",
+                        "label":"FORM_TEST_WMS_SERVICE_CONFIGURATION_CONFIGURATION_VM4MS_CONFIG",
+                        "nb_cols":3,
+                        "web_service":{
+                            "ressource_id":"vm4ms/publicwmsservices",
+                            "id_key":"wmsservice_id",
+                            "label_key":"wmsservice_id",
+                            "parameters":{
+                                    "order_by":"wmsservice_id"
+                            }
+                        },
+                        "required": true
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"codemirror",
+                        "name":"test_wms_service_default_content",
+                        "label":"FORM_TEST_WMS_SERVICE_DEFAULT_CONTENT_CONFIGURATION_CONFIGURATION_VM4MS_CONFIG",
+                        "nb_cols":12,
+                        "codemirrorOptions":{
+                            "lineSeparator": "<return>",
+                            "runnable":true,
+                            "lineNumbers":true,
+                            "matchBrackets":true,
+                            "mode":"map",
+                            "indentUnit":4,
+                            "indentWithTabs":true,
+                            "enterMode":"keep",
+                            "tabMode":"shift",
+                            "appHeight":"30%"
+                        }
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"codemirror",
+                        "name":"getFeatureInfo_default_content",
+                        "label":"FORM_GETFEATUREINFO_DEFAULT_CONTENT_CONFIGURATION_CONFIGURATION_VM4MS_CONFIG",
+                        "nb_cols":12,
+                        "codemirrorOptions":{
+                            "lineSeparator": "<return>",
+                            "runnable":true,
+                            "lineNumbers":true,
+                            "matchBrackets":true,
+                            "mode":"htmlmixed",
+                            "indentUnit":4,
+                            "indentWithTabs":true,
+                            "enterMode":"keep",
+                            "tabMode":"shift",
+                            "appHeight":"30%"
+                        }
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "text",
+                        "name": "datadir",
+                        "label": "FORM_DATADIR_CONFIGURATION_CONFIGURATION_VM4MS_CONFIG",
+                        "required": true,
+                        "nb_cols": 5
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "button",
+                        "class": "btn-ungroup btn-group-sm",
+                        "nb_cols": 7,
+                        "buttons": [
+                            {
+                                "type": "submit",
+                                "name": "form_submit",
+                                "label": "FORM_UPDATE",
+                                "class": "btn-primary"
+                            }
+                        ]
+                    }
+                ]
+            }
+        ]
+    },
+    "insert": {},
+    "display": {}
+}
diff --git a/vmap/client/modules/vm4ms/forms/vm4ms/vm4ms_vm4ms_connection.json b/vmap/client/modules/vm4ms/forms/vm4ms/vm4ms_vm4ms_connection.json
new file mode 100755
index 0000000000000000000000000000000000000000..e176aaa57d8b63133136acd0724cfac81703c78b
--- /dev/null
+++ b/vmap/client/modules/vm4ms/forms/vm4ms/vm4ms_vm4ms_connection.json
@@ -0,0 +1,520 @@
+{
+    "search": {
+        "name": "vm4ms_connection_search_form",
+        "title": "",
+        "input_size": "xxs",
+        "nb_cols": 12,
+        "rows": [
+            {
+                "fields": [
+                    {
+                        "type": "text",
+                        "name": "name",
+                        "label": "FORM_NAME_VM4MS_VM4MS_CONNECTION",
+                        "nb_cols": 3
+                    },
+                    {
+                        "type": "radio",
+                        "name": "private",
+                        "label": "FORM_PRIVATE_VM4MS_VM4MS_CONNECTION",
+                        "options": {
+                            "choices": [{
+                                    "label": "FORM_PRIVATE_YES_VM4MS_VM4MS_CONNECTION",
+                                    "value": true
+                                },
+                                {
+                                    "label": "FORM_PRIVATE_NO_VM4MS_VM4MS_CONNECTION",
+                                    "value": false
+                                }]
+                        },
+                        "inline": true,
+                        "nb_cols": 3
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "text",
+                        "name": "server",
+                        "label": "FORM_SERVER_VM4MS_VM4MS_CONNECTION",
+                        "nb_cols": 3
+                    },
+                    {
+                        "type": "number",
+                        "name": "port",
+                        "label": "FORM_PORT_VM4MS_VM4MS_CONNECTION",
+                        "nb_cols": 3
+                    },
+                    {
+                        "type": "text",
+                        "name": "database",
+                        "label": "FORM_DATABASE_VM4MS_VM4MS_CONNECTION",
+                        "nb_cols": 3
+                    },
+                    {
+                        "type": "text",
+                        "name": "user",
+                        "label": "FORM_USER_VM4MS_VM4MS_CONNECTION",
+                        "nb_cols": 3
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "button",
+                        "class": "btn-ungroup btn-group-xs",
+                        "nb_cols": 12,
+                        "buttons": [
+                            {
+                                "type": "button",
+                                "name": "search",
+                                "label": "FORM_SEARCH_BUTTON",
+                                "class": "btn-primary",
+                                "event": "setGridFilter()"
+                            },
+                            {
+                                "type": "reset",
+                                "name": "reset",
+                                "label": "FORM_RESET_BUTTON",
+                                "class": "btn-primary",
+                                "event": "resetGridFilter()"
+                            }
+                        ]
+                    }
+                ]
+            }
+        ]
+    },
+    "update": {
+        "name": "vm4ms_connection_update_form",
+        "title": "FORM_TITLE_VM4MS_VM4MS_CONNECTION",
+        "input_size": "xs",
+        "initEvent": "initVm4msConnectionForm()",
+        "beforeEvent": "beforeSendingVm4msConnectionForm()",
+        "event": "sendSimpleForm()",
+        "nb_cols": 12,
+        "rows": [
+            {
+                "fields": [
+                    {
+                        "type": "label",
+                        "name": "connection_id",
+                        "label": "FORM_CONNECTION_ID_VM4MS_VM4MS_CONNECTION",
+                        "nb_cols": 4
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "text",
+                        "name": "name",
+                        "label": "FORM_NAME_VM4MS_VM4MS_CONNECTION",
+                        "nb_cols": 4,
+                        "visible": true
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "text",
+                        "name": "server",
+                        "label": "FORM_SERVER_VM4MS_VM4MS_CONNECTION",
+                        "nb_cols": 4,
+                        "visible": true
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "text",
+                        "name": "port",
+                        "label": "FORM_PORT_VM4MS_VM4MS_CONNECTION",
+                        "nb_cols": 4,
+                        "visible": true
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "text",
+                        "name": "public_database",
+                        "label": "FORM_DATABASE_VM4MS_VM4MS_CONNECTION",
+                        "nb_cols": 4,
+                        "visible": true
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "select",
+                        "name": "private_database",
+                        "label": "FORM_DATABASE_VM4MS_VM4MS_CONNECTION",
+                        "nb_cols": 3,
+                        "web_service": {
+                            "ressource_id": "vitis/genericquerys",
+                            "id_key": "datname",
+                            "label_key": "datname",
+                            "parameters": {
+                                "order_by": "datname",
+                                "schema": "pg_catalog",
+                                "table": "pg_database",
+                                "sort_order": "ASC",
+                                "attributs": "datname",
+                                "distinct": true,
+                                "filter": {
+                                    "relation": "AND",
+                                    "operators": [{
+                                            "column": "datistemplate",
+                                            "compare_operator": "=",
+                                            "value": false
+                                        }, {
+                                            "column": "datname",
+                                            "compare_operator": "<>",
+                                            "value": "postgres"
+                                        }]
+                                }
+                            }
+                        },
+                        "required": true,
+                        "visible": true
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "hidden",
+                        "name": "database",
+                        "nb_cols": 1
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "text",
+                        "name": "user",
+                        "label": "FORM_USER_VM4MS_VM4MS_CONNECTION",
+                        "nb_cols": 4,
+                        "visible": true
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "text",
+                        "name": "password",
+                        "label": "FORM_PASSWORD_VM4MS_VM4MS_CONNECTION",
+                        "tooltip": {
+                            "content": "FORM_PASSWORD_TOOLTIP_CONTENT_VM4MS_VM4MS_PRIVATE_WMS_SERVICE"
+                        },
+                        "nb_cols": 4,
+                        "visible": true
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "button",
+                        "class": "btn-ungroup btn-group-sm",
+                        "nb_cols": 12,
+                        "buttons": [
+                            {
+                                "type": "submit",
+                                "name": "form_submit",
+                                "label": "FORM_UPDATE",
+                                "class": "btn-primary"
+                            },
+                            {
+                                "type": "button",
+                                "name": "return_list",
+                                "label": "FORM_RETURN_LIST",
+                                "class": "btn-primary",
+                                "event": "setMode(\"search\")"
+                            }
+                        ]
+                    }
+                ]
+            }
+        ]
+    },
+    "insert": {
+        "name": "vm4ms_connection_insert_form",
+        "title": "FORM_TITLE_VM4MS_VM4MS_CONNECTION",
+        "input_size": "xs",
+        "beforeEvent": "beforeSendingVm4msConnectionForm()",
+        "initEvent": "initVm4msConnectionForm()",
+        "event": "sendSimpleForm()",
+        "afterEvent": "editSectionForm()",
+        "nb_cols": 12,
+        "rows": [
+            {
+                "fields": [
+                    {
+                        "type": "radio",
+                        "name": "private",
+                        "label": "FORM_PRIVATE_VM4MS_VM4MS_CONNECTION",
+                        "options": {
+                            "choices": [{
+                                    "label": "FORM_PRIVATE_YES_VM4MS_VM4MS_CONNECTION",
+                                    "value": true
+                                },
+                                {
+                                    "label": "FORM_PRIVATE_NO_VM4MS_VM4MS_CONNECTION",
+                                    "value": false
+                                }]
+                        },
+                        "default_value": false,
+                        "nb_cols": 12
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "text",
+                        "name": "name",
+                        "label": "FORM_NAME_VM4MS_VM4MS_CONNECTION",
+                        "required": true,
+                        "nb_cols": 4,
+                        "visible": true
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "text",
+                        "name": "server",
+                        "label": "FORM_SERVER_VM4MS_VM4MS_CONNECTION",
+                        "nb_cols": 4,
+                        "visible": true
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "text",
+                        "name": "port",
+                        "label": "FORM_PORT_VM4MS_VM4MS_CONNECTION",
+                        "nb_cols": 4,
+                        "visible": true
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "text",
+                        "name": "public_database",
+                        "label": "FORM_DATABASE_VM4MS_VM4MS_CONNECTION",
+                        "nb_cols": 4,
+                        "visible": true
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "select",
+                        "name": "private_database",
+                        "label": "FORM_DATABASE_VM4MS_VM4MS_CONNECTION",
+                        "nb_cols": 3,
+                        "web_service": {
+                            "ressource_id": "vitis/genericquerys",
+                            "id_key": "datname",
+                            "label_key": "datname",
+                            "parameters": {
+                                "order_by": "datname",
+                                "schema": "pg_catalog",
+                                "table": "pg_database",
+                                "sort_order": "ASC",
+                                "attributs": "datname",
+                                "distinct": true,
+                                "filter": {
+                                    "relation": "AND",
+                                    "operators": [{
+                                            "column": "datistemplate",
+                                            "compare_operator": "=",
+                                            "value": false
+                                        }, {
+                                            "column": "datname",
+                                            "compare_operator": "<>",
+                                            "value": "postgres"
+                                        }]
+                                }
+                            }
+                        },
+                        "required": true,
+                        "visible": true
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "hidden",
+                        "name": "database",
+                        "nb_cols": 1
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "text",
+                        "name": "user",
+                        "label": "FORM_USER_VM4MS_VM4MS_CONNECTION",
+                        "nb_cols": 4,
+                        "visible": true
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "text",
+                        "name": "password",
+                        "label": "FORM_PASSWORD_VM4MS_VM4MS_CONNECTION",
+                        "tooltip": {
+                            "content": "FORM_PASSWORD_TOOLTIP_CONTENT_VM4MS_VM4MS_PRIVATE_WMS_SERVICE"
+                        },
+                        "nb_cols": 4,
+                        "visible": true
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "button",
+                        "class": "btn-ungroup btn-group-sm",
+                        "nb_cols": 12,
+                        "buttons": [
+                            {
+                                "type": "submit",
+                                "name": "form_submit",
+                                "label": "FORM_CREATE",
+                                "class": "btn-primary"
+                            },
+                            {
+                                "type": "button",
+                                "name": "return_list",
+                                "label": "FORM_RETURN_LIST",
+                                "class": "btn-primary",
+                                "event": "setMode(\"search\")"
+                            }
+                        ]
+                    }
+                ]
+            }
+        ]
+    },
+    "display": {
+        "name": "vm4ms_connection_display_form",
+        "title": "FORM_TITLE_VM4MS_VM4MS_CONNECTION",
+        "input_size": "xs",
+        "initEvent": "initVm4msConnectionForm()",
+        "nb_cols": 12,
+        "rows": [
+            {
+                "fields": [
+                    {
+                        "type": "label",
+                        "name": "connection_id",
+                        "label": "FORM_CONNECTION_ID_VM4MS_VM4MS_CONNECTION",
+                        "nb_cols": 6
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "label",
+                        "name": "name",
+                        "label": "FORM_NAME_VM4MS_VM4MS_CONNECTION",
+                        "nb_cols": 3
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "label",
+                        "name": "server",
+                        "label": "FORM_SERVER_VM4MS_VM4MS_CONNECTION",
+                        "nb_cols": 4
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "label",
+                        "name": "port",
+                        "label": "FORM_PORT_VM4MS_VM4MS_CONNECTION",
+                        "nb_cols": 4
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "label",
+                        "name": "database",
+                        "label": "FORM_DATABASE_VM4MS_VM4MS_CONNECTION",
+                        "nb_cols": 4
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "label",
+                        "name": "user",
+                        "label": "FORM_USER_VM4MS_VM4MS_CONNECTION",
+                        "nb_cols": 4
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "label",
+                        "name": "password",
+                        "label": "FORM_PASSWORD_VM4MS_VM4MS_CONNECTION",
+                        "nb_cols": 4
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "button",
+                        "class": "btn-ungroup btn-group-sm",
+                        "nb_cols": 12,
+                        "buttons": [
+                            {
+                                "type": "button",
+                                "name": "return_list",
+                                "label": "FORM_RETURN_LIST",
+                                "class": "btn-primary",
+                                "event": "setMode(\"search\")"
+                            }
+                        ]
+                    }
+                ]
+            }
+        ]
+    }
+}
\ No newline at end of file
diff --git a/vmap/client/modules/vm4ms/forms/vm4ms/vm4ms_vm4ms_coordsys.json b/vmap/client/modules/vm4ms/forms/vm4ms/vm4ms_vm4ms_coordsys.json
new file mode 100755
index 0000000000000000000000000000000000000000..6a00de981d0fb2c3fb78608e53855022a7e6f311
--- /dev/null
+++ b/vmap/client/modules/vm4ms/forms/vm4ms/vm4ms_vm4ms_coordsys.json
@@ -0,0 +1,323 @@
+{
+    "search":{
+        "name":"vm4ms_coordsys_search_form",
+        "title":"",
+        "input_size":"xxs",
+        "nb_cols":12,
+        "rows":[
+            {
+                "fields":[
+                    {
+                        "type":"number",
+                        "name":"coordsys_id",
+                        "label":"FORM_SRID_VM4MS_VM4MS_COORDSYS",
+                        "nb_cols":3
+                    },
+                    {
+                        "type":"text",
+                        "name":"label",
+                        "label":"FORM_LABEL_VM4MS_VM4MS_COORDSYS",
+                        "nb_cols":3
+                    },
+                    {
+                        "type":"text",
+                        "name":"epsg",
+                        "label":"FORM_EPSG_VM4MS_VM4MS_COORDSYS",
+                        "nb_cols":3
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"button",
+                        "class":"btn-ungroup btn-group-xs",
+                        "nb_cols":12,
+                        "buttons":[
+                            {
+                                "type":"button",
+                                "name":"search",
+                                "label":"FORM_SEARCH_BUTTON",
+                                "class":"btn-primary",
+                                "event":"setGridFilter()"
+                            },
+                            {
+                                "type":"reset",
+                                "name":"reset",
+                                "label":"FORM_RESET_BUTTON",
+                                "class":"btn-primary",
+                                "event":"resetGridFilter()"
+                            }
+                        ]
+                    }
+                ]
+            }
+        ]
+    },
+    "update":{
+        "name":"vm4ms_coordsys_update_form",
+        "title":"FORM_TITLE_VM4MS_VM4MS_COORDSYS",
+        "input_size":"xs",
+        "event":"sendSimpleForm()",
+        "nb_cols":12,
+        "rows":[
+            {
+                "fields":[
+                    {
+                        "type":"number",
+                        "name":"coordsys_id",
+                        "label":"FORM_SRID_VM4MS_VM4MS_COORDSYS",
+                        "required":true,
+                        "nb_cols":6
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"text",
+                        "name":"label",
+                        "label":"FORM_LABEL_VM4MS_VM4MS_COORDSYS",
+                        "nb_cols":4
+                    },
+                    {
+                        "type":"text",
+                        "name":"epsg",
+                        "label":"FORM_EPSG_VM4MS_VM4MS_COORDSYS",
+                        "nb_cols":4
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"text",
+                        "name":"epsg_definition",
+                        "label":"FORM_EPSG_DEFINITION_VM4MS_VM4MS_COORDSYS",
+                        "nb_cols":12,
+                        "tooltip": {
+                            "title": "",
+                            "content": "FORM_EPSG_DEFINITION_DESCRIPTION_VM4MS_VM4MS_COORDSYS",
+                            "container": "body"
+                        }
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"codemirror",
+                        "name":"definition",
+                        "label":"FORM_DEFINITION_VM4MS_VM4MS_COORDSYS",
+                        "nb_cols":12,
+                        "codemirrorOptions":{
+                            "runnable":true,
+                            "lineNumbers":true,
+                            "matchBrackets":true,
+                            "mode":"map",
+                            "indentUnit":4,
+                            "indentWithTabs":true,
+                            "enterMode":"keep",
+                            "tabMode":"shift",
+                            "appHeight":"30%"
+                        }
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"button",
+                        "class":"btn-ungroup btn-group-sm",
+                        "nb_cols":12,
+                        "buttons":[
+                            {
+                                "type":"submit",
+                                "name":"form_submit",
+                                "label":"FORM_UPDATE",
+                                "class":"btn-primary"
+                            },
+                            {
+                                "type":"button",
+                                "name":"return_list",
+                                "label":"FORM_RETURN_LIST",
+                                "class":"btn-primary",
+                                "event":"setMode(\"search\")"
+                            }
+                        ]
+                    }
+                ]
+            }
+        ]
+    },
+    "insert":{
+        "name":"vm4ms_coordsys_insert_form",
+        "title":"FORM_TITLE_VM4MS_VM4MS_COORDSYS",
+        "input_size":"xs",
+        "event":"sendSimpleForm()",
+        "afterEvent":"editSectionForm()",
+        "nb_cols":12,
+        "rows":[
+            {
+                "fields":[
+                    {
+                        "type":"number",
+                        "name":"coordsys_id",
+                        "label":"FORM_SRID_VM4MS_VM4MS_COORDSYS",
+                        "required":true,
+                        "nb_cols":4
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"text",
+                        "name":"label",
+                        "label":"FORM_LABEL_VM4MS_VM4MS_COORDSYS",
+                        "nb_cols":4
+                    },
+                    {
+                        "type":"text",
+                        "name":"epsg",
+                        "label":"FORM_EPSG_VM4MS_VM4MS_COORDSYS",
+                        "nb_cols":4
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"text",
+                        "name":"epsg_definition",
+                        "label":"FORM_EPSG_DEFINITION_VM4MS_VM4MS_COORDSYS",
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"codemirror",
+                        "name":"definition",
+                        "label":"FORM_DEFINITION_VM4MS_VM4MS_COORDSYS",
+                        "nb_cols":12,
+                        "codemirrorOptions":{
+                            "runnable":true,
+                            "lineNumbers":true,
+                            "matchBrackets":true,
+                            "mode":"map",
+                            "indentUnit":4,
+                            "indentWithTabs":true,
+                            "enterMode":"keep",
+                            "tabMode":"shift",
+                            "appHeight":"30%"
+                        }
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"button",
+                        "class":"btn-ungroup btn-group-sm",
+                        "nb_cols":12,
+                        "buttons":[
+                            {
+                                "type":"submit",
+                                "name":"form_submit",
+                                "label":"FORM_CREATE",
+                                "class":"btn-primary"
+                            },
+                            {
+                                "type":"button",
+                                "name":"return_list",
+                                "label":"FORM_RETURN_LIST",
+                                "class":"btn-primary",
+                                "event":"setMode(\"search\")"
+                            }
+                        ]
+                    }
+                ]
+            }
+        ]
+    },
+    "display":{
+        "name":"vm4ms_coordsys_display_form",
+        "title":"FORM_TITLE_VM4MS_VM4MS_COORDSYS",
+        "input_size":"xs",
+        "nb_cols":12,
+        "rows":[
+            {
+                "fields":[
+                    {
+                        "type":"label",
+                        "name":"coordsys_id",
+                        "label":"FORM_SRID_VM4MS_VM4MS_COORDSYS",
+                        "nb_cols":6
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"label",
+                        "name":"epsg",
+                        "label":"FORM_EPSG_VM4MS_VM4MS_COORDSYS",
+                        "nb_cols":6
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"label",
+                        "name":"epsg_definition",
+                        "label":"FORM_EPSG_DEFINITION_VM4MS_VM4MS_COORDSYS",
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"codemirror",
+                        "name":"definition",
+                        "label":"FORM_DEFINITION_VM4MS_VM4MS_COORDSYS",
+                        "nb_cols":12,
+                        "codemirrorOptions":{
+                            "runnable":true,
+                            "lineNumbers":true,
+                            "matchBrackets":true,
+                            "mode":"map",
+                            "indentUnit":4,
+                            "indentWithTabs":true,
+                            "enterMode":"keep",
+                            "tabMode":"shift",
+                            "appHeight":"30%",
+                            "readOnly":"true"
+                        }
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"button",
+                        "class":"btn-ungroup btn-group-sm",
+                        "nb_cols":12,
+                        "buttons":[
+                            {
+                                "type":"button",
+                                "name":"return_list",
+                                "label":"FORM_RETURN_LIST",
+                                "class":"btn-primary",
+                                "event":"setMode(\"search\")"
+                            }
+                        ]
+                    }
+                ]
+            }
+        ]
+    }
+}
\ No newline at end of file
diff --git a/vmap/client/modules/vm4ms/forms/vm4ms/vm4ms_vm4ms_layer.json b/vmap/client/modules/vm4ms/forms/vm4ms/vm4ms_vm4ms_layer.json
new file mode 100755
index 0000000000000000000000000000000000000000..7e5bddb7ca5704c47a41a78ac751273bdb20696a
--- /dev/null
+++ b/vmap/client/modules/vm4ms/forms/vm4ms/vm4ms_vm4ms_layer.json
@@ -0,0 +1,928 @@
+{
+    "search": {
+        "name": "vm4ms_layer_search_form",
+        "title": "",
+        "input_size": "xxs",
+        "nb_cols": 12,
+        "rows": [
+            {
+                "fields": [
+                    {
+                        "type": "text",
+                        "name": "name",
+                        "label": "FORM_NAME_VM4MS_VM4MS_LAYER",
+                        "nb_cols": 3
+                    },
+                    {
+                        "type": "text",
+                        "name": "title",
+                        "label": "FORM_LAYER_TITLE_VM4MS_VM4MS_LAYER",
+                        "nb_cols": 3
+                    },
+                    {
+                        "type": "select",
+                        "name": "coordsys_id",
+                        "label": "FORM_COORDSYS_ID_VM4MS_VM4MS_LAYER",
+                        "nb_cols": 3,
+                        "web_service": {
+                            "ressource_id": "vm4ms/coordinatesystems",
+                            "id_key": "coordsys_id",
+                            "label_key": "label",
+                            "parameters": {
+                                "order_by": "label"
+                            }
+                        }
+                    },
+                    {
+                        "type": "select",
+                        "name": "source_id",
+                        "label": "FORM_SOURCE_ID_VM4MS_VM4MS_LAYER",
+                        "nb_cols": 3,
+                        "web_service": {
+                            "ressource_id": "vm4ms/sources",
+                            "id_key": "source_id",
+                            "label_key": "name",
+                            "parameters": {
+                                "order_by": "name"
+                            }
+                        }
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "select",
+                        "name": "connection_id",
+                        "label": "FORM_CONNECTION_ID_VM4MS_VM4MS_LAYER",
+                        "nb_cols": 3,
+                        "web_service": {
+                            "ressource_id": "vm4ms/layerconnections",
+                            "id_key": "connection_id",
+                            "label_key": "name",
+                            "parameters": {
+                                "order_by": "name"
+                            }
+                        }
+                    },
+                    {
+                        "type": "select",
+                        "name": "ms_layertype_id",
+                        "label": "FORM_LAYERTYPE_ID_VM4MS_VM4MS_LAYER",
+                        "nb_cols": 3,
+                        "web_service": {
+                            "ressource_id": "vm4ms/layertypes",
+                            "id_key": "ms_layertype_id",
+                            "label_key": "ms_layertype_id",
+                            "parameters": {
+                                "order_by": "ms_layertype_id"
+                            }
+                        }
+                    },
+                    {
+                        "type": "text",
+                        "name": "definition",
+                        "label": "FORM_DEFINITION_VM4MS_VM4MS_LAYER",
+                        "nb_cols": 3
+                    },
+                    {
+                        "type": "radio",
+                        "name": "active",
+                        "label": "FORM_ACTIVE_VM4MS_VM4MS_LAYER",
+                        "options": {
+                            "choices": [{
+                                    "label": "FORM_ACTIVE_YES_VM4MS_VM4MS_LAYER",
+                                    "value": true
+                                },
+                                {
+                                    "label": "FORM_ACTIVE_NO_VM4MS_VM4MS_LAYER",
+                                    "value": false
+                                }]
+                        },
+                        "inline": true,
+                        "nb_cols": 3
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "number",
+                        "name": "opacity",
+                        "label": "FORM_OPACITY_VM4MS_VM4MS_LAYER",
+                        "pattern": "^([0-9]|[1-9][0-9]|[1][0][0])$",
+                        "nb_cols": 3
+                    },
+                    {
+                        "type": "text",
+                        "name": "tableschema",
+                        "label": "FORM_TABLESCHEMA_VM4MS_VM4MS_LAYER",
+                        "nb_cols": 3
+                    },
+                    {
+                        "type": "text",
+                        "name": "tablename",
+                        "label": "FORM_TABLENAME_VM4MS_VM4MS_LAYER",
+                        "nb_cols": 3
+                    },
+                    {
+                        "type": "text",
+                        "name": "tableidfield",
+                        "label": "FORM_TABLEIDFIELD_VM4MS_VM4MS_LAYER",
+                        "nb_cols": 3
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "select",
+                        "name": "metadata_id",
+                        "label": "FORM_METADATA_ID_VM4MS_VM4MS_LAYER",
+                        "nb_cols": 3,
+                        "web_service": {
+                            "ressource_id": "vm4ms/metadatas",
+                            "id_key": "metadata_id",
+                            "label_key": "name",
+                            "parameters": {
+                                "order_by": "name"
+                            }
+                        }
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "button",
+                        "class": "btn-ungroup btn-group-xs",
+                        "nb_cols": 12,
+                        "buttons": [
+                            {
+                                "type": "button",
+                                "name": "search",
+                                "label": "FORM_SEARCH_BUTTON",
+                                "class": "btn-primary",
+                                "event": "setGridFilter()"
+                            },
+                            {
+                                "type": "reset",
+                                "name": "reset",
+                                "label": "FORM_RESET_BUTTON",
+                                "class": "btn-primary",
+                                "event": "resetGridFilter()"
+                            }
+                        ]
+                    }
+                ]
+            }
+        ]
+    },
+    "update": {
+        "name": "vm4ms_layer_update_form",
+        "title": "FORM_TITLE_VM4MS_VM4MS_LAYER",
+        "input_size": "xs",
+        "initEvent": "initVm4msLayerForm()",
+        "beforeEvent": "beforeSendingLayerForm()",
+        "event": "sendSimpleForm()",
+        "afterEvent": "editSectionForm()",
+        "nb_cols": 12,
+        "rows": [
+            {
+                "fields": [
+                    {
+                        "type": "label",
+                        "name": "ms_layer_id",
+                        "label": "FORM_LAYER_ID_VM4MS_VM4MS_LAYER",
+                        "nb_cols": 3
+                    },
+                    {
+                        "type": "label",
+                        "name": "name",
+                        "label": "FORM_LAYER_NAME_VM4MS_VM4MS_LAYER",
+                        "nb_cols": 3
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "text",
+                        "name": "title",
+                        "label": "FORM_LAYER_TITLE_VM4MS_VM4MS_LAYER",
+                        "required": true,
+                        "tooltip": {
+                            "content":"FORM_LAYER_TITLE_TOOLTIP_CONTENT_VM4MS_VM4MS_LAYER",
+                            "width": "300px"
+                        },
+                        "nb_cols": 12
+                    }
+                ]
+            },
+            {
+                "class": "form-field-inline layer-connexion-row",
+                "fields": [
+                    {
+                        "type": "select",
+                        "name": "connection_id",
+                        "label": "FORM_CONNECTION_ID_VM4MS_VM4MS_LAYER",
+                        "nb_cols": 2,
+                        "web_service": {
+                            "ressource_id": "vm4ms/layerconnections",
+                            "id_key": "connection_id",
+                            "label_key": "name",
+                            "parameters": {
+                                "order_by": "name"
+                            }
+                        }
+                    },
+                    {
+                        "type": "editable_select",
+                        "name": "tableschema",
+                        "label": "FORM_TABLESCHEMA_VM4MS_VM4MS_LAYER",
+                        "nb_cols": 2
+                    },
+                    {
+                        "type": "button",
+                        "class": "btn-group btn-group-sm",
+                        "nb_cols": 1,
+                        "buttons": [
+                            {
+                                "type": "button",
+                                "name": "table-datalist",
+                                "label": "FORM_BTN_TABLE_VM4MS_VM4MS_LAYER",
+                                "class": "btn-primary",
+                                "event": "setLayerTableOptions()",
+                                "glyphicon": "refresh"
+                            }
+                        ]
+                    },
+                    {
+                        "type": "editable_select",
+                        "name": "tablename",
+                        "label": "FORM_TABLENAME_VM4MS_VM4MS_LAYER",
+                        "nb_cols": 2
+                    },
+                    {
+                        "type": "button",
+                        "class": "btn-group btn-group-sm",
+                        "nb_cols": 1,
+                        "buttons": [
+                            {
+                                "type": "button",
+                                "name": "id-field-datalist",
+                                "label": "FORM_BTN_IDENTIFIER_VM4MS_VM4MS_LAYER",
+                                "class": "btn-primary",
+                                "event": "setLayerIdFieldOptions()",
+                                "glyphicon": "refresh"
+                            }
+                        ]
+                    },
+                    {
+                        "type": "editable_select",
+                        "name": "tableidfield",
+                        "label": "FORM_TABLEIDFIELD_VM4MS_VM4MS_LAYER",
+                        "nb_cols": 2
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "select",
+                        "name": "ms_layertype_id",
+                        "label": "FORM_LAYERTYPE_ID_VM4MS_VM4MS_LAYER",
+                        "nb_cols": 4,
+                        "web_service": {
+                            "ressource_id": "vm4ms/layertypes",
+                            "id_key": "ms_layertype_id",
+                            "label_key": "ms_layertype_id",
+                            "parameters": {
+                                "order_by": "ms_layertype_id"
+                            }
+                        },
+                        "required": true
+                    },
+                    {
+                        "type": "select",
+                        "name": "coordsys_id",
+                        "label": "FORM_COORDSYS_ID_VM4MS_VM4MS_LAYER",
+                        "nb_cols": 4,
+                        "web_service": {
+                            "ressource_id": "vm4ms/coordinatesystems",
+                            "id_key": "coordsys_id",
+                            "label_key": "label",
+                            "parameters": {
+                                "order_by": "label"
+                            }
+                        }
+                    },
+                    {
+                        "type": "select",
+                        "name": "source_id",
+                        "label": "FORM_SOURCE_ID_VM4MS_VM4MS_LAYER",
+                        "nb_cols": 4,
+                        "web_service": {
+                            "ressource_id": "vm4ms/sources",
+                            "id_key": "source_id",
+                            "label_key": "name",
+                            "parameters": {
+                                "order_by": "name"
+                            }
+                        }
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "radio",
+                        "name": "active",
+                        "label": "FORM_ACTIVE_VM4MS_VM4MS_LAYER",
+                        "options": {
+                            "choices": [{
+                                    "label": "FORM_ACTIVE_YES_VM4MS_VM4MS_LAYER",
+                                    "value": true
+                                },
+                                {
+                                    "label": "FORM_ACTIVE_NO_VM4MS_VM4MS_LAYER",
+                                    "value": false
+                                }]
+                        },
+                        "default_value": true,
+                        "nb_cols": 3
+                    },
+                    {
+                        "type": "text",
+                        "name": "opacity",
+                        "label": "FORM_OPACITY_VM4MS_VM4MS_LAYER",
+                        "pattern": "^([0-9]|[1-9][0-9]|[1][0][0])$",
+                        "default_value": 100,
+                        "required": true,
+                        "nb_cols": 1
+                    },
+                    {
+                        "type": "select",
+                        "name": "metadata_id",
+                        "label": "FORM_METADATA_ID_VM4MS_VM4MS_LAYER",
+                        "nb_cols": 4,
+                        "web_service": {
+                            "ressource_id": "vm4ms/metadatas",
+                            "id_key": "metadata_id",
+                            "label_key": "name",
+                            "parameters": {
+                                "order_by": "name"
+                            }
+                        }
+                    },
+                    {
+                        "type": "hidden",
+                        "name": "create_ws_map_file",
+                        "default_value": "true",
+                        "nb_cols": 1
+                    },
+                    {
+                        "type": "hidden",
+                        "name": "test_layer",
+                        "default_value": false,
+                        "nb_cols": 1
+                    }
+                ]
+            },
+            {
+                "class": "form-row-layer-definition",
+                "fields": [
+                    {
+                        "type": "codemirror",
+                        "name": "definition",
+                        "label": "FORM_DEFINITION_VM4MS_VM4MS_LAYER",
+                        "nb_cols": 12,
+                        "required": true,
+                        "codemirrorOptions": {
+                            "runnable": true,
+                            "lineNumbers": true,
+                            "matchBrackets": true,
+                            "mode": "map",
+                            "indentUnit": 4,
+                            "indentWithTabs": true,
+                            "enterMode": "keep",
+                            "tabMode": "shift",
+                            "appHeight": "40%"
+                        }
+                    }
+                ]
+            },
+            {
+                "class": "form-field-inline form-row-layer-palette",
+                "fields": [
+                    {
+                        "type": "text",
+                        "name": "layer_login",
+                        "label": "FORM_LAYER_LOGIN_VM4MS_VM4MS_LAYER_DEFINITION",
+                        "nb_cols": 2
+                    },
+                    {
+                        "type": "password",
+                        "name": "layer_password",
+                        "label": "FORM_LAYER_PASSWORD_VM4MS_VM4MS_LAYER_DEFINITION",
+                        "nb_cols": 2
+                    },
+                    {
+                        "type": "button",
+                        "class": "btn-ungroup btn-group-sm vm4ms-layer-symbols-fonts-container",
+                        "nb_cols": 5,
+                        "buttons": [
+                            {
+                                "type": "button",
+                                "name": "mapserver_symbols",
+                                "label": "FORM_BTN_SYMBOLS_VM4MS_VM4MS_LAYER",
+                                "class": "btn-default",
+                                "event": "displayMapServerSymbolsModal()"
+                            },
+                            {
+                                "type": "button",
+                                "name": "mapserver_fonts",
+                                "label": "FORM_BTN_FONTS_VM4MS_VM4MS_LAYER",
+                                "class": "btn-default",
+                                "event": "displayMapServerFontsModal()"
+                            }
+                        ]
+                    }
+                ]
+            },
+            {
+                "class": "form-row-margin-top form-row-layer-btn",
+                "fields": [
+                    {
+                        "type": "button",
+                        "class": "btn-ungroup btn-group-sm",
+                        "nb_cols": 12,
+                        "buttons": [
+                            {
+                                "type": "submit",
+                                "name": "form_submit",
+                                "label": "FORM_BTN_SAVE_LAYER_VM4MS_VM4MS_LAYER",
+                                "class": "btn-primary"
+                            },
+                            {
+                                "type": "button",
+                                "name": "test_layer_btn",
+                                "label": "FORM_TEST_LAYER_VM4MS_VM4MS_LAYER",
+                                "class": "btn-primary",
+                                "event": "testVm4msLayer()"
+                            },
+                            {
+                                "type": "button",
+                                "name": "getfeatureinfo_template_layer_btn",
+                                "label": "FORM_GETFEATUREINFO_TEMPLATE_VM4MS_VM4MS_LAYER",
+                                "class": "btn-primary",
+                                "event": "editGetFeatureInfoTemplate()"
+                            },
+                            {
+                                "type": "button",
+                                "name": "clone_form",
+                                "label": "FORM_CLONE",
+                                "class": "btn-primary",
+                                "event": "cloneVm4msLayer()"
+                            },
+                            {
+                                "type": "button",
+                                "name": "return_list",
+                                "label": "FORM_RETURN_LIST",
+                                "class": "btn-primary",
+                                "event": "setMode(\"search\")"
+                            }
+                        ]
+                    }
+                ]
+            }
+        ]
+    },
+    "insert": {
+        "name": "vm4ms_layer_insert_form",
+        "title": "FORM_TITLE_VM4MS_VM4MS_LAYER",
+        "input_size": "xs",
+        "initEvent": "initVm4msLayerForm()",
+        "event": "sendSimpleForm()",
+        "afterEvent": "editSectionForm()",
+        "nb_cols": 12,
+        "rows": [
+            {
+                "fields": [
+                    {
+                        "type": "text",
+                        "name": "name",
+                        "label": "FORM_NAME_VM4MS_VM4MS_LAYER",
+                        "pattern": "[a-zA-Z0-9_]+",
+                        "required": true,
+                        "tooltip": {
+                            "content":"FORM_LAYER_NAME_TOOLTIP_CONTENT_VM4MS_VM4MS_LAYER",
+                            "width": "390px"
+                        },
+                        "nb_cols": 3
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "text",
+                        "name": "title",
+                        "label": "FORM_LAYER_TITLE_VM4MS_VM4MS_LAYER",
+                        "required": true,
+                        "tooltip": {
+                            "content":"FORM_LAYER_TITLE_TOOLTIP_CONTENT_VM4MS_VM4MS_LAYER",
+                            "width": "300px"
+                        },
+                        "nb_cols": 12
+                    }
+                ]
+            },
+            {
+                "class": "form-field-inline layer-connexion-row",
+                "fields": [
+                    {
+                        "type": "select",
+                        "name": "connection_id",
+                        "label": "FORM_CONNECTION_ID_VM4MS_VM4MS_LAYER",
+                        "nb_cols": 1,
+                        "web_service": {
+                            "ressource_id": "vm4ms/layerconnections",
+                            "id_key": "connection_id",
+                            "label_key": "name",
+                            "parameters": {
+                                "order_by": "name"
+                            }
+                        }
+                    },
+                    {
+                        "type": "editable_select",
+                        "name": "tableschema",
+                        "label": "FORM_TABLESCHEMA_VM4MS_VM4MS_LAYER",
+                        "nb_cols": 2
+                    },
+                    {
+                        "type": "button",
+                        "class": "btn-group btn-group-sm",
+                        "nb_cols": 1,
+                        "buttons": [
+                            {
+                                "type": "button",
+                                "name": "table-datalist",
+                                "label": "FORM_BTN_TABLE_VM4MS_VM4MS_LAYER",
+                                "class": "btn-primary",
+                                "event": "setLayerTableOptions()",
+                                "glyphicon": "refresh"
+                            }
+                        ]
+                    },
+                    {
+                        "type": "editable_select",
+                        "name": "tablename",
+                        "label": "FORM_TABLENAME_VM4MS_VM4MS_LAYER",
+                        "nb_cols": 2
+                    },
+                    {
+                        "type": "button",
+                        "class": "btn-group btn-group-sm",
+                        "nb_cols": 1,
+                        "buttons": [
+                            {
+                                "type": "button",
+                                "name": "id-field-datalist",
+                                "label": "FORM_BTN_IDENTIFIER_VM4MS_VM4MS_LAYER",
+                                "class": "btn-primary",
+                                "event": "setLayerIdFieldOptions()",
+                                "glyphicon": "refresh"
+                            }
+                        ]
+                    },
+                    {
+                        "type": "editable_select",
+                        "name": "tableidfield",
+                        "label": "FORM_TABLEIDFIELD_VM4MS_VM4MS_LAYER",
+                        "nb_cols": 2
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "select",
+                        "name": "ms_layertype_id",
+                        "label": "FORM_LAYERTYPE_ID_VM4MS_VM4MS_LAYER",
+                        "nb_cols": 4,
+                        "web_service": {
+                            "ressource_id": "vm4ms/layertypes",
+                            "id_key": "ms_layertype_id",
+                            "label_key": "ms_layertype_id",
+                            "parameters": {
+                                "order_by": "ms_layertype_id"
+                            }
+                        },
+                        "required": true,
+                        "options": ["|"]
+                    },
+                    {
+                        "type": "select",
+                        "name": "coordsys_id",
+                        "label": "FORM_COORDSYS_ID_VM4MS_VM4MS_LAYER",
+                        "nb_cols": 4,
+                        "web_service": {
+                            "ressource_id": "vm4ms/coordinatesystems",
+                            "id_key": "coordsys_id",
+                            "label_key": "label",
+                            "parameters": {
+                                "order_by": "label"
+                            }
+                        }
+                    },
+                    {
+                        "type": "select",
+                        "name": "source_id",
+                        "label": "FORM_SOURCE_ID_VM4MS_VM4MS_LAYER",
+                        "nb_cols": 4,
+                        "web_service": {
+                            "ressource_id": "vm4ms/sources",
+                            "id_key": "source_id",
+                            "label_key": "name",
+                            "parameters": {
+                                "order_by": "name"
+                            }
+                        }
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "radio",
+                        "name": "active",
+                        "label": "FORM_ACTIVE_VM4MS_VM4MS_LAYER",
+                        "options": {
+                            "choices": [{
+                                    "label": "FORM_ACTIVE_YES_VM4MS_VM4MS_LAYER",
+                                    "value": true
+                                },
+                                {
+                                    "label": "FORM_ACTIVE_NO_VM4MS_VM4MS_LAYER",
+                                    "value": false
+                                }]
+                        },
+                        "default_value": true,
+                        "nb_cols": 3
+                    },
+                    {
+                        "type": "text",
+                        "name": "opacity",
+                        "label": "FORM_OPACITY_VM4MS_VM4MS_LAYER",
+                        "pattern": "^([0-9]|[1-9][0-9]|[1][0][0])$",
+                        "required": true,
+                        "default_value": 100,
+                        "nb_cols": 1
+                    },
+                    {
+                        "type": "select",
+                        "name": "metadata_id",
+                        "label": "FORM_METADATA_ID_VM4MS_VM4MS_LAYER",
+                        "nb_cols": 4,
+                        "web_service": {
+                            "ressource_id": "vm4ms/metadatas",
+                            "id_key": "metadata_id",
+                            "label_key": "name",
+                            "parameters": {
+                                "order_by": "name"
+                            }
+                        }
+                    },
+                    {
+                        "type": "hidden",
+                        "name": "create_ws_map_file",
+                        "default_value": "true",
+                        "nb_cols": 1
+                    },
+                    {
+                        "type": "hidden",
+                        "name": "wmsservices",
+                        "nb_cols": 1
+                    }
+                ]
+            },
+            {
+                "class": "form-row-layer-definition",
+                "fields": [
+                    {
+                        "type": "codemirror",
+                        "name": "definition",
+                        "label": "FORM_DEFINITION_VM4MS_VM4MS_LAYER",
+                        "nb_cols": 12,
+                        "required": true,
+                        "codemirrorOptions": {
+                            "runnable": true,
+                            "lineNumbers": true,
+                            "matchBrackets": true,
+                            "mode": "map",
+                            "indentUnit": 4,
+                            "indentWithTabs": true,
+                            "enterMode": "keep",
+                            "tabMode": "shift",
+                            "appHeight": "40%"
+                        }
+                    }
+                ]
+            },
+            {
+                "class": "form-field-inline form-row-layer-palette",
+                "fields": [
+                    {
+                        "type": "button",
+                        "class": "btn-ungroup btn-group-sm vm4ms-layer-symbols-fonts-container",
+                        "nb_cols": 5,
+                        "buttons": [
+                            {
+                                "type": "button",
+                                "name": "mapserver_symbols",
+                                "label": "FORM_BTN_SYMBOLS_VM4MS_VM4MS_LAYER",
+                                "class": "btn-default",
+                                "event": "displayMapServerSymbolsModal()"
+                            },
+                            {
+                                "type": "button",
+                                "name": "mapserver_fonts",
+                                "label": "FORM_BTN_FONTS_VM4MS_VM4MS_LAYER",
+                                "class": "btn-default",
+                                "event": "displayMapServerFontsModal()"
+                            }
+                        ]
+                    }
+                ]
+            },
+            {
+                "class": "form-row-margin-top form-row-layer-btn",
+                "fields": [
+                    {
+                        "type": "button",
+                        "class": "btn-ungroup btn-group-sm",
+                        "nb_cols": 12,
+                        "buttons": [
+                            {
+                                "type": "submit",
+                                "name": "form_submit",
+                                "label": "FORM_CREATE",
+                                "class": "btn-primary"
+                            },
+                            {
+                                "type": "button",
+                                "name": "return_list",
+                                "label": "FORM_RETURN_LIST",
+                                "class": "btn-primary",
+                                "event": "setMode(\"search\")"
+                            }
+                        ]
+                    }
+                ]
+            }
+        ]
+    },
+    "display": {
+        "name": "vm4ms_layer_display_form",
+        "title": "FORM_TITLE_VM4MS_VM4MS_LAYER",
+        "input_size": "xs",
+        "nb_cols": 12,
+        "rows": [
+            {
+                "fields": [
+                    {
+                        "type": "label",
+                        "name": "ms_layer_id",
+                        "label": "FORM_LAYER_ID_VM4MS_VM4MS_LAYER",
+                        "nb_cols": 3
+                    },
+                    {
+                        "type": "label",
+                        "name": "name",
+                        "label": "FORM_NAME_VM4MS_VM4MS_LAYER",
+                        "nb_cols": 3
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "label",
+                        "name": "title",
+                        "label": "FORM_LAYER_TITLE_VM4MS_VM4MS_LAYER",
+                        "nb_cols": 12
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "label",
+                        "name": "connection_label",
+                        "label": "FORM_CONNECTION_ID_VM4MS_VM4MS_LAYER",
+                        "nb_cols": 3
+                    },
+                    {
+                        "type": "label",
+                        "name": "tableschema",
+                        "label": "FORM_TABLESCHEMA_VM4MS_VM4MS_LAYER",
+                        "nb_cols": 3
+                    },
+                    {
+                        "type": "label",
+                        "name": "tablename",
+                        "label": "FORM_TABLENAME_VM4MS_VM4MS_LAYER",
+                        "nb_cols": 3
+                    },
+                    {
+                        "type": "label",
+                        "name": "tableidfield",
+                        "label": "FORM_TABLEIDFIELD_VM4MS_VM4MS_LAYER",
+                        "nb_cols": 3
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "label",
+                        "name": "source_label",
+                        "label": "FORM_SOURCE_ID_VM4MS_VM4MS_LAYER",
+                        "nb_cols": 3
+                    },
+                    {
+                        "type": "label",
+                        "name": "ms_layertype_id",
+                        "label": "FORM_LAYERTYPE_ID_VM4MS_VM4MS_LAYER",
+                        "nb_cols": 3
+                    },
+                    {
+                        "type": "label",
+                        "name": "coordsys_label",
+                        "label": "FORM_COORDSYS_ID_VM4MS_VM4MS_LAYER",
+                        "nb_cols": 3
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "label",
+                        "name": "active",
+                        "label": "FORM_ACTIVE_VM4MS_VM4MS_LAYER",
+                        "default_value": "setRadioTranslation('active')",
+                        "nb_cols": 3
+                    },
+                    {
+                        "type": "label",
+                        "name": "opacity",
+                        "label": "FORM_OPACITY_VM4MS_VM4MS_LAYER",
+                        "nb_cols": 1
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "codemirror",
+                        "name": "definition",
+                        "label": "FORM_DEFINITION_VM4MS_VM4MS_LAYER",
+                        "nb_cols": 12,
+                        "codemirrorOptions": {
+                            "runnable": true,
+                            "lineNumbers": true,
+                            "matchBrackets": true,
+                            "mode": "map",
+                            "indentUnit": 4,
+                            "indentWithTabs": true,
+                            "enterMode": "keep",
+                            "tabMode": "shift",
+                            "readOnly": "true",
+                            "appHeight": "40%"
+                        }
+                    }
+                ]
+            },
+            {
+                "fields": [
+                    {
+                        "type": "button",
+                        "class": "btn-ungroup btn-group-sm",
+                        "nb_cols": 12,
+                        "buttons": [
+                            {
+                                "type": "button",
+                                "name": "return_list",
+                                "label": "FORM_RETURN_LIST",
+                                "class": "btn-primary",
+                                "event": "setMode(\"search\")"
+                            }
+                        ]
+                    }
+                ]
+            }
+        ]
+    }
+}
diff --git a/vmap/client/modules/vm4ms/forms/vm4ms/vm4ms_vm4ms_layer_getfeatureinfo_template.json b/vmap/client/modules/vm4ms/forms/vm4ms/vm4ms_vm4ms_layer_getfeatureinfo_template.json
new file mode 100755
index 0000000000000000000000000000000000000000..d8d2d4ffce7ede2fada760b06477e3c1087591db
--- /dev/null
+++ b/vmap/client/modules/vm4ms/forms/vm4ms/vm4ms_vm4ms_layer_getfeatureinfo_template.json
@@ -0,0 +1,61 @@
+{
+    "search": {},
+    "update": {
+        "name": "vm4ms_layer_update_form",
+        "title": "FORM_TITLE_VM4MS_VM4MS_LAYER",
+        "input_size": "xs",
+        "event": "sendLayerGetFeatureInfoTemplate()",
+        "nb_cols": 12,
+        "rows": [{
+                "fields":[
+                    {
+                        "type":"codemirror",
+                        "id":"vm4ms_layer_form_getFeatureInfo_template",
+                        "name":"getFeatureInfo_template",
+                        "label":"FORM_LAYER_GETFEATUREINFO_TEMPLATE_CONTENT",
+                        "nb_cols":12,
+                        "codemirrorOptions":{
+                            "runnable":true,
+                            "lineNumbers":true,
+                            "matchBrackets":true,
+                            "mode":"htmlmixed",
+                            "indentUnit":4,
+                            "indentWithTabs":true,
+                            "enterMode":"keep",
+                            "tabMode":"shift",
+                            "appHeight":"70%"
+                        }
+                    }
+                ]
+            },
+            {
+                "class": "form-row-margin-top form-row-layer-btn",
+                "fields": [
+                    {
+                        "type": "button",
+                        "class": "btn-ungroup btn-group-sm",
+                        "nb_cols": 12,
+                        "buttons": [
+                            {
+                                "type": "button",
+                                "name": "save_getfeatureinfo_template_layer_btn",
+                                "label": "FORM_SAVE_GETFEATUREINFO_TEMPLATE_VM4MS_VM4MS_LAYER",
+                                "class": "btn-primary",
+                                "event": "sendLayerGetFeatureInfoTemplate()"
+                            },
+                            {
+                                "type": "button",
+                                "name": "regen_getfeatureinfo_template_layer_btn",
+                                "label": "FORM_REGEN_GETFEATUREINFO_TEMPLATE_VM4MS_VM4MS_LAYER",
+                                "class": "btn-primary",
+                                "event": "regenLayerGetFeatureInfoTemplate()"
+                            }
+                        ]
+                    }
+                ]
+            }
+        ]
+    },
+    "insert": {},
+    "display": {}
+}
diff --git a/vmap/client/modules/vm4ms/forms/vm4ms/vm4ms_vm4ms_layer_openlayers_test.json b/vmap/client/modules/vm4ms/forms/vm4ms/vm4ms_vm4ms_layer_openlayers_test.json
new file mode 100755
index 0000000000000000000000000000000000000000..af07780341c584617b6ae2c9cec08730a628a868
--- /dev/null
+++ b/vmap/client/modules/vm4ms/forms/vm4ms/vm4ms_vm4ms_layer_openlayers_test.json
@@ -0,0 +1,93 @@
+{
+    "search":{
+    },
+    "update":{
+        "name":"layer_openlayers_test_update_form",
+        "title":"",
+        "input_size":"xs",
+        "event":"",
+        "nb_cols":12,
+        "rows":[
+            {
+                "fields": [
+                    {
+                        "type": "map_vmap",
+                        "name": "layer_test_map",
+                        "required": false,
+                        "nb_cols": 12,
+                        "id": "layer_test_map",
+                        "style": {
+                            "height": "100%",
+                            "margin-bottom": "-20px"
+                        },
+                        "map_options": {
+                            "center": {
+                                "extent": [
+                                ]
+                            },
+                            "type": "vmap",
+                            "controls": {
+                                "MP": false,
+                                "ZO": true,
+                                "SL": true,
+                                "CP": true
+                            },
+                            "layers": [],
+                            "interactions": {
+                                "multi_geometry": false,
+                                "full_screen": false,
+                                "RA": false,
+                                "RO": false,
+                                "ED": false,
+                                "DP": false,
+                                "DL": false,
+                                "DPol": false,
+                                "SE": true,
+                                "layer_tree": true
+                            },
+                            "draw_color": "rgba(54,184,255,0.6)",
+                            "contour_color": "rgba(0,0,0,0.4)",
+                            "contour_size": 2,
+                            "circle_radius": 6,
+                            "features": [],
+                            "coord_accuracy": 8,
+                            "tree": {
+                                "name": "Tree",
+                                "children": [
+                                    {
+                                        "view": {
+                                            "zoom": 6,
+                                            "maxZoom": 28,
+                                            "minZoom": 0,
+                                            "extent": [
+                                            ]
+                                        }
+                                    },
+                                    {
+                                        "name": "Open Street Map",
+                                        "children": [
+                                            {
+                                                "name": "Open Street Maps",
+                                                "visible": true,
+                                                "select": true,
+                                                "layerType": "osm",
+                                                "url": "https://{a-c}.tile.openstreetmap.org/{z}/{x}/{y}.png",
+                                                "select": true,
+                                                "index": 0
+                                            }
+                                        ],
+                                        "visible": true
+                                    }
+                                ]
+                            }
+                        }
+                    }
+                ]
+            }
+        ]
+    },
+    "insert":{
+    },
+    "display":{
+    }
+}
\ No newline at end of file
diff --git a/vmap/client/modules/vm4ms/forms/vm4ms/vm4ms_vm4ms_layer_wms_service.json b/vmap/client/modules/vm4ms/forms/vm4ms/vm4ms_vm4ms_layer_wms_service.json
new file mode 100755
index 0000000000000000000000000000000000000000..7068cf71077fd37bf9bc59398b22be70880d8103
--- /dev/null
+++ b/vmap/client/modules/vm4ms/forms/vm4ms/vm4ms_vm4ms_layer_wms_service.json
@@ -0,0 +1,126 @@
+{
+    "search":{
+    },
+    "insert":{
+    },
+    "update":{
+        "name":"vm4ms_layer_wms_service_update_form",
+        "title":"FORM_TITLE_VM4MS_VM4MS_LAYER_WMS_SERVICE",
+        "input_size":"xs",
+        "event":"sendSimpleForm()",
+        "nb_cols":12,
+        "rows":[
+            {
+                "fields":[
+                    {
+                        "type":"label",
+                        "name":"ms_layer_id",
+                        "label":"FORM_LAYER_ID_VM4MS_VM4MS_LAYER_WMS_SERVICE",
+                        "nb_cols":6
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"double_select",
+                        "name":"wmsservices",
+                        "name_from":"wmsservice",
+                        "name_to":"wmsservices",
+                        "label":"FORM_WMSSERVICE_VM4MS_VM4MS_LAYER",
+                        "label_from":"FORM_AVAILABLE_WMSSERVICE_VM4MS_VM4MS_LAYER",
+                        "label_to":"FORM_LINKED_WMSSERVICE_VM4MS_VM4MS_LAYER",
+                        "web_service":{
+                            "ressource_id":"vm4ms/publicwmsservices",
+                            "id_key":"wmsservice_id",
+                            "label_key":"wmsservice_id",
+                            "parameters":{
+                                    "order_by":"wmsservice_id"
+                            }
+                        },
+                        "size":12,
+                        "nb_cols":8
+                    }
+                ]
+            },
+            {
+                "class":"form-row-margin-top",
+                "fields":[
+                    {
+                        "type":"button",
+                        "class":"btn-ungroup btn-group-sm",
+                        "nb_cols":12,
+                        "buttons":[
+                            {
+                                "type":"submit",
+                                "name":"form_update_submit",
+                                "label":"FORM_UPDATE",
+                                "class":"btn-primary"
+                            },
+                            {
+                                "type":"button",
+                                "name":"clone_form",
+                                "label":"FORM_CLONE",
+                                "class":"btn-primary",
+                                "event":"cloneVm4msLayer()"
+                            },
+                            {
+                                "type":"button",
+                                "name":"return_list",
+                                "label":"FORM_RETURN_LIST",
+                                "class":"btn-primary",
+                                "event":"setMode(\"search\")"
+                            }
+                        ]
+                    }
+                ]
+            }
+        ]
+    },
+    "display":{
+        "name":"vm4ms_layer_wms_service_display_form",
+        "title":"FORM_TITLE_VM4MS_VM4MS_LAYER_WMS_SERVICE",
+        "input_size":"xs",
+        "nb_cols":12,
+        "rows":[
+            {
+                "fields":[
+                    {
+                        "type":"label",
+                        "name":"ms_layer_id",
+                        "label":"FORM_LAYER_ID_VM4MS_VM4MS_LAYER_WMS_SERVICE",
+                        "nb_cols":6
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"label",
+                        "name":"wmsservices_label",
+                        "label":"FORM_WMSSERVICE_VM4MS_VM4MS_LAYER",
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"button",
+                        "class":"btn-ungroup btn-group-sm",
+                        "nb_cols":12,
+                        "buttons":[
+                            {
+                                "type":"button",
+                                "name":"return_list",
+                                "label":"FORM_RETURN_LIST",
+                                "class":"btn-primary",
+                                "event":"setMode(\"search\")"
+                            }
+                        ]
+                    }
+                ]
+            }
+        ]
+    }
+}
\ No newline at end of file
diff --git a/vmap/client/modules/vm4ms/forms/vm4ms/vm4ms_vm4ms_metadata.json b/vmap/client/modules/vm4ms/forms/vm4ms/vm4ms_vm4ms_metadata.json
new file mode 100755
index 0000000000000000000000000000000000000000..f453dabbbc66a4d6d9510b9252bab92a9ccfaa3e
--- /dev/null
+++ b/vmap/client/modules/vm4ms/forms/vm4ms/vm4ms_vm4ms_metadata.json
@@ -0,0 +1,261 @@
+{
+    "search":{
+        "name":"vm4ms_metadata_search_form",
+        "title":"",
+        "input_size":"xxs",
+        "nb_cols":12,
+        "rows":[
+            {
+                "fields":[
+                    {
+                        "type":"text",
+                        "name":"name",
+                        "label":"FORM_NAME_VM4MS_VM4MS_METADATA",
+                        "nb_cols":3
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"button",
+                        "class":"btn-ungroup btn-group-xs",
+                        "nb_cols":12,
+                        "buttons":[
+                            {
+                                "type":"button",
+                                "name":"search",
+                                "label":"FORM_SEARCH_BUTTON",
+                                "class":"btn-primary",
+                                "event":"setGridFilter()"
+                            },
+                            {
+                                "type":"reset",
+                                "name":"reset",
+                                "label":"FORM_RESET_BUTTON",
+                                "class":"btn-primary",
+                                "event":"resetGridFilter()"
+                            }
+                        ]
+                    }
+                ]
+            }
+        ]
+    },
+    "update":{
+        "name":"vm4ms_metadata_update_form",
+        "title":"FORM_TITLE_VM4MS_VM4MS_METADATA",
+        "input_size":"xs",
+        "event":"sendSimpleForm()",
+        "nb_cols":12,
+        "rows":[
+            {
+                "fields":[
+                    {
+                        "type":"label",
+                        "name":"metadata_id",
+                        "label":"FORM_METADATA_ID_VM4MS_VM4MS_METADATA",
+                        "nb_cols":6
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"text",
+                        "name":"name",
+                        "label":"FORM_NAME_VM4MS_VM4MS_METADATA",
+                        "required":true,
+                        "nb_cols":4
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"codemirror",
+                        "name":"definition",
+                        "label":"FORM_DEFINITION_VM4MS_VM4MS_METADATA",
+                        "nb_cols":12,
+                        "codemirrorOptions":{
+                            "runnable":true,
+                            "lineNumbers":true,
+                            "matchBrackets":true,
+                            "mode":"map",
+                            "indentUnit":4,
+                            "indentWithTabs":true,
+                            "enterMode":"keep",
+                            "tabMode":"shift",
+                            "appHeight":"70%"
+                        }
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"button",
+                        "class":"btn-ungroup btn-group-sm",
+                        "nb_cols":12,
+                        "buttons":[
+                            {
+                                "type":"submit",
+                                "name":"form_submit",
+                                "label":"FORM_UPDATE",
+                                "class":"btn-primary"
+                            },
+                            {
+                                "type":"button",
+                                "name":"clone_form",
+                                "label":"FORM_CLONE",
+                                "class":"btn-primary",
+                                "event":"cloneSectionForm()"
+                            },
+                            {
+                                "type":"button",
+                                "name":"return_list",
+                                "label":"FORM_RETURN_LIST",
+                                "class":"btn-primary",
+                                "event":"setMode(\"search\")"
+                            }
+                        ]
+                    }
+                ]
+            }
+        ]
+    },
+    "insert":{
+        "name":"vm4ms_metadata_insert_form",
+        "title":"FORM_TITLE_VM4MS_VM4MS_METADATA",
+        "input_size":"xs",
+        "event":"sendSimpleForm()",
+        "afterEvent":"editSectionForm()",
+        "nb_cols":12,
+        "rows":[
+            {
+                "fields":[
+                    {
+                        "type":"text",
+                        "name":"name",
+                        "label":"FORM_NAME_VM4MS_VM4MS_METADATA",
+                        "required":true,
+                        "nb_cols":4
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"codemirror",
+                        "name":"definition",
+                        "label":"FORM_DEFINITION_VM4MS_VM4MS_METADATA",
+                        "nb_cols":12,
+                        "codemirrorOptions":{
+                            "runnable":true,
+                            "lineNumbers":true,
+                            "matchBrackets":true,
+                            "mode":"map",
+                            "indentUnit":4,
+                            "indentWithTabs":true,
+                            "enterMode":"keep",
+                            "tabMode":"shift",
+                            "appHeight":"70%"
+                        }
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"button",
+                        "class":"btn-ungroup btn-group-sm",
+                        "nb_cols":12,
+                        "buttons":[
+                            {
+                                "type":"submit",
+                                "name":"form_submit",
+                                "label":"FORM_CREATE",
+                                "class":"btn-primary"
+                            },
+                            {
+                                "type":"button",
+                                "name":"return_list",
+                                "label":"FORM_RETURN_LIST",
+                                "class":"btn-primary",
+                                "event":"setMode(\"search\")"
+                            }
+                        ]
+                    }
+                ]
+            }
+        ]
+    },
+    "display":{
+        "name":"vm4ms_metadata_display_form",
+        "title":"FORM_TITLE_VM4MS_VM4MS_METADATA",
+        "input_size":"xs",
+        "nb_cols":12,
+        "rows":[
+            {
+                "fields":[
+                    {
+                        "type":"label",
+                        "name":"metadata_id",
+                        "label":"FORM_METADATA_ID_VM4MS_VM4MS_METADATA",
+                        "nb_cols":6
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"label",
+                        "name":"name",
+                        "label":"FORM_NAME_VM4MS_VM4MS_METADATA",
+                        "nb_cols":6
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"codemirror",
+                        "name":"definition",
+                        "label":"FORM_DEFINITION_VM4MS_VM4MS_METADATA",
+                        "nb_cols":12,
+                        "codemirrorOptions":{
+                            "runnable":true,
+                            "lineNumbers":true,
+                            "matchBrackets":true,
+                            "mode":"map",
+                            "indentUnit":4,
+                            "indentWithTabs":true,
+                            "enterMode":"keep",
+                            "tabMode":"shift",
+                            "appHeight":"50%",
+                            "readOnly":"true"
+                        }
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"button",
+                        "class":"btn-ungroup btn-group-sm",
+                        "nb_cols":12,
+                        "buttons":[
+                            {
+                                "type":"button",
+                                "name":"return_list",
+                                "label":"FORM_RETURN_LIST",
+                                "class":"btn-primary",
+                                "event":"setMode(\"search\")"
+                            }
+                        ]
+                    }
+                ]
+            }
+        ]
+    }
+}
\ No newline at end of file
diff --git a/vmap/client/modules/vm4ms/forms/vm4ms/vm4ms_vm4ms_private_wms_service.json b/vmap/client/modules/vm4ms/forms/vm4ms/vm4ms_vm4ms_private_wms_service.json
new file mode 100755
index 0000000000000000000000000000000000000000..65925125556d39cade0dd31c3c247c5599672dc5
--- /dev/null
+++ b/vmap/client/modules/vm4ms/forms/vm4ms/vm4ms_vm4ms_private_wms_service.json
@@ -0,0 +1,301 @@
+{
+    "search":{
+        "name":"vm4ms_private_wms_service_search_form",
+        "title":"",
+        "input_size":"xxs",
+        "nb_cols":12,
+        "rows":[
+            {
+                "fields":[
+                    {
+                        "type":"text",
+                        "name":"wmsservice_id",
+                        "label":"FORM_WMSSERVICEID_VM4MS_VM4MS_PRIVATE_WMS_SERVICE",
+                        "nb_cols":3
+                    },
+                    {
+                        "type":"select",
+                        "name":"web_id",
+                        "label":"FORM_WEB_ID_VM4MS_VM4MS_PRIVATE_WMS_SERVICE",
+                        "nb_cols":3,
+                        "web_service":{
+                            "ressource_id":"vm4ms/webobjects",
+                            "id_key":"web_id",
+                            "label_key":"name",
+                            "parameters":{
+                                    "order_by":"name"
+                            }
+                        }
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"button",
+                        "class":"btn-ungroup btn-group-xs",
+                        "nb_cols":12,
+                        "buttons":[
+                            {
+                                "type":"button",
+                                "name":"search",
+                                "label":"FORM_SEARCH_BUTTON",
+                                "class":"btn-primary",
+                                "event":"setGridFilter()"
+                            },
+                            {
+                                "type":"reset",
+                                "name":"reset",
+                                "label":"FORM_RESET_BUTTON",
+                                "class":"btn-primary",
+                                "event":"resetGridFilter()"
+                            }
+                        ]
+                    }
+                ]
+            }
+        ]
+    },
+    "update":{
+        "name":"vm4ms_private_wms_service_update_form",
+        "title":"FORM_TITLE_VM4MS_VM4MS_PRIVATE_WMS_SERVICE",
+        "input_size":"xs",
+        "event":"sendSimpleForm()",
+        "afterEvent":"afterSendingWmsServiceForm()",
+        "nb_cols":12,
+        "rows":[
+            {
+                "class":"form-field-inline no-bs-col-padding-field-2 wms-service-url",
+                "fields":[
+                    {
+                        "type":"label",
+                        "name":"wmsservice_id",
+                        "label":"FORM_WMSSERVICEID_VM4MS_VM4MS_PRIVATE_WMS_SERVICE",
+                        "required":true,
+                        "nb_cols":3
+                    },
+                    {
+                        "type":"label",
+                        "name":"wms_service_url",
+                        "label":"FORM_WMS_SERVICE_URL_VM4MS_VM4MS_PUBLIC_WMS_SERVICE",
+                        "nb_cols":3
+                    },
+                    {
+                        "type": "button",
+                        "class": "btn-group btn-group-sm",
+                        "nb_cols": 1,
+                        "buttons": [
+                            {
+                                "type": "button",
+                                "name": "copy_wms_service_url",
+                                "label": "FORM_BTN_WMS_SERVICE_URL_VM4MS_VM4MS_PRIVATE_WMS_SERVICE",
+                                "class": "btn-primary",
+                                "event": "copyFormElemContentToClipboard('wms_service_url')"
+                            }
+                        ]
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"textarea",
+                        "name":"description",
+                        "label":"FORM_DESCRIPTION_VM4MS_VM4MS_PRIVATE_WMS_SERVICE",
+                        "size":10,
+                        "nb_cols":10
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"codemirror",
+                        "name":"definition",
+                        "label":"FORM_DEFINITION_VM4MS_VM4MS_PRIVATE_WMS_SERVICE",
+                        "nb_cols":12,
+                        "codemirrorOptions":{
+                            "runnable":true,
+                            "lineNumbers":true,
+                            "matchBrackets":true,
+                            "mode":"map",
+                            "indentUnit":4,
+                            "indentWithTabs":true,
+                            "enterMode":"keep",
+                            "tabMode":"shift",
+                            "appHeight":"50%"
+                        }
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"select",
+                        "name":"web_id",
+                        "label":"FORM_WEB_ID_VM4MS_VM4MS_PRIVATE_WMS_SERVICE",
+                        "nb_cols":3,
+                        "web_service":{
+                            "ressource_id":"vm4ms/webobjects",
+                            "id_key":"web_id",
+                            "label_key":"name",
+                            "parameters":{
+                                    "order_by":"name"
+                            }
+                        }
+                    },
+                    {
+                        "type":"select",
+                        "name":"msdebuglevel_id",
+                        "label":"FORM_MSDEBUGLEVEL_ID_VM4MS_VM4MS_PRIVATE_WMS_SERVICE",
+                        "nb_cols":3,
+                        "web_service":{
+                            "ressource_id":"vm4ms/mapserverdebuglevels",
+                            "id_key":"msdebuglevel_id",
+                            "label_key":"translation",
+                            "parameters":{
+                                "order_by":"msdebuglevel_id",
+                                "filter": {
+                                    "lang": "getPropertie('language')"
+                                }
+                            }
+                        },
+                        "required": true,
+                        "default_value": 0
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"button",
+                        "class":"btn-ungroup btn-group-sm",
+                        "nb_cols":12,
+                        "buttons":[
+                            {
+                                "type":"submit",
+                                "name":"form_submit",
+                                "label":"FORM_UPDATE",
+                                "class":"btn-primary"
+                            },
+                            {
+                                "type":"button",
+                                "name":"return_list",
+                                "label":"FORM_RETURN_LIST",
+                                "class":"btn-primary",
+                                "event":"setMode(\"search\")"
+                            }
+                        ]
+                    }
+                ]
+            }
+        ]
+    },
+    "insert":{
+    },
+    "display":{
+        "name":"vm4ms_private_wms_service_display_form",
+        "title":"FORM_TITLE_VM4MS_VM4MS_PRIVATE_WMS_SERVICE",
+        "input_size":"xs",
+        "nb_cols":12,
+        "rows":[
+            {
+                "class":"form-field-inline wms-service-url",
+                "fields":[
+                    {
+                        "type":"label",
+                        "name":"wmsservice_id",
+                        "label":"FORM_WMSSERVICEID_VM4MS_VM4MS_PRIVATE_WMS_SERVICE",
+                        "nb_cols":3
+                    },
+                    {
+                        "type":"label",
+                        "name":"wms_service_url",
+                        "label":"FORM_WMS_SERVICE_URL_VM4MS_VM4MS_PUBLIC_WMS_SERVICE",
+                        "nb_cols":9
+                    },
+                    {
+                        "type": "button",
+                        "class": "btn-group btn-group-sm",
+                        "nb_cols": 1,
+                        "buttons": [
+                            {
+                                "type": "button",
+                                "name": "copy_wms_service_url",
+                                "label": "FORM_BTN_WMS_SERVICE_URL_VM4MS_VM4MS_PUBLIC_WMS_SERVICE",
+                                "class": "btn-primary",
+                                "event": "copyFormElemContentToClipboard('wms_service_url')"
+                            }
+                        ]
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"label",
+                        "name":"description",
+                        "label":"FORM_DESCRIPTION_VM4MS_VM4MS_PRIVATE_WMS_SERVICE",
+                        "nb_cols":10
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"codemirror",
+                        "name":"definition",
+                        "label":"FORM_DEFINITION_VM4MS_VM4MS_PRIVATE_WMS_SERVICE",
+                        "nb_cols":12,
+                        "codemirrorOptions":{
+                            "runnable":true,
+                            "lineNumbers":true,
+                            "matchBrackets":true,
+                            "mode":"map",
+                            "indentUnit":4,
+                            "indentWithTabs":true,
+                            "enterMode":"keep",
+                            "tabMode":"shift",
+                            "appHeight":"50%",
+                            "readOnly":"true"
+                        }
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"label",
+                        "name":"web_name",
+                        "label":"FORM_WEB_ID_VM4MS_VM4MS_PRIVATE_WMS_SERVICE",
+                        "nb_cols":3
+                    },
+                    {
+                        "type":"label",
+                        "name":"msdebuglevel_id",
+                        "label":"FORM_MSDEBUGLEVEL_ID_VM4MS_VM4MS_PRIVATE_WMS_SERVICE",
+                        "nb_cols":3
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"button",
+                        "class":"btn-ungroup btn-group-sm",
+                        "nb_cols":12,
+                        "buttons":[
+                            {
+                                "type":"button",
+                                "name":"return_list",
+                                "label":"FORM_RETURN_LIST",
+                                "class":"btn-primary",
+                                "event":"setMode(\"search\")"
+                            }
+                        ]
+                    }
+                ]
+            }
+        ]
+    }
+}
\ No newline at end of file
diff --git a/vmap/client/modules/vm4ms/forms/vm4ms/vm4ms_vm4ms_private_wms_service_layers.json b/vmap/client/modules/vm4ms/forms/vm4ms/vm4ms_vm4ms_private_wms_service_layers.json
new file mode 100755
index 0000000000000000000000000000000000000000..68fb3dfee3830dae8bab2f80a1a6a611a66b3716
--- /dev/null
+++ b/vmap/client/modules/vm4ms/forms/vm4ms/vm4ms_vm4ms_private_wms_service_layers.json
@@ -0,0 +1,57 @@
+{
+    "search":{
+    },
+    "update":{
+        "name":"vm4ms_private_wms_service_layers_search_form",
+        "title":"",
+        "input_size":"xxs",
+        "nb_cols":12,
+        "rows":[
+            {
+                "fields":[
+                    {
+                        "type":"text",
+                        "name":"ms_layer_id",
+                        "label":"FORM_LAYER_ID_VM4MS_VM4MS_PRIVATE_WMS_SERVICE_LAYERS",
+                        "nb_cols":4
+                    },
+                    {
+                        "type":"hidden",
+                        "name":"wmsservice_id",
+                        "default_value":"getTabIdFieldValue()",
+                        "nb_cols":4
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"button",
+                        "class":"btn-ungroup btn-group-xs",
+                        "nb_cols":12,
+                        "buttons":[
+                            {
+                                "type":"button",
+                                "name":"search",
+                                "label":"FORM_SEARCH_BUTTON",
+                                "class":"btn-primary",
+                                "event":"setGridFilter()"
+                            },
+                            {
+                                "type":"reset",
+                                "name":"reset",
+                                "label":"FORM_RESET_BUTTON",
+                                "class":"btn-primary",
+                                "event":"resetGridFilter()"
+                            }
+                        ]
+                    }
+                ]
+            }
+        ]
+    },
+    "insert":{
+    },
+    "display":{
+    }
+}
\ No newline at end of file
diff --git a/vmap/client/modules/vm4ms/forms/vm4ms/vm4ms_vm4ms_private_wms_service_tests.json b/vmap/client/modules/vm4ms/forms/vm4ms/vm4ms_vm4ms_private_wms_service_tests.json
new file mode 100755
index 0000000000000000000000000000000000000000..8ec21d814fab523cb47d665f5d67499efc26ec3a
--- /dev/null
+++ b/vmap/client/modules/vm4ms/forms/vm4ms/vm4ms_vm4ms_private_wms_service_tests.json
@@ -0,0 +1,48 @@
+{
+    "search":{
+    },
+    "update":{
+        "name":"vm4ms_private_wms_service_tests_update_form",
+        "title":"",
+        "input_size":"xs",
+        "event":"",
+        "nb_cols":12,
+        "rows":[
+            {
+                "class":"form-field-inline",
+                "fields":[
+                    {
+                        "type":"text",
+                        "name":"wms_service_login",
+                        "label":"FORM_LOGIN_VM4MS_VM4MS_PRIVATE_WMS_SERVICE_TESTS",
+                        "nb_cols":3
+                    },
+                    {
+                        "type":"password",
+                        "name":"wms_service_password",
+                        "label":"FORM_PASSWORD_VM4MS_VM4MS_PRIVATE_WMS_SERVICE_TESTS",
+                        "nb_cols":3
+                    },
+                    {
+                        "type":"button",
+                        "class":"btn-ungroup btn-group-sm",
+                        "nb_cols":3,
+                        "buttons":[
+                            {
+                                "type":"button",
+                                "name":"form_submit",
+                                "class":"btn-primary",
+                                "glyphicon":"refresh",
+                                "event":"refreshWmsServiceTestsTab()"
+                            }
+                        ]
+                    }
+                ]
+            }
+        ]
+    },
+    "insert":{
+    },
+    "display":{
+    }
+}
\ No newline at end of file
diff --git a/vmap/client/modules/vm4ms/forms/vm4ms/vm4ms_vm4ms_public_wms_service.json b/vmap/client/modules/vm4ms/forms/vm4ms/vm4ms_vm4ms_public_wms_service.json
new file mode 100755
index 0000000000000000000000000000000000000000..2cc2f131deb25296653648fc31bc36e0d6d49a72
--- /dev/null
+++ b/vmap/client/modules/vm4ms/forms/vm4ms/vm4ms_vm4ms_public_wms_service.json
@@ -0,0 +1,420 @@
+{
+    "search":{
+        "name":"vm4ms_public_wms_service_search_form",
+        "title":"",
+        "input_size":"xxs",
+        "nb_cols":12,
+        "rows":[
+            {
+                "fields":[
+                    {
+                        "type":"text",
+                        "name":"wmsservice_id",
+                        "label":"FORM_WMSSERVICEID_VM4MS_VM4MS_PUBLIC_WMS_SERVICE",
+                        "nb_cols":3
+                    },
+                    {
+                        "type":"select",
+                        "name":"web_id",
+                        "label":"FORM_WEB_ID_VM4MS_VM4MS_PUBLIC_WMS_SERVICE",
+                        "nb_cols":3,
+                        "web_service":{
+                            "ressource_id":"vm4ms/webobjects",
+                            "id_key":"web_id",
+                            "label_key":"name",
+                            "parameters":{
+                                    "order_by":"name"
+                            }
+                        }
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"button",
+                        "class":"btn-ungroup btn-group-xs",
+                        "nb_cols":12,
+                        "buttons":[
+                            {
+                                "type":"button",
+                                "name":"search",
+                                "label":"FORM_SEARCH_BUTTON",
+                                "class":"btn-primary",
+                                "event":"setGridFilter()"
+                            },
+                            {
+                                "type":"reset",
+                                "name":"reset",
+                                "label":"FORM_RESET_BUTTON",
+                                "class":"btn-primary",
+                                "event":"resetGridFilter()"
+                            }
+                        ]
+                    }
+                ]
+            }
+        ]
+    },
+    "update":{
+        "name":"vm4ms_public_wms_service_update_form",
+        "title":"FORM_TITLE_VM4MS_VM4MS_PUBLIC_WMS_SERVICE",
+        "input_size":"xs",
+        "event":"sendSimpleForm()",
+        "afterEvent":"afterSendingWmsServiceForm()",
+        "nb_cols":12,
+        "rows":[
+            {
+                "class":"form-field-inline no-bs-col-padding-field-2 wms-service-url",
+                "fields":[
+                    {
+                        "type":"label",
+                        "name":"wmsservice_id",
+                        "label":"FORM_WMSSERVICEID_VM4MS_VM4MS_PUBLIC_WMS_SERVICE",
+                        "nb_cols":3
+                    },
+                    {
+                        "type":"label",
+                        "name":"wms_service_url",
+                        "label":"FORM_WMS_SERVICE_URL_VM4MS_VM4MS_PUBLIC_WMS_SERVICE",
+                        "nb_cols":3
+                    },
+                    {
+                        "type": "button",
+                        "class": "btn-group btn-group-sm",
+                        "nb_cols": 1,
+                        "buttons": [
+                            {
+                                "type": "button",
+                                "name": "copy_wms_service_url",
+                                "label": "FORM_BTN_WMS_SERVICE_URL_VM4MS_VM4MS_PUBLIC_WMS_SERVICE",
+                                "class": "btn-primary",
+                                "event": "copyFormElemContentToClipboard('wms_service_url')"
+                            }
+                        ]
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"textarea",
+                        "name":"description",
+                        "label":"FORM_DESCRIPTION_VM4MS_VM4MS_PUBLIC_WMS_SERVICE",
+                        "size":10,
+                        "nb_cols":10
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"codemirror",
+                        "name":"definition",
+                        "label":"FORM_DEFINITION_VM4MS_VM4MS_PUBLIC_WMS_SERVICE",
+                        "nb_cols":12,
+                        "codemirrorOptions":{
+                            "runnable":true,
+                            "lineNumbers":true,
+                            "matchBrackets":true,
+                            "mode":"map",
+                            "indentUnit":4,
+                            "indentWithTabs":true,
+                            "enterMode":"keep",
+                            "tabMode":"shift",
+                            "appHeight":"50%"
+                        }
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"select",
+                        "name":"web_id",
+                        "label":"FORM_WEB_ID_VM4MS_VM4MS_PUBLIC_WMS_SERVICE",
+                        "nb_cols":3,
+                        "web_service":{
+                            "ressource_id":"vm4ms/webobjects",
+                            "id_key":"web_id",
+                            "label_key":"name",
+                            "parameters":{
+                                    "order_by":"name"
+                            }
+                        }
+                    },
+                    {
+                        "type":"select",
+                        "name":"msdebuglevel_id",
+                        "label":"FORM_MSDEBUGLEVEL_ID_VM4MS_VM4MS_PUBLIC_WMS_SERVICE",
+                        "nb_cols":3,
+                        "web_service":{
+                            "ressource_id":"vm4ms/mapserverdebuglevels",
+                            "id_key":"msdebuglevel_id",
+                            "label_key":"translation",
+                            "parameters":{
+                                "order_by":"msdebuglevel_id",
+                                "filter": {
+                                    "lang": "getPropertie('language')"
+                                }
+                            }
+                        },
+                        "required": true,
+                        "default_value": 0
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"button",
+                        "class":"btn-ungroup btn-group-sm",
+                        "nb_cols":12,
+                        "buttons":[
+                            {
+                                "type":"submit",
+                                "name":"form_submit",
+                                "label":"FORM_UPDATE",
+                                "class":"btn-primary"
+                            },
+                            {
+                                "type":"button",
+                                "name":"clone_form",
+                                "label":"FORM_CLONE",
+                                "class":"btn-primary",
+                                "event":"cloneSectionForm()"
+                            },
+                            {
+                                "type":"button",
+                                "name":"return_list",
+                                "label":"FORM_RETURN_LIST",
+                                "class":"btn-primary",
+                                "event":"setMode(\"search\")"
+                            }
+                        ]
+                    }
+                ]
+            }
+        ]
+    },
+    "insert":{
+        "name":"vm4ms_public_wms_service_insert_form",
+        "title":"FORM_TITLE_VM4MS_VM4MS_PUBLIC_WMS_SERVICE",
+        "input_size":"xs",
+        "event":"sendSimpleForm()",
+        "afterEvent":"editSectionForm()",
+        "nb_cols":12,
+        "rows":[
+            {
+                "fields":[
+                    {
+                        "type":"text",
+                        "name":"wmsservice_id",
+                        "label":"FORM_WMSSERVICEID_VM4MS_VM4MS_PUBLIC_WMS_SERVICE",
+                        "pattern": "[a-zA-Z0-9_]+",
+                        "required":true,
+                        "nb_cols":6
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"textarea",
+                        "name":"description",
+                        "label":"FORM_DESCRIPTION_VM4MS_VM4MS_PUBLIC_WMS_SERVICE",
+                        "size":10,
+                        "nb_cols":10
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"codemirror",
+                        "name":"definition",
+                        "label":"FORM_DEFINITION_VM4MS_VM4MS_PUBLIC_WMS_SERVICE",
+                        "nb_cols":12,
+                        "codemirrorOptions":{
+                            "runnable":true,
+                            "lineNumbers":true,
+                            "matchBrackets":true,
+                            "mode":"map",
+                            "indentUnit":4,
+                            "indentWithTabs":true,
+                            "enterMode":"keep",
+                            "tabMode":"shift",
+                            "appHeight":"50%"
+                        }
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"select",
+                        "name":"web_id",
+                        "label":"FORM_WEB_ID_VM4MS_VM4MS_PUBLIC_WMS_SERVICE",
+                        "nb_cols":3,
+                        "web_service":{
+                            "ressource_id":"vm4ms/webobjects",
+                            "id_key":"web_id",
+                            "label_key":"name",
+                            "parameters":{
+                                    "order_by":"name"
+                            }
+                        }
+                    },
+                    {
+                        "type":"select",
+                        "name":"msdebuglevel_id",
+                        "label":"FORM_MSDEBUGLEVEL_ID_VM4MS_VM4MS_PUBLIC_WMS_SERVICE",
+                        "nb_cols":3,
+                        "web_service":{
+                            "ressource_id":"vm4ms/mapserverdebuglevels",
+                            "id_key":"msdebuglevel_id",
+                            "label_key":"translation",
+                            "parameters":{
+                                "order_by":"msdebuglevel_id",
+                                "filter": {
+                                    "lang": "getPropertie('language')"
+                                }
+                            }
+                        },
+                        "required": true,
+                        "default_value": 0
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"button",
+                        "class":"btn-ungroup btn-group-sm",
+                        "nb_cols":12,
+                        "buttons":[
+                            {
+                                "type":"submit",
+                                "name":"form_submit",
+                                "label":"FORM_CREATE",
+                                "class":"btn-primary"
+                            },
+                            {
+                                "type":"button",
+                                "name":"return_list",
+                                "label":"FORM_RETURN_LIST",
+                                "class":"btn-primary",
+                                "event":"setMode(\"search\")"
+                            }
+                        ]
+                    }
+                ]
+            }
+        ]
+    },
+    "display":{
+        "name":"vm4ms_public_wms_service_display_form",
+        "title":"FORM_TITLE_VM4MS_VM4MS_PUBLIC_WMS_SERVICE",
+        "input_size":"xs",
+        "nb_cols":12,
+        "rows":[
+            {
+                "class":"form-field-inline wms-service-url",
+                "fields":[
+                    {
+                        "type":"label",
+                        "name":"wmsservice_id",
+                        "label":"FORM_WMSSERVICEID_VM4MS_VM4MS_PUBLIC_WMS_SERVICE",
+                        "nb_cols":3
+                    },
+                    {
+                        "type":"label",
+                        "name":"wms_service_url",
+                        "label":"FORM_WMS_SERVICE_URL_VM4MS_VM4MS_PUBLIC_WMS_SERVICE",
+                        "nb_cols":9
+                    },
+                    {
+                        "type": "button",
+                        "class": "btn-group btn-group-sm",
+                        "nb_cols": 1,
+                        "buttons": [
+                            {
+                                "type": "button",
+                                "name": "copy_wms_service_url",
+                                "label": "FORM_BTN_WMS_SERVICE_URL_VM4MS_VM4MS_PUBLIC_WMS_SERVICE",
+                                "class": "btn-primary",
+                                "event": "copyFormElemContentToClipboard('wms_service_url')"
+                            }
+                        ]
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"label",
+                        "name":"description",
+                        "label":"FORM_DESCRIPTION_VM4MS_VM4MS_PUBLIC_WMS_SERVICE",
+                        "nb_cols":10
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"codemirror",
+                        "name":"definition",
+                        "label":"FORM_DEFINITION_VM4MS_VM4MS_PUBLIC_WMS_SERVICE",
+                        "nb_cols":12,
+                        "codemirrorOptions":{
+                            "runnable":true,
+                            "lineNumbers":true,
+                            "matchBrackets":true,
+                            "mode":"map",
+                            "indentUnit":4,
+                            "indentWithTabs":true,
+                            "enterMode":"keep",
+                            "tabMode":"shift",
+                            "appHeight":"50%",
+                            "readOnly":"true"
+                        }
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"label",
+                        "name":"web_name",
+                        "label":"FORM_WEB_ID_VM4MS_VM4MS_PUBLIC_WMS_SERVICE",
+                        "nb_cols":3
+                    },
+                    {
+                        "type":"label",
+                        "name":"msdebuglevel_id",
+                        "label":"FORM_MSDEBUGLEVEL_ID_VM4MS_VM4MS_PUBLIC_WMS_SERVICE",
+                        "nb_cols":3
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"button",
+                        "class":"btn-ungroup btn-group-sm",
+                        "nb_cols":12,
+                        "buttons":[
+                            {
+                                "type":"button",
+                                "name":"return_list",
+                                "label":"FORM_RETURN_LIST",
+                                "class":"btn-primary",
+                                "event":"setMode(\"search\")"
+                            }
+                        ]
+                    }
+                ]
+            }
+        ]
+    }
+}
\ No newline at end of file
diff --git a/vmap/client/modules/vm4ms/forms/vm4ms/vm4ms_vm4ms_public_wms_service_available_layers.json b/vmap/client/modules/vm4ms/forms/vm4ms/vm4ms_vm4ms_public_wms_service_available_layers.json
new file mode 100755
index 0000000000000000000000000000000000000000..5190178a6e3fd5d46cdcc0077f291f7ba6f8fbe2
--- /dev/null
+++ b/vmap/client/modules/vm4ms/forms/vm4ms/vm4ms_vm4ms_public_wms_service_available_layers.json
@@ -0,0 +1,51 @@
+{
+    "search":{
+        "name":"vm4ms_public_wms_service_available_layers_search_form",
+        "title":"",
+        "input_size":"xxs",
+        "nb_cols":12,
+        "rows":[
+            {
+                "fields":[
+                    {
+                        "type":"text",
+                        "name":"name",
+                        "label":"FORM_NAME_VM4MS_VM4MS_PUBLIC_WMS_SERVICE_AVAILABLE_LAYERS",
+                        "nb_cols":4
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"button",
+                        "class":"btn-ungroup btn-group-xs",
+                        "nb_cols":12,
+                        "buttons":[
+                            {
+                                "type":"button",
+                                "name":"search",
+                                "label":"FORM_SEARCH_BUTTON",
+                                "class":"btn-primary",
+                                "event":"setGridFilter()"
+                            },
+                            {
+                                "type":"reset",
+                                "name":"reset",
+                                "label":"FORM_RESET_BUTTON",
+                                "class":"btn-primary",
+                                "event":"resetGridFilter()"
+                            }
+                        ]
+                    }
+                ]
+            }
+        ]
+    },
+    "update":{
+    },
+    "insert":{
+    },
+    "display":{
+    }
+}
\ No newline at end of file
diff --git a/vmap/client/modules/vm4ms/forms/vm4ms/vm4ms_vm4ms_public_wms_service_layers.json b/vmap/client/modules/vm4ms/forms/vm4ms/vm4ms_vm4ms_public_wms_service_layers.json
new file mode 100755
index 0000000000000000000000000000000000000000..233d5f91dddf446e8f57be8ae9fa858abf76c662
--- /dev/null
+++ b/vmap/client/modules/vm4ms/forms/vm4ms/vm4ms_vm4ms_public_wms_service_layers.json
@@ -0,0 +1,57 @@
+{
+    "search":{
+    },
+    "update":{
+        "name":"vm4ms_public_wms_service_layers_search_form",
+        "title":"",
+        "input_size":"xxs",
+        "nb_cols":12,
+        "rows":[
+            {
+                "fields":[
+                    {
+                        "type":"text",
+                        "name":"ms_layer_id",
+                        "label":"FORM_LAYER_ID_VM4MS_VM4MS_PUBLIC_WMS_SERVICE_LAYERS",
+                        "nb_cols":4
+                    },
+                    {
+                        "type":"hidden",
+                        "name":"wmsservice_id",
+                        "default_value":"getTabIdFieldValue()",
+                        "nb_cols":4
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"button",
+                        "class":"btn-ungroup btn-group-xs",
+                        "nb_cols":12,
+                        "buttons":[
+                            {
+                                "type":"button",
+                                "name":"search",
+                                "label":"FORM_SEARCH_BUTTON",
+                                "class":"btn-primary",
+                                "event":"setGridFilter()"
+                            },
+                            {
+                                "type":"reset",
+                                "name":"reset",
+                                "label":"FORM_RESET_BUTTON",
+                                "class":"btn-primary",
+                                "event":"resetGridFilter()"
+                            }
+                        ]
+                    }
+                ]
+            }
+        ]
+    },
+    "insert":{
+    },
+    "display":{
+    }
+}
\ No newline at end of file
diff --git a/vmap/client/modules/vm4ms/forms/vm4ms/vm4ms_vm4ms_source.json b/vmap/client/modules/vm4ms/forms/vm4ms/vm4ms_vm4ms_source.json
new file mode 100755
index 0000000000000000000000000000000000000000..06a9572dc31fa8854e4e225e528ea50d0fd23dbb
--- /dev/null
+++ b/vmap/client/modules/vm4ms/forms/vm4ms/vm4ms_vm4ms_source.json
@@ -0,0 +1,190 @@
+{
+    "search":{
+        "name":"vm4ms_source_search_form",
+        "title":"",
+        "input_size":"xxs",
+        "nb_cols":12,
+        "rows":[
+            {
+                "fields":[
+                    {
+                        "type":"text",
+                        "name":"name",
+                        "label":"FORM_NAME_VM4MS_VM4MS_SOURCE",
+                        "nb_cols":3
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"button",
+                        "class":"btn-ungroup btn-group-xs",
+                        "nb_cols":12,
+                        "buttons":[
+                            {
+                                "type":"button",
+                                "name":"search",
+                                "label":"FORM_SEARCH_BUTTON",
+                                "class":"btn-primary",
+                                "event":"setGridFilter()"
+                            },
+                            {
+                                "type":"reset",
+                                "name":"reset",
+                                "label":"FORM_RESET_BUTTON",
+                                "class":"btn-primary",
+                                "event":"resetGridFilter()"
+                            }
+                        ]
+                    }
+                ]
+            }
+        ]
+    },
+    "update":{
+        "name":"vm4ms_source_update_form",
+        "title":"FORM_TITLE_VM4MS_VM4MS_SOURCE",
+        "input_size":"xs",
+        "event":"sendSimpleForm()",
+        "nb_cols":12,
+        "rows":[
+            {
+                "fields":[
+                    {
+                        "type":"label",
+                        "name":"source_id",
+                        "label":"FORM_SOURCE_ID_VM4MS_VM4MS_SOURCE",
+                        "nb_cols":6
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"text",
+                        "name":"name",
+                        "label":"FORM_NAME_VM4MS_VM4MS_SOURCE",
+                        "required":true,
+                        "nb_cols":4
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"button",
+                        "class":"btn-ungroup btn-group-sm",
+                        "nb_cols":12,
+                        "buttons":[
+                            {
+                                "type":"submit",
+                                "name":"form_submit",
+                                "label":"FORM_UPDATE",
+                                "class":"btn-primary"
+                            },
+                            {
+                                "type":"button",
+                                "name":"return_list",
+                                "label":"FORM_RETURN_LIST",
+                                "class":"btn-primary",
+                                "event":"setMode(\"search\")"
+                            }
+                        ]
+                    }
+                ]
+            }
+        ]
+    },
+    "insert":{
+        "name":"vm4ms_source_insert_form",
+        "title":"FORM_TITLE_VM4MS_VM4MS_SOURCE",
+        "input_size":"xs",
+        "event":"sendSimpleForm()",
+        "afterEvent":"editSectionForm()",
+        "nb_cols":12,
+        "rows":[
+            {
+                "fields":[
+                    {
+                        "type":"text",
+                        "name":"name",
+                        "label":"FORM_NAME_VM4MS_VM4MS_SOURCE",
+                        "required":true,
+                        "nb_cols":4
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"button",
+                        "class":"btn-ungroup btn-group-sm",
+                        "nb_cols":12,
+                        "buttons":[
+                            {
+                                "type":"submit",
+                                "name":"form_submit",
+                                "label":"FORM_CREATE",
+                                "class":"btn-primary"
+                            },
+                            {
+                                "type":"button",
+                                "name":"return_list",
+                                "label":"FORM_RETURN_LIST",
+                                "class":"btn-primary",
+                                "event":"setMode(\"search\")"
+                            }
+                        ]
+                    }
+                ]
+            }
+        ]
+    },
+    "display":{
+        "name":"vm4ms_source_display_form",
+        "title":"FORM_TITLE_VM4MS_VM4MS_SOURCE",
+        "input_size":"xs",
+        "nb_cols":12,
+        "rows":[
+            {
+                "fields":[
+                    {
+                        "type":"label",
+                        "name":"source_id",
+                        "label":"FORM_SOURCE_ID_VM4MS_VM4MS_SOURCE",
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"label",
+                        "name":"name",
+                        "label":"FORM_NAME_VM4MS_VM4MS_SOURCE",
+                        "nb_cols":12
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"button",
+                        "class":"btn-ungroup btn-group-sm",
+                        "nb_cols":12,
+                        "buttons":[
+                            {
+                                "type":"button",
+                                "name":"return_list",
+                                "label":"FORM_RETURN_LIST",
+                                "class":"btn-primary",
+                                "event":"setMode(\"search\")"
+                            }
+                        ]
+                    }
+                ]
+            }
+        ]
+    }
+}
\ No newline at end of file
diff --git a/vmap/client/modules/vm4ms/forms/vm4ms/vm4ms_vm4ms_web_object.json b/vmap/client/modules/vm4ms/forms/vm4ms/vm4ms_vm4ms_web_object.json
new file mode 100755
index 0000000000000000000000000000000000000000..1b40691b79052c287544e0d875af33e5968630a7
--- /dev/null
+++ b/vmap/client/modules/vm4ms/forms/vm4ms/vm4ms_vm4ms_web_object.json
@@ -0,0 +1,261 @@
+{
+    "search":{
+        "name":"vm4ms_web_object_search_form",
+        "title":"",
+        "input_size":"xxs",
+        "nb_cols":12,
+        "rows":[
+            {
+                "fields":[
+                    {
+                        "type":"text",
+                        "name":"name",
+                        "label":"FORM_NAME_VM4MS_VM4MS_WEB_OBJECT",
+                        "nb_cols":3
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"button",
+                        "class":"btn-ungroup btn-group-xs",
+                        "nb_cols":12,
+                        "buttons":[
+                            {
+                                "type":"button",
+                                "name":"search",
+                                "label":"FORM_SEARCH_BUTTON",
+                                "class":"btn-primary",
+                                "event":"setGridFilter()"
+                            },
+                            {
+                                "type":"reset",
+                                "name":"reset",
+                                "label":"FORM_RESET_BUTTON",
+                                "class":"btn-primary",
+                                "event":"resetGridFilter()"
+                            }
+                        ]
+                    }
+                ]
+            }
+        ]
+    },
+    "update":{
+        "name":"vm4ms_web_object_update_form",
+        "title":"FORM_TITLE_VM4MS_VM4MS_WEB_OBJECT",
+        "input_size":"xs",
+        "event":"sendSimpleForm()",
+        "nb_cols":12,
+        "rows":[
+            {
+                "fields":[
+                    {
+                        "type":"label",
+                        "name":"web_id",
+                        "label":"FORM_WEB_ID_VM4MS_VM4MS_WEB_OBJECT",
+                        "nb_cols":6
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"text",
+                        "name":"name",
+                        "label":"FORM_NAME_VM4MS_VM4MS_WEB_OBJECT",
+                        "required":true,
+                        "nb_cols":4
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"codemirror",
+                        "name":"definition",
+                        "label":"FORM_DEFINITION_VM4MS_VM4MS_WEB_OBJECT",
+                        "nb_cols":12,
+                        "codemirrorOptions":{
+                            "runnable":true,
+                            "lineNumbers":true,
+                            "matchBrackets":true,
+                            "mode":"map",
+                            "indentUnit":4,
+                            "indentWithTabs":true,
+                            "enterMode":"keep",
+                            "tabMode":"shift",
+                            "appHeight":"70%"
+                        }
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"button",
+                        "class":"btn-ungroup btn-group-sm",
+                        "nb_cols":12,
+                        "buttons":[
+                            {
+                                "type":"submit",
+                                "name":"form_submit",
+                                "label":"FORM_UPDATE",
+                                "class":"btn-primary"
+                            },
+                            {
+                                "type":"button",
+                                "name":"clone_form",
+                                "label":"FORM_CLONE",
+                                "class":"btn-primary",
+                                "event":"cloneSectionForm()"
+                            },
+                            {
+                                "type":"button",
+                                "name":"return_list",
+                                "label":"FORM_RETURN_LIST",
+                                "class":"btn-primary",
+                                "event":"setMode(\"search\")"
+                            }
+                        ]
+                    }
+                ]
+            }
+        ]
+    },
+    "insert":{
+        "name":"vm4ms_web_object_insert_form",
+        "title":"FORM_TITLE_VM4MS_VM4MS_WEB_OBJECT",
+        "input_size":"xs",
+        "event":"sendSimpleForm()",
+        "afterEvent":"editSectionForm()",
+        "nb_cols":12,
+        "rows":[
+            {
+                "fields":[
+                    {
+                        "type":"text",
+                        "name":"name",
+                        "label":"FORM_NAME_VM4MS_VM4MS_WEB_OBJECT",
+                        "required":true,
+                        "nb_cols":4
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"codemirror",
+                        "name":"definition",
+                        "label":"FORM_DEFINITION_VM4MS_VM4MS_WEB_OBJECT",
+                        "nb_cols":12,
+                        "codemirrorOptions":{
+                            "runnable":true,
+                            "lineNumbers":true,
+                            "matchBrackets":true,
+                            "mode":"map",
+                            "indentUnit":4,
+                            "indentWithTabs":true,
+                            "enterMode":"keep",
+                            "tabMode":"shift",
+                            "appHeight":"70%"
+                        }
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"button",
+                        "class":"btn-ungroup btn-group-sm",
+                        "nb_cols":12,
+                        "buttons":[
+                            {
+                                "type":"submit",
+                                "name":"form_submit",
+                                "label":"FORM_CREATE",
+                                "class":"btn-primary"
+                            },
+                            {
+                                "type":"button",
+                                "name":"return_list",
+                                "label":"FORM_RETURN_LIST",
+                                "class":"btn-primary",
+                                "event":"setMode(\"search\")"
+                            }
+                        ]
+                    }
+                ]
+            }
+        ]
+    },
+    "display":{
+        "name":"vm4ms_web_object_display_form",
+        "title":"FORM_TITLE_VM4MS_VM4MS_WEB_OBJECT",
+        "input_size":"xs",
+        "nb_cols":12,
+        "rows":[
+            {
+                "fields":[
+                    {
+                        "type":"label",
+                        "name":"web_id",
+                        "label":"FORM_WEB_ID_VM4MS_VM4MS_WEB_OBJECT",
+                        "nb_cols":6
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"label",
+                        "name":"name",
+                        "label":"FORM_NAME_VM4MS_VM4MS_WEB_OBJECT",
+                        "nb_cols":6
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"codemirror",
+                        "name":"definition",
+                        "label":"FORM_DEFINITION_VM4MS_VM4MS_WEB_OBJECT",
+                        "nb_cols":12,
+                        "codemirrorOptions":{
+                            "runnable":true,
+                            "lineNumbers":true,
+                            "matchBrackets":true,
+                            "mode":"map",
+                            "indentUnit":4,
+                            "indentWithTabs":true,
+                            "enterMode":"keep",
+                            "tabMode":"shift",
+                            "appHeight":"50%",
+                            "readOnly":"true"
+                        }
+                    }
+                ]
+            },
+            {
+                "fields":[
+                    {
+                        "type":"button",
+                        "class":"btn-ungroup btn-group-sm",
+                        "nb_cols":12,
+                        "buttons":[
+                            {
+                                "type":"button",
+                                "name":"return_list",
+                                "label":"FORM_RETURN_LIST",
+                                "class":"btn-primary",
+                                "event":"setMode(\"search\")"
+                            }
+                        ]
+                    }
+                ]
+            }
+        ]
+    }
+}
\ No newline at end of file
diff --git a/vmap/client/modules/vm4ms/forms/vm4ms/vm4ms_vm4ms_web_service_openlayers_test.json b/vmap/client/modules/vm4ms/forms/vm4ms/vm4ms_vm4ms_web_service_openlayers_test.json
new file mode 100755
index 0000000000000000000000000000000000000000..9d277ebff6faba9a01d41ed2ebe0cedf19999ca4
--- /dev/null
+++ b/vmap/client/modules/vm4ms/forms/vm4ms/vm4ms_vm4ms_web_service_openlayers_test.json
@@ -0,0 +1,92 @@
+{
+    "search":{
+    },
+    "update":{
+        "name":"wms_service_openlayers_test_update_form",
+        "title":"",
+        "input_size":"xs",
+        "event":"",
+        "nb_cols":12,
+        "rows":[
+            {
+                "fields": [
+                    {
+                        "type": "map_vmap",
+                        "name": "wms_service_test_map",
+                        "required": false,
+                        "nb_cols": 12,
+                        "id": "wms_service_test_map",
+                        "style": {
+                            "height": "100%",
+                            "margin-bottom": "-20px"
+                        },
+                        "map_options": {
+                            "center": {
+                                "extent": [
+                                ]
+                            },
+                            "type": "vmap",
+                            "controls": {
+                                "MP": false,
+                                "ZO": true,
+                                "SL": true,
+                                "CP": true
+                            },
+                            "layers": [],
+                            "interactions": {
+                                "multi_geometry": false,
+                                "full_screen": false,
+                                "RA": false,
+                                "RO": false,
+                                "ED": false,
+                                "DP": false,
+                                "DL": false,
+                                "DPol": false,
+                                "SE": true,
+                                "layer_tree": true
+                            },
+                            "draw_color": "rgba(54,184,255,0.6)",
+                            "contour_color": "rgba(0,0,0,0.4)",
+                            "contour_size": 2,
+                            "circle_radius": 6,
+                            "features": [],
+                            "coord_accuracy": 8,
+                            "tree": {
+                                "name": "Tree",
+                                "children": [
+                                    {
+                                        "view": {
+                                            "zoom": 6,
+                                            "maxZoom": 28,
+                                            "minZoom": 0,
+                                            "extent": [
+                                            ]
+                                        }
+                                    },
+                                    {
+                                        "name": "Open Street Map",
+                                        "children": [
+                                            {
+                                                "name": "Open Street Maps",
+                                                "visible": true,
+                                                "layerType": "osm",
+                                                "url": "https://{a-c}.tile.openstreetmap.org/{z}/{x}/{y}.png",
+                                                "select": true,
+                                                "index": 0
+                                            }
+                                        ],
+                                        "visible": true
+                                    }
+                                ]
+                            }
+                        }
+                    }
+                ]
+            }
+        ]
+    },
+    "insert":{
+    },
+    "display":{
+    }
+}
\ No newline at end of file
diff --git a/vmap/client/modules/vm4ms/javascript/controllers/layerTestsCtrl.js b/vmap/client/modules/vm4ms/javascript/controllers/layerTestsCtrl.js
new file mode 100755
index 0000000000000000000000000000000000000000..fad1e7d4f469dce0c6fea43d7beed6637ba0f703
--- /dev/null
+++ b/vmap/client/modules/vm4ms/javascript/controllers/layerTestsCtrl.js
@@ -0,0 +1,368 @@
+'use strict';
+
+// Google closure
+goog.provide("vitis.controllers.layerTests");
+goog.require("vitis.modules.main");
+
+/**
+ * layerTests Controller.
+ * .
+ * @param {angular.$log} $log Angular log service.
+ * @param {angular.$scope} $scope Angular scope.
+ * @param {angular.$templateRequest} $templateRequest Angular templateRequest service.
+ * @param {angular.$compile} $compile Angular compile.
+ * @param {angular.$timeout} $timeout Angular timeout service.
+ * @param {service} propertiesSrvc Paramètres des properties.
+ * @param {service} envSrvc Paramètres d'environnement.
+ * @param {service} sessionSrvc Service de gestion des sessions.
+ * @param {service} formSrvc Service de gestion des formulaires.
+ * @param {service} modesSrvc Liste des modes et objets de l'utilisateur.
+ * @ngInject
+ **/
+vitisApp.layerTestsCtrl = function ($log, $scope, $templateRequest, $compile, $timeout, propertiesSrvc, envSrvc, sessionSrvc, formSrvc, modesSrvc) {
+    // Initialisation
+    $log.info("initLayerTests");
+    // Etat de l'affichage des onglets.
+    $scope["aLayerTestTabs"] = {
+        "get_capabilities": {
+        },
+        "openlayers_test": {
+            "loaded": false
+        },
+        "maplayer_test": {
+            "loaded": false
+        },
+        "mapserver_log": {
+            "loaded": false,
+            "file_content": ""
+        },
+        "map_file": {
+            "loaded": false
+        }
+    };
+
+    // Sauve le nouveau scope crée dans la définition de l'onglet. 
+    modesSrvc["addScopeToObject"](envSrvc["oSelectedObject"]["name"], envSrvc["oSelectedMode"]["mode_id"], $scope);
+
+    /**
+     * testLayerWithOpenLayers function.
+     * Affiche le flux WMS avec OpenLayers.
+     * @param {boolean} bRefresh Force le raffraichissement de l'onglet.
+     **/
+    $scope["testLayerWithOpenLayers"] = function (bRefresh) {
+        $log.info("testLayerWithOpenLayers");
+        if (goog.isDefAndNotNull(propertiesSrvc["ms_cgi_url"]) && propertiesSrvc["ms_cgi_url"] != "") {
+            if (!$scope["aLayerTestTabs"]["openlayers_test"]["loaded"] || bRefresh === true) {
+                if (typeof ($scope["oGetCapabilities"]) != "undefined" && typeof ($scope["oGetCapabilities"]["json"]) != "undefined") {
+                    // Formulaire spécifique.
+                    $scope["sFormDefinitionName"] = envSrvc["sFormDefinitionName"] + "_openlayers_test";
+                    $scope["oFormRequestParams"] = {
+                        "sUrl": "modules/" + envSrvc["oSelectedMode"]["module_name"] + "/forms/" + envSrvc["oSelectedMode"]["mode_id"] + "/vm4ms_vm4ms_layer_openlayers_test.json"
+                    };
+                    // Vide le conteneur de la carte vMap.
+                    $("#layer_tests_layer_ol_map").empty();
+                    // Compilation du template de formulaire.
+                    $templateRequest("templates/formTpl.html").then(function (sTemplate) {
+                        $compile($("#layer_tests_layer_ol_map").html(sTemplate).contents())($scope);
+                        //
+                        var clearListener = $scope.$root.$on('formDefinitionLoaded', function () {
+                            // Supprime le "listener".
+                            clearListener();
+                            // 1ere projection compatible.
+                            var sProj = $scope.$root["proj"]["projections"][0]["code"];
+                            if (typeof ($scope["oGetCapabilities"]["json"]["Capability"]["Layer"]) != "undefined") {
+                                $scope.$root["proj"]["projections"].forEach(function (oProjection) {
+                                    var iProjIndex = $scope["oGetCapabilities"]["json"]["Capability"]["Layer"]["CRS"].indexOf(oProjection["code"]);
+                                    if (iProjIndex != -1 && typeof (sProj) == "undefined")
+                                        sProj = $scope["oGetCapabilities"]["json"]["Capability"]["Layer"]["CRS"][iProjIndex];
+                                });
+                            }
+                            var oMapFormElement = formSrvc["getFormElementDefinition"]("layer_test_map", $scope["sFormDefinitionName"]);
+                            oMapFormElement["map_options"]["proj"] = sProj;
+                            oMapFormElement["map_options"]["tree"]["children"][0]["view"]["projection"] = sProj;
+
+                            // Ajoute les projections manquantes.
+                            nsVitisComponent.Map.prototype.addCustomProjections();
+                            // Etendues.
+                            if (typeof ($scope["oGetCapabilities"]["json"]["Capability"]["Layer"]) != "undefined")
+                                oMapFormElement["map_options"]["center"]["extent"] = ol.proj.transformExtent($scope["oGetCapabilities"]["json"]["Capability"]["Layer"]["EX_GeographicBoundingBox"], "EPSG:4326", sProj);
+                            oMapFormElement["map_options"]["tree"]["children"][0]["view"]["extent"] = oMapFormElement["map_options"]["center"]["extent"];
+                            //oMapFormElement["map_options"]["tree"]["children"][0]["view"]["extent"] = $scope["oGetCapabilities"]["json"]["Capability"]["Layer"]["Layer"][0]["EX_GeographicBoundingBox"];
+                            //oMapFormElement["map_options"]["tree"]["children"][0]["view"]["extent"] = $scope["oGetCapabilities"]["json"]["Capability"]["Layer"]["Layer"][0]["BoundingBox"][0]["extent"];
+
+                            // Couches du flux WMS.
+                            if (typeof ($scope["oGetCapabilities"]["json"]["Capability"]["Layer"]) != "undefined") {
+                                $scope["oGetCapabilities"]["json"]["Capability"]["Layer"]["Layer"].forEach(function (oLayer, iLayerIndex) {
+                                    // Définition de la couche.
+                                    var oChildrenLayer = {
+                                        "name": oLayer["Name"],
+                                        "children": [
+                                            {
+                                                "name": oLayer["Name"],
+                                                "layerType": "imagewms",
+                                                "visible": true,
+                                                //"legend": "true",
+                                                "select": true,
+                                                "url": $scope["oGetCapabilities"]["service_url"],
+                                                "params": {
+                                                    "LAYERS": oLayer["Name"],
+                                                    "VERSION": "1.3.0",
+                                                    "TIMESTAMP": new Date().getTime()
+                                                },
+                                                "index": iLayerIndex + 1
+                                            }
+                                        ]
+                                    };
+                                    // Source de la couche.
+                                    if (typeof ($scope["oGetCapabilities"]["layers_sources"][oLayer["Name"]]) != "undefined") {
+                                        oChildrenLayer["children"][0]["attributions"] = [
+                                            new ol.Attribution({
+                                                html: $scope["oGetCapabilities"]["layers_sources"][oLayer["Name"]]
+                                            })
+                                                    //ol.source.OSM.ATTRIBUTION
+                                        ];
+                                    }
+                                    // Ajout de la couche.
+                                    oMapFormElement["map_options"]["tree"]["children"].push(oChildrenLayer);
+                                });
+                            }
+                            // Attends la création de la carte.
+                            var clearListener2 = $scope.$root.$on("OpenLayersMapCreated", function (event, oMap) {
+                                // Supprime le "listener".
+                                clearListener2();
+                                // Affichage des sources.
+                                oMap.MapObject.addControl(new ol.control.Attribution());
+                                // Evènement déclenché pas OpernLayers en cas d'erreur de chargement sur une des couches.
+                                $scope["aEventKey"] = [];
+                                oMap.MapObject.getLayers().getArray().forEach(function (oLayer) {
+                                    if (oLayer instanceof ol.layer.Image) {
+                                        $scope["aEventKey"][$scope["aEventKey"].length] = oLayer.getSource().on(["imageloaderror", "tileloaderror"], function (event) {
+                                            $scope.$root["displayLayerLoadingError"](event);
+                                        });
+                                    }
+                                });
+                            });
+                        });
+                    });
+                    //
+                    $scope["aLayerTestTabs"]["openlayers_test"]["loaded"] = true;
+                }
+            }
+        } else {
+            var oOptions = {
+                "className": "modal-danger",
+                "message": "ERROR_MS_CGI_URL_CONFIGURATION_CONFIGURATION_VM4MS_CONFIG"
+            };
+            $scope.$root["modalWindow"]("dialog", "REQUEST_ERROR", oOptions);
+        }
+    };
+
+    /**
+     * testLayerWithMapServer function.
+     * Affiche le flux WMS avec MapServer.
+     * @param {boolean} bRefresh Force le raffraichissement de l'onglet.
+     **/
+    $scope["testLayerWithMapServer"] = function (bRefresh) {
+        $log.info("testLayerWithMapServer");
+        if (goog.isDefAndNotNull(propertiesSrvc["ms_cgi_url"]) && propertiesSrvc["ms_cgi_url"] != "") {
+            if (!$scope["aLayerTestTabs"]["maplayer_test"]["loaded"] || bRefresh === true) {
+                if (typeof ($scope["oGetCapabilities"]) != "undefined" && typeof ($scope["oGetCapabilities"]["json"]) != "undefined") {
+                    // affiche la barre de scroll de l'iframe.
+                    $("#layer_tests_layer_ms_iframe").load(function () {
+                        var this_ = this;
+                        // injecte css
+                        $('link').each(function () {
+                            if (this.rel === 'stylesheet' && this.type === 'text/css') {
+                                var cssLink = document.createElement("link");
+                                cssLink.href = this.href;
+                                cssLink.rel = "stylesheet";
+                                cssLink.type = "text/css";
+                                this_.contentWindow.document.body.appendChild(cssLink);
+                            }
+                        });
+                        // style
+                        this.contentWindow.document.body.style.overflow = "auto";
+                    });
+                    // Liste des couches du flux WMS de test et de la couche à tester.
+                    var aLayers = [];
+                    if (typeof ($scope["oGetCapabilities"]["json"]["Capability"]["Layer"]) != "undefined") {
+                        $scope["oGetCapabilities"]["json"]["Capability"]["Layer"]["Layer"].forEach(function (oLayer) {
+                            aLayers.push(oLayer["Name"]);
+                        });
+                    }
+                    // Url de mapserver.
+                    var sIframeUrl = $scope["oGetCapabilities"]["service_url"] + "?ms_cgi_url=" + propertiesSrvc["ms_cgi_url"] + "&LAYERS=" + aLayers.join(" ") + "&no_cache=" + new Date().getTime();
+                    // Hauteur et largeur de l'image générée par MapServer.
+                    var oIframeWontainer = document.getElementById("layer_tests_layer_mapserver");
+                    if (oIframeWontainer !== null) {
+                        var iMapFileWidth = parseInt(oIframeWontainer.clientWidth * 0.75) - 23;
+                        var iMapFileHeight = oIframeWontainer.clientHeight - 83;
+                        sIframeUrl += "&MAPSIZE=" + iMapFileWidth + "+" + iMapFileHeight;
+                    }
+                    // Url de mapserver dans l'iframe.
+                    document.getElementById("layer_tests_layer_ms_iframe").contentWindow.location.href = sIframeUrl;
+                    // Chargement de MapServer dans l'iframe.
+                    $scope["aLayerTestTabs"]["maplayer_test"]["loaded"] = true;
+                }
+            } else {
+                // Affiche les scrollbars si besoin (bug chrome).
+                document.getElementById("layer_tests_layer_ms_iframe").contentWindow.document.body.style.overflow = "hidden";
+                setTimeout(function () {
+                    document.getElementById("layer_tests_layer_ms_iframe").contentWindow.document.body.style.overflow = "auto";
+                }, 100);
+            }
+        } else {
+            var oOptions = {
+                "className": "modal-danger",
+                "message": "ERROR_MS_CGI_URL_CONFIGURATION_CONFIGURATION_VM4MS_CONFIG"
+            };
+            $scope.$root["modalWindow"]("dialog", "REQUEST_ERROR", oOptions);
+        }
+    };
+
+    /**
+     * clearLayerTestsTabs function.
+     * Vide tous les onglets.
+     **/
+    $scope["clearLayerTestsTabs"] = function () {
+        $log.info("clearLayerTestsTabs");
+        //
+        document.getElementById("layer_tests_layer_ms_iframe").contentWindow.location.href = "about:blank";
+        $("#layer_tests_layer_ol_map").empty();
+    };
+
+    /**
+     * loadLayerMapServerLog function.
+     * Charge le fichier de log de MapServer dans l'éditeur CodeMirror.
+     * @param {boolean} bRefresh Force le raffraichissement de l'onglet.
+     **/
+    $scope["loadLayerMapServerLog"] = function (bRefresh) {
+        $log.info("loadLayerMapServerLog");
+        if (!$scope["aLayerTestTabs"]["mapserver_log"]["loaded"] || bRefresh === true) {
+            ajaxRequest({
+                "method": "GET",
+                "url": propertiesSrvc["web_server_name"] + "/" + propertiesSrvc["services_alias"] + "/vm4ms/layers/" + envSrvc["sId"] + "/MapServerLog",
+                "scope": $scope,
+                "success": function(response) {
+                    if (response["data"]["status"] == 1) {
+                        var oMapServerLogs = envSrvc["extractWebServiceData"]("layers", response["data"])[0];
+                        $scope["aLayerTestTabs"]["mapserver_log"]["file_content"] = oMapServerLogs["log_file_content"];
+                    } else {
+                        //
+                        var oOptions = {
+                            "className": "modal-danger"
+                        };
+                        // Message d'erreur ?
+                        if (response["data"]["errorMessage"] != null)
+                            oOptions["message"] = response["data"]["errorMessage"];
+                        $scope.$root["modalWindow"]("alert", "REQUEST_ERROR", oOptions);
+                    }
+                }
+            });
+            //
+            $scope["aLayerTestTabs"]["mapserver_log"]["loaded"] = true;
+        }
+    };
+
+    /**
+     * loadLayerMapFile function.
+     * Charge le fichier .map du flux wms de test de la couche dans l'éditeur CodeMirror.
+     * @param {boolean} bRefresh Force le raffraichissement de l'onglet.
+     **/
+    $scope["loadLayerMapFile"] = function (bRefresh) {
+        $log.info("loadLayerMapFile");
+        if (!$scope["aLayerTestTabs"]["map_file"]["loaded"] || bRefresh === true) {
+            // Requête pour récupérer les infos du fichier ".map".
+            var oParams = {
+                "ms_layer_id": envSrvc["sId"],
+                "creation": false
+            };
+                ajaxRequest({
+                    "method": "GET",
+                    "url": propertiesSrvc["web_server_name"] + "/" + propertiesSrvc["services_alias"] + "/vm4ms/Layers/" +  + envSrvc["sId"] + "/MapFile/",
+                    "params": oParams,
+                    "scope": $scope,
+                    "success": function(response) {
+                        if (response["data"]["status"] == 1) {
+                            var oLayer = envSrvc["extractWebServiceData"]("layers", response["data"])[0];
+                            $scope["oMapFileCodeMirrorEditor"]["setValue"](oLayer["map_file_content"]);
+                        } else {
+                            //
+                            var oOptions = {
+                                "className": "modal-danger"
+                            };
+                            // Message d'erreur ?
+                            if (response["data"]["errorMessage"] != null)
+                                oOptions["message"] = response["data"]["errorMessage"];
+                            $scope.$root["modalWindow"]("alert", "REQUEST_ERROR", oOptions);
+                        }
+                    }
+                });
+            //
+            $scope["aLayerTestTabs"]["map_file"]["loaded"] = true;
+        }
+    };
+
+    // Requête pour créer et récupérer le fichier ".map" de la couche.
+    var oFormData = new FormData();
+    oFormData.append("ms_layer_id", envSrvc["sId"]);
+    if (typeof (envSrvc["oFormValues"][envSrvc["sFormDefinitionName"]]) != "undefined") {
+        var sUserLogin = envSrvc["oFormValues"][envSrvc["sFormDefinitionName"]]["layer_login"];
+        var sUserPassword = envSrvc["oFormValues"][envSrvc["sFormDefinitionName"]]["layer_password"];
+        if (goog.isDefAndNotNull(sUserLogin) && goog.isDefAndNotNull(sUserPassword)) {
+            oFormData.append("user_login", sUserLogin);
+            oFormData.append("user_password", sUserPassword);
+        }
+    }
+    // Paramètres du webservice.
+    ajaxRequest({
+        "method": "POST",
+        "url": propertiesSrvc["web_server_name"] + "/" + propertiesSrvc["services_alias"] + "/vm4ms/Layers/MapFile",
+        "data": oFormData,
+        "scope": $scope,
+        "success": function(response) {
+            if (response["data"]["status"] == 1) {
+                var oLayer = envSrvc["extractWebServiceData"]("layers", response["data"])[0];
+                var sServiceUrl = propertiesSrvc["ms_cgi_url"] + "/test/" + oLayer["map_file_hash"] + "_" + oLayer["name"];
+                $scope.$root["getCapabilities"](sServiceUrl, {"showErrorMessage":false}).then(function (oGetCapabilities) {
+                    if (goog.isDefAndNotNull(oGetCapabilities)) {
+                        $scope["oGetCapabilities"] = oGetCapabilities;
+                        $scope["oGetCapabilities"]["service_url"] = sServiceUrl;
+                        if (typeof (oLayer["layers_sources"]) != "undefined")
+                            $scope["oGetCapabilities"]["layers_sources"] = oLayer["layers_sources"];
+                        // Lance le test de la couche avec MapServer (1er onglet affiché).
+                        $scope["testLayerWithMapServer"]();
+                    }
+                    else {
+                        // Affiche la section des logs en cas d'erreur.
+                        $timeout(function () {
+                            // Cache les onglets "GetCapabilities", "MapServer" et "OL3".
+                            document.querySelector(".layer-tests .nav-tabs > li:nth-child(1)").style.display = "none";
+                            document.querySelector(".layer-tests .nav-tabs > li:nth-child(2)").style.display = "none";
+                            // Affiche les logs.
+                            document.querySelector(".layer-tests .nav-tabs > li > a[aria-controls='layer_mapserver_log']").click();
+                        });
+                    }
+                });
+            } else {
+                // Supprime le précédent getCapabilities.
+                delete $scope["oGetCapabilities"];
+                // Vide les onglets
+                $scope["clearLayerTestsTabs"]();
+                // Rechargement obligatoire de tous les onglets.
+                $scope["aLayerTestTabs"]["openlayers_test"]["loaded"] = false;
+                $scope["aLayerTestTabs"]["maplayer_test"]["loaded"] = false;
+                //
+                var oOptions = {
+                    "className": "modal-danger"
+                };
+                // Message d'erreur ?
+                if (response["data"]["errorMessage"] != null)
+                    oOptions["message"] = response["data"]["errorMessage"];
+                $scope.$root["modalWindow"]("alert", "REQUEST_ERROR", oOptions);
+            }
+        }
+    });
+    //
+};
+vitisApp.module.controller("layerTestsCtrl", vitisApp.layerTestsCtrl);
diff --git a/vmap/client/modules/vm4ms/javascript/controllers/mapServerSymbolsCtrl.js b/vmap/client/modules/vm4ms/javascript/controllers/mapServerSymbolsCtrl.js
new file mode 100755
index 0000000000000000000000000000000000000000..4a4d0f81fbb2351104763a1a4f31b46bd76ebe24
--- /dev/null
+++ b/vmap/client/modules/vm4ms/javascript/controllers/mapServerSymbolsCtrl.js
@@ -0,0 +1,65 @@
+'use strict';
+
+// Google closure
+goog.provide("vitis.controllers.mapServerSymbols");
+goog.require("vitis.modules.main");
+
+/**
+ * mapServerSymbols Controller.
+ * .
+ * @param {angular.$log} $log Angular log service.
+ * @param {angular.$scope} $scope Angular scope.
+ * @param {angular.$timeout} $timeout Angular timeout service.
+ * @param {angular.$sce} $sce Angular sce service.
+ * @param {service} propertiesSrvc Paramètres des properties.
+ * @param {service} envSrvc Paramètres d'environnement.
+ * @param {service} sessionSrvc Service de gestion des sessions.
+ * @ngInject
+ **/
+vitisApp.mapServerSymbolsCtrl = function ($log, $scope, $timeout, $sce, propertiesSrvc, envSrvc, sessionSrvc) {
+        // Initialisation
+        $log.info("initMapServerSymbols");
+        /**
+         * loadMapServerSymbols function.
+         * Charge la liste des symboles.
+         **/
+        $scope["loadMapServerSymbols"] = function() {
+            $log.info("loadMapServerSymbols");
+            ajaxRequest({
+                "method": "GET",
+                "url": propertiesSrvc["web_server_name"] + "/" + propertiesSrvc["services_alias"] + "/vm4ms/mapserver/Symbols",
+                "scope": $scope,
+                "success": function(response) {
+                    if (response["data"]["status"] == 1) {
+                        var oMapServerSymbols = envSrvc["extractWebServiceData"]("mapserver", response["data"])[0];
+                        var oMapServerSymbols = angular.copy(oMapServerSymbols["symbols_content"])
+                        oMapServerSymbols.forEach(function(oSymbol, iSymbolIndex){
+                            oSymbol["definition"].forEach(function(sDefinition, iDefinitionIndex){
+                                oMapServerSymbols[iSymbolIndex]["definition"][iDefinitionIndex] = "<span>" + sDefinition.replace(/\t/g, '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;') + "</span>";
+                            });
+                        });
+                        $scope["oMapServerSymbols"] = oMapServerSymbols;
+                    } else {
+                        //
+                        var oOptions = {
+                            "className": "modal-danger"
+                        };
+                        // Message d'erreur ?
+                        if (response["data"]["errorMessage"] != null)
+                            oOptions["message"] = response["data"]["errorMessage"];
+                        $scope.$root["modalWindow"]("alert", "REQUEST_ERROR", oOptions);
+                    }
+                }
+            });
+        };
+        /**
+         * trustAsHtml function.
+         * Valeur sans filtre.
+         **/
+        $scope["trustAsHtml"] = function(value) {
+            return $sce.trustAsHtml(value);
+        };        
+        //
+        $scope["loadMapServerSymbols"]();
+};
+vitisApp.module.controller("mapServerSymbolsCtrl", vitisApp.mapServerSymbolsCtrl);
diff --git a/vmap/client/modules/vm4ms/javascript/controllers/wmsServiceTestsCtrl.js b/vmap/client/modules/vm4ms/javascript/controllers/wmsServiceTestsCtrl.js
new file mode 100755
index 0000000000000000000000000000000000000000..883eb6102a1f043f86eba71d76c4efb3874256f0
--- /dev/null
+++ b/vmap/client/modules/vm4ms/javascript/controllers/wmsServiceTestsCtrl.js
@@ -0,0 +1,461 @@
+/* global goog, ol, nsVitisComponent */
+
+'use strict';
+
+// Google closure
+goog.provide("vitis.controllers.wmsServiceTests");
+goog.require("vitis.modules.main");
+
+/**
+ * wmsServiceTests Controller.
+ * .
+ * @param {angular.$log} $log Angular log service.
+ * @param {angular.$scope} $scope Angular scope.
+ * @param {angular.$templateRequest} $templateRequest Angular templateRequest service.
+ * @param {angular.$compile} $compile Angular compile.
+ * @param {angular.$timeout} $timeout Angular timeout service.
+ * @param {angular.$rootScope} $rootScope Angular rootScope.
+ * @param {service} propertiesSrvc Paramètres des properties.
+ * @param {service} envSrvc Paramètres d'environnement.
+ * @param {service} sessionSrvc Service de gestion des sessions.
+ * @param {service} formSrvc Service de gestion des formulaires.
+ * @param {service} modesSrvc Liste des modes et objets de l'utilisateur.
+ * @ngInject
+ **/
+vitisApp.wmsServiceTestsCtrl = function ($log, $scope, $templateRequest, $compile, $timeout, $rootScope, propertiesSrvc, envSrvc, sessionSrvc, formSrvc, modesSrvc) {
+    // Initialisation
+    $log.info("initWmsServiceTests");
+    // Etat de l'affichage des onglets.
+    $scope["aWmsServiceTestTabs"] = {
+        "get_capabilities": {
+            "loaded": false
+        },
+        "openlayers_test": {
+            "loaded": false
+        },
+        "maplayer_test": {
+            "loaded": false
+        },
+        "mapserver_log": {
+            "loaded": false,
+            "file_content": ""
+        },
+        "map_file": {
+            "loaded": false
+        }
+    };
+
+    // Sauve le nouveau scope crée dans la définition de l'onglet. 
+    modesSrvc["addScopeToObject"](envSrvc["oSelectedObject"]["name"], envSrvc["oSelectedMode"]["mode_id"], $scope);
+
+    /**
+     * showWmsServiceGetCapabilities function.
+     * Affiche le résultat du "GetCapibilities" du flux WMS dans l'éditeur CodeMirror.
+     * @param {boolean} bRefresh Force le raffraichissement de l'onglet.
+     **/
+    $scope["showWmsServiceGetCapabilities"] = function (bRefresh) {
+        $log.info("showWmsServiceGetCapabilities");
+        if (goog.isDefAndNotNull(propertiesSrvc["ms_cgi_url"]) && propertiesSrvc["ms_cgi_url"] != "") {
+            if (!$scope["aWmsServiceTestTabs"]["get_capabilities"]["loaded"] || bRefresh === true) {
+                // Requête pour créer et récupérer le fichier ".map" du service wms.
+                var oFormData = new FormData();
+                oFormData.append("wmsservice_id", envSrvc["sId"]);
+                oFormData.append("type", "test");
+                if (typeof (envSrvc["oFormValues"][envSrvc["sFormDefinitionName"]]) != "undefined") {
+                    var sUserLogin = envSrvc["oFormValues"][envSrvc["sFormDefinitionName"]]["wms_service_login"];
+                    var sUserPassword = envSrvc["oFormValues"][envSrvc["sFormDefinitionName"]]["wms_service_password"];
+                    if (goog.isDefAndNotNull(sUserLogin) && goog.isDefAndNotNull(sUserPassword)) {
+                        oFormData.append("user_login", sUserLogin);
+                        oFormData.append("user_password", sUserPassword);
+                    }
+                }
+                ajaxRequest({
+                    "method": "POST",
+                    "url": propertiesSrvc["web_server_name"] + "/" + propertiesSrvc["services_alias"] + "/vm4ms/WmsServices/MapFile",
+                    "data": oFormData,
+                    "scope": $scope,
+                    "success": function (response) {
+                        if (response["data"]["status"] == 1) {
+                            var oWmsService = envSrvc["extractWebServiceData"]("wmsservices", response["data"])[0];
+                            var sServiceUrl = propertiesSrvc["ms_cgi_url"] + "/test/" + oWmsService["map_file_hash"];
+                            if (envSrvc["sId"] != propertiesSrvc["private_wms_service"])
+                                sServiceUrl += "_" + oWmsService["wmsservice_id"];
+                            $scope["aWmsServiceTestTabs"]["map_file_hash"] = oWmsService["map_file_hash"];
+                            $scope.$root["getCapabilities"](sServiceUrl, {"showErrorMessage": true}).then(function (oGetCapabilities) {
+                                if (goog.isDefAndNotNull(oGetCapabilities)) {
+                                    $scope["aWmsServiceTestTabs"]["get_capabilities"]["oCodeMirrorEditor"]["setValue"](oGetCapabilities["xml"]);
+                                    $scope["oGetCapabilities"] = oGetCapabilities;
+                                    $scope["oGetCapabilities"]["service_url"] = sServiceUrl;
+                                    if (typeof (oWmsService["layers_sources"]) != "undefined")
+                                        $scope["oGetCapabilities"]["layers_sources"] = oWmsService["layers_sources"];
+                                } else {
+                                    // Affiche la section des logs en cas d'erreur.
+                                    $timeout(function () {
+                                        // Cache les onglets "GetCapabilities", "MapServer" et "OL3".
+                                        document.querySelector(".wms-service-tests .nav-tabs > li:nth-child(1)").style.display = "none";
+                                        document.querySelector(".wms-service-tests .nav-tabs > li:nth-child(2)").style.display = "none";
+                                        document.querySelector(".wms-service-tests .nav-tabs > li:nth-child(3)").style.display = "none";
+                                        // Affiche les logs.
+                                        document.querySelector(".wms-service-tests .nav-tabs > li > a[aria-controls='wms_service_tests_wms_service_log']").click();
+                                    });
+                                }
+                            });
+                        } else {
+                            // Supprime le précédent getCapabilities.
+                            delete $scope["oGetCapabilities"];
+                            // Vide les onglets
+                            $scope["clearWmsServiceTestsTabs"]();
+                            // Rechargement obligatoire de tous les onglets.
+                            $scope["aWmsServiceTestTabs"]["get_capabilities"]["loaded"] = false;
+                            $scope["aWmsServiceTestTabs"]["openlayers_test"]["loaded"] = false;
+                            $scope["aWmsServiceTestTabs"]["maplayer_test"]["loaded"] = false;
+                            //
+                            var oOptions = {
+                                "className": "modal-danger"
+                            };
+                            // Message d'erreur ?
+                            if (response["data"]["errorMessage"] != null)
+                                oOptions["message"] = response["data"]["errorMessage"];
+                            $scope.$root["modalWindow"]("alert", "REQUEST_ERROR", oOptions);
+                        }
+                    }
+                });
+                //
+                $scope["aWmsServiceTestTabs"]["get_capabilities"]["loaded"] = true;
+            }
+        } else {
+            var oOptions = {
+                "className": "modal-danger",
+                "message": "ERROR_MS_CGI_URL_CONFIGURATION_CONFIGURATION_VM4MS_CONFIG"
+            };
+            $scope.$root["modalWindow"]("dialog", "REQUEST_ERROR", oOptions);
+        }
+    };
+
+    /**
+     * testWmsServiceWithOpenLayers function.
+     * Affiche le flux WMS avec OpenLayers.
+     * @param {boolean} bRefresh Force le raffraichissement de l'onglet.
+     **/
+    $scope["testWmsServiceWithOpenLayers"] = function (bRefresh) {
+        $log.info("testWmsServiceWithOpenLayers");
+        if (goog.isDefAndNotNull(propertiesSrvc["ms_cgi_url"]) && propertiesSrvc["ms_cgi_url"] != "") {
+            if (!$scope["aWmsServiceTestTabs"]["openlayers_test"]["loaded"] || bRefresh === true) {
+                if (typeof ($scope["oGetCapabilities"]) != "undefined" && typeof ($scope["oGetCapabilities"]["json"]) != "undefined") {
+                    // Formulaire spécifique.
+                    $scope["sFormDefinitionName"] = envSrvc["sFormDefinitionName"] + "_openlayers_test";
+                    $scope["oFormRequestParams"] = {
+                        "sUrl": "modules/" + envSrvc["oSelectedMode"]["module_name"] + "/forms/" + envSrvc["oSelectedMode"]["mode_id"] + "/vm4ms_vm4ms_web_service_openlayers_test.json"
+                    };
+                    // Vide le conteneur de la carte vMap.
+                    $("#wms_service_tests_wms_service_ol_map").empty();
+                    // Compilation du template de formulaire.
+                    $templateRequest("templates/formTpl.html").then(function (sTemplate) {
+                        $compile($("#wms_service_tests_wms_service_ol_map").html(sTemplate).contents())($scope);
+                        //
+                        var clearListener = $scope.$root.$on('formDefinitionLoaded', function () {
+                            // Supprime le "listener".
+                            clearListener();
+                            // 1ere projection compatible.
+                            var sProj = $scope.$root["proj"]["projections"][0]["code"];
+                            if (typeof ($scope["oGetCapabilities"]["json"]["Capability"]["Layer"]) != "undefined") {
+                                $scope.$root["proj"]["projections"].forEach(function (oProjection) {
+                                    var iProjIndex = $scope["oGetCapabilities"]["json"]["Capability"]["Layer"]["CRS"].indexOf(oProjection["code"]);
+                                    if (iProjIndex != -1 && typeof (sProj) == "undefined")
+                                        sProj = $scope["oGetCapabilities"]["json"]["Capability"]["Layer"]["CRS"][iProjIndex];
+                                });
+                            }
+                            var oMapFormElement = formSrvc["getFormElementDefinition"]("wms_service_test_map", $scope["sFormDefinitionName"]);
+                            oMapFormElement["map_options"]["bLayersTreeOpen"] = true;
+                            oMapFormElement["map_options"]["proj"] = sProj;
+                            oMapFormElement["map_options"]["tree"]["children"][0]["view"]["projection"] = sProj;
+
+                            // Ajoute les projections manquantes.
+                            nsVitisComponent.Map.prototype.addCustomProjections();
+                            // Etendues.
+                            if (goog.isDefAndNotNull($scope["oGetCapabilities"]["json"]["Capability"]["Layer"])) {
+                                oMapFormElement["map_options"]["center"]["extent"] = ol.proj.transformExtent($scope["oGetCapabilities"]["json"]["Capability"]["Layer"]["EX_GeographicBoundingBox"], "EPSG:4326", sProj);
+                            } else {
+                                var oExtents = {
+                                    'EPSG:3857': [-1901744.2199433097, 4779520.942381757, 2501744.2199433097, 7220479.057618243],
+                                    'EPSG:2154': [-2648.2345550218597, 6231825.554877603, 7024177.333740164, 7024177.333740164],
+                                    'EPSG:4326': [-4.6307373046875, 42.802734375, 51.0205078125, 51.0205078125]
+                                };
+                                if (goog.isDefAndNotNull(oExtents[sProj])) {
+                                    oMapFormElement["map_options"]["center"]["extent"] = oExtents[sProj];
+                                }
+                            }
+                            oMapFormElement["map_options"]["tree"]["children"][0]["view"]["extent"] = oMapFormElement["map_options"]["center"]["extent"];
+                            //oMapFormElement["map_options"]["tree"]["children"][0]["view"]["extent"] = $scope["oGetCapabilities"]["json"]["Capability"]["Layer"]["Layer"][0]["EX_GeographicBoundingBox"];
+                            //oMapFormElement["map_options"]["tree"]["children"][0]["view"]["extent"] = $scope["oGetCapabilities"]["json"]["Capability"]["Layer"]["Layer"][0]["BoundingBox"][0]["extent"];
+                            // Couches du flux WMS.
+                            if (typeof ($scope["oGetCapabilities"]["json"]["Capability"]["Layer"]) != "undefined") {
+
+                                var oService = {
+                                    "name": 'Service',
+                                    "children": []
+                                };
+
+                                var aLayers = angular.copy($scope["oGetCapabilities"]["json"]["Capability"]["Layer"]["Layer"]);
+
+                                // Réordonne les couches à afficher par nom
+                                aLayers.sort(function (a, b) {
+                                    return a["Name"].localeCompare(b["Name"]);
+                                });
+
+                                aLayers.forEach(function (oLayer, iLayerIndex) {
+                                    // Définition de la couche.
+                                    var oChildrenLayer = {
+                                        "name": oLayer["Name"],
+                                        "layerType": "imagewms",
+                                        "visible": false,
+                                        "legend": "true",
+                                        "select": true,
+                                        "url": $scope["oGetCapabilities"]["service_url"],
+                                        "params": {
+                                            "LAYERS": oLayer["Name"],
+                                            "VERSION": "1.3.0",
+                                            "TIMESTAMP": new Date().getTime()
+                                        },
+                                        "index": iLayerIndex + 1
+                                    };
+                                    // Source de la couche.
+                                    if (typeof ($scope["oGetCapabilities"]["layers_sources"][oLayer["Name"]]) != "undefined") {
+                                        oChildrenLayer["attributions"] = [
+                                            new ol.Attribution({
+                                                html: $scope["oGetCapabilities"]["layers_sources"][oLayer["Name"]]
+                                            })
+                                                    //ol.source.OSM.ATTRIBUTION
+                                        ];
+                                    }
+                                    // Ajout de la couche.
+                                    oService['children'].push(oChildrenLayer);
+                                });
+
+                                // Ajout du service.
+                                oMapFormElement["map_options"]["tree"]["children"].push(oService);
+                            }
+                            // Attends la création de la carte.
+                            var clearListener2 = $scope.$root.$on("OpenLayersMapCreated", function (event, oMap) {
+                                // Supprime le "listener".
+                                clearListener2();
+                                // Affichage des sources.
+                                oMap.MapObject.addControl(new ol.control.Attribution());
+                                // Evènement déclenché pas OpernLayers en cas d'erreur de chargement sur une des couches.
+                                $scope["aEventKey"] = [];
+                                oMap.MapObject.getLayers().getArray().forEach(function (oLayer) {
+                                    if (oLayer instanceof ol.layer.Image) {
+                                        $scope["aEventKey"][$scope["aEventKey"].length] = oLayer.getSource().on(["imageloaderror", "tileloaderror"], function (event) {
+                                            $rootScope["displayLayerLoadingError"](event);
+                                        });
+                                    }
+                                });
+                            });
+                        });
+                    });
+                    //
+                    $scope["aWmsServiceTestTabs"]["openlayers_test"]["loaded"] = true;
+                }
+            }
+        } else {
+            var oOptions = {
+                "className": "modal-danger",
+                "message": "ERROR_MS_CGI_URL_CONFIGURATION_CONFIGURATION_VM4MS_CONFIG"
+            };
+            $scope.$root["modalWindow"]("dialog", "REQUEST_ERROR", oOptions);
+        }
+    };
+
+    /**
+     * testWmsServiceWithMapServer function.
+     * Affiche le flux WMS avec MapServer.
+     * @param {boolean} bRefresh Force le raffraichissement de l'onglet.
+     **/
+    $scope["testWmsServiceWithMapServer"] = function (bRefresh) {
+        $log.info("testWmsServiceWithMapServer");
+        if (goog.isDefAndNotNull(propertiesSrvc["ms_cgi_url"]) && propertiesSrvc["ms_cgi_url"] != "") {
+            if (!$scope["aWmsServiceTestTabs"]["maplayer_test"]["loaded"] || bRefresh === true) {
+                if (typeof ($scope["oGetCapabilities"]) != "undefined" && typeof ($scope["oGetCapabilities"]["json"]) != "undefined") {
+                    if (typeof ($scope["oGetCapabilities"]["json"]["Capability"]["Layer"]) != "undefined") {
+
+                        $scope['aMSTestLayers'] = [];
+                        $('#wms_service_tests_layer_select_modal').modal('show');
+
+                        $scope["testWmsServiceSelectedLayersWithMapServer"] = function (aLayers) {
+                            $log.info("testWmsServiceSelectedLayersWithMapServer", aLayers);
+
+                            $('#wms_service_tests_layer_select_modal').modal('hide');
+                            // Url de mapserver dans l'iframe.
+                            $scope["aWmsServiceTestTabs"]["map_file"]
+                            var sServiceUrl = propertiesSrvc["ms_cgi_url"] + "/test/" + $scope["aWmsServiceTestTabs"]["map_file_hash"];
+                            if (envSrvc["sId"] != propertiesSrvc["private_wms_service"])
+                                sServiceUrl += "_" + envSrvc["sId"];
+                            var sIframeUrl = sServiceUrl + "?ms_cgi_url=" + propertiesSrvc["ms_cgi_url"] + "&LAYERS=" + aLayers.join(" ") + "&no_cache=" + new Date().getTime();
+                            // Hauteur et largeur de l'image générée par MapServer.
+                            var oIframeWontainer = document.getElementById("wms_service_tests_wms_service_mapserver");
+                            if (oIframeWontainer !== null) {
+                                var iMapFileWidth = parseInt(oIframeWontainer.clientWidth * 0.75) - 23;
+                                var iMapFileHeight = oIframeWontainer.clientHeight - 83;
+                                sIframeUrl += "&MAPSIZE=" + iMapFileWidth + "+" + iMapFileHeight;
+                            }
+                            // Chargement de l'image dans l'iframe.
+                            document.getElementById("wms_service_tests_wms_service_ms_iframe").contentWindow.location.href = sIframeUrl;
+                            //
+                            $scope["aWmsServiceTestTabs"]["maplayer_test"]["loaded"] = true;
+
+                            $("#wms_service_tests_wms_service_ms_iframe").load(function () {
+                                var this_ = this;
+                                // injecte css
+                                $('link').each(function () {
+                                    if (this.rel === 'stylesheet' && this.type === 'text/css') {
+                                        var cssLink = document.createElement("link");
+                                        cssLink.href = this.href;
+                                        cssLink.rel = "stylesheet";
+                                        cssLink.type = "text/css";
+                                        this_.contentWindow.document.body.appendChild(cssLink);
+                                    }
+                                });
+                                // style
+                                this.contentWindow.document.body.style.overflow = "auto";
+                            });
+                        }
+
+                        $scope["testWmsServiceSelectAllLayers"] = function () {
+                            $scope['aMSTestLayers'] = [];
+                            $scope["oGetCapabilities"]["json"]["Capability"]["Layer"]["Layer"].forEach(function (oLayer) {
+                                $scope['aMSTestLayers'].push(oLayer["Name"]);
+                            });
+                        }
+                    }
+                }
+            }
+        } else {
+            var oOptions = {
+                "className": "modal-danger",
+                "message": "ERROR_MS_CGI_URL_CONFIGURATION_CONFIGURATION_VM4MS_CONFIG"
+            };
+            $scope.$root["modalWindow"]("dialog", "REQUEST_ERROR", oOptions);
+        }
+    };
+
+    /**
+     * refreshWmsServiceTestsTab function.
+     * Rechargement et affichage de l'onglet "GetCapabilities" avec les identifiants spécifiés.
+     **/
+    $scope.$root["refreshWmsServiceTestsTab"] = function () {
+        $log.info("refreshWmsServiceTestsTab");
+        // Login + mdp obligatoires (si un des 2 est spécifié).
+        var sUserLogin = envSrvc["oFormValues"][envSrvc["sFormDefinitionName"]]["wms_service_login"];
+        var sUserPassword = envSrvc["oFormValues"][envSrvc["sFormDefinitionName"]]["wms_service_password"];
+        var formScope = angular.element("form[name='" + envSrvc["oFormDefinition"][envSrvc["sFormDefinitionName"]]["name"]).scope();
+        var bRefresh = true;
+        formScope[envSrvc["oFormDefinition"][envSrvc["sFormDefinitionName"]]["name"]]["wms_service_login"]["$setValidity"]("wms_service_login", true);
+        formScope[envSrvc["oFormDefinition"][envSrvc["sFormDefinitionName"]]["name"]]["wms_service_password"]["$setValidity"]("wms_service_password", true);
+        if (!((!goog.isDefAndNotNull(sUserLogin) || sUserLogin == "") && (!goog.isDefAndNotNull(sUserPassword) || sUserPassword == ""))) {
+            if ((!goog.isDefAndNotNull(sUserLogin) || sUserLogin == "")) {
+                formScope[envSrvc["oFormDefinition"][envSrvc["sFormDefinitionName"]]["name"]]["wms_service_login"]["$setValidity"]("wms_service_login", false);
+                formScope[envSrvc["oFormDefinition"][envSrvc["sFormDefinitionName"]]["name"]]["wms_service_login"]["$setDirty"]();
+                bRefresh = false;
+            }
+            if ((!goog.isDefAndNotNull(sUserPassword) || sUserPassword == "")) {
+                formScope[envSrvc["oFormDefinition"][envSrvc["sFormDefinitionName"]]["name"]]["wms_service_password"]["$setValidity"]("wms_service_password", false);
+                formScope[envSrvc["oFormDefinition"][envSrvc["sFormDefinitionName"]]["name"]]["wms_service_password"]["$setDirty"]();
+                bRefresh = false;
+            }
+        }
+        // Création du fichier ".map" et rechargement et affichage de l'onglet "GetCapabilities".
+        if (bRefresh) {
+            $(".wms-service-tests a[href='#wms_service_tests_get_capabilities']").tab('show');
+            $scope["showWmsServiceGetCapabilities"](true);
+            // Onglets à recharger.
+            $scope["aWmsServiceTestTabs"]["openlayers_test"]["loaded"] = false;
+            $scope["aWmsServiceTestTabs"]["maplayer_test"]["loaded"] = false;
+            $scope["aWmsServiceTestTabs"]["mapserver_log"]["loaded"] = false;
+            $scope["aWmsServiceTestTabs"]["map_file"]["loaded"] = false;
+        }
+    };
+
+    /**
+     * clearWmsServiceTestsTabs function.
+     * Vide tous les onglets.
+     **/
+    $scope["clearWmsServiceTestsTabs"] = function () {
+        $log.info("clearWmsServiceTestsTabs");
+        //
+        $scope["aWmsServiceTestTabs"]["get_capabilities"]["oCodeMirrorEditor"]["setValue"]("");
+        document.getElementById("wms_service_tests_wms_service_ms_iframe").contentWindow.location.href = "about:blank";
+        $("#wms_service_tests_wms_service_ol_map").empty();
+    };
+
+    /**
+     * loadWmsServiceMapServerLog function.
+     * Charge le fichier de log de MapServer dans l'éditeur CodeMirror.
+     * @param {boolean} bRefresh Force le raffraichissement de l'onglet.
+     **/
+    $scope["loadWmsServiceMapServerLog"] = function (bRefresh) {
+        $log.info("loadWmsServiceMapServerLog");
+        if (!$scope["aWmsServiceTestTabs"]["mapserver_log"]["loaded"] || bRefresh === true) {
+            ajaxRequest({
+                "method": "GET",
+                "url": propertiesSrvc["web_server_name"] + "/" + propertiesSrvc["services_alias"] + "/vm4ms/wmsservices/" + envSrvc["sId"] + "/MapServerLog",
+                "scope": $scope,
+                "success": function (response) {
+                    if (response["data"]["status"] == 1) {
+                        var oMapServerLogs = envSrvc["extractWebServiceData"]("wmsservices", response["data"])[0];
+                        $scope["aWmsServiceTestTabs"]["mapserver_log"]["file_content"] = oMapServerLogs["log_file_content"];
+                    } else {
+                        //
+                        var oOptions = {
+                            "className": "modal-danger"
+                        };
+                        // Message d'erreur ?
+                        if (response["data"]["errorMessage"] != null)
+                            oOptions["message"] = response["data"]["errorMessage"];
+                        $scope.$root["modalWindow"]("alert", "REQUEST_ERROR", oOptions);
+                    }
+                }
+            });
+            //
+            $scope["aWmsServiceTestTabs"]["mapserver_log"]["loaded"] = true;
+        }
+    };
+
+    /**
+     * loadWmsServiceMapFile function.
+     * Charge le fichier .map du flux wms testé dans l'éditeur CodeMirror.
+     * @param {boolean} bRefresh Force le raffraichissement de l'onglet.
+     **/
+    $scope["loadWmsServiceMapFile"] = function (bRefresh) {
+        $log.info("loadWmsServiceMapFile");
+        if (!$scope["aWmsServiceTestTabs"]["map_file"]["loaded"] || bRefresh === true) {
+            var oParams = {
+                "wmsservice_id": envSrvc["sId"],
+                "type": "test"
+            };
+            ajaxRequest({
+                "method": "GET",
+                "url": propertiesSrvc["web_server_name"] + "/" + propertiesSrvc["services_alias"] + "/vm4ms/wmsservices/" + envSrvc["sId"] + "/MapFile",
+                "params": oParams,
+                "scope": $scope,
+                "success": function (response) {
+                    if (response["data"]["status"] == 1) {
+                        var oWmsService = envSrvc["extractWebServiceData"]("wmsservices", response["data"])[0];
+                        $scope["aWmsServiceTestTabs"]["map_file"]["oCodeMirrorEditor"]["setValue"](oWmsService["map_file_content"]);
+                    } else {
+                        //
+                        var oOptions = {
+                            "className": "modal-danger"
+                        };
+                        // Message d'erreur ?
+                        if (response["data"]["errorMessage"] != null)
+                            oOptions["message"] = response["data"]["errorMessage"];
+                        $scope.$root["modalWindow"]("alert", "REQUEST_ERROR", oOptions);
+                    }
+                }
+            });
+            //
+            $scope["aWmsServiceTestTabs"]["map_file"]["loaded"] = true;
+        }
+    };
+};
+vitisApp.module.controller("wmsServiceTestsCtrl", vitisApp.wmsServiceTestsCtrl);
diff --git a/vmap/client/modules/vm4ms/javascript/deps.js b/vmap/client/modules/vm4ms/javascript/deps.js
new file mode 100755
index 0000000000000000000000000000000000000000..cf7bb4f17e1511f481a4960dc831f1db54408d68
--- /dev/null
+++ b/vmap/client/modules/vm4ms/javascript/deps.js
@@ -0,0 +1,14 @@
+'use strict';
+/* 
+ * Dépendances de closure pour le module "vm4ms".
+ */
+goog.provide("vmap.vm4ms");
+
+goog.require("vitis.controllers.wmsServiceTests");
+goog.require("vitis.controllers.layerTests");
+
+goog.require("vitis.directives.wmsServiceTests");
+goog.require("vitis.directives.layerTests");
+
+goog.require("vitis.controllers.mapServerSymbols");
+goog.require("vitis.directives.mapServerSymbols");
diff --git a/vmap/client/modules/vm4ms/javascript/directives/layerTestsDrtv.js b/vmap/client/modules/vm4ms/javascript/directives/layerTestsDrtv.js
new file mode 100755
index 0000000000000000000000000000000000000000..0745f25232888c6e509ca52ee93128bab6f6ecae
--- /dev/null
+++ b/vmap/client/modules/vm4ms/javascript/directives/layerTestsDrtv.js
@@ -0,0 +1,43 @@
+'use strict';
+
+// Google closure
+goog.provide("vitis.directives.layerTests");
+goog.require("vitis.modules.main");
+
+/**
+ * appLayerTests directive.
+ * .
+ * @ngInject
+ **/
+vitisApp.appLayerTestsDrtv = function() {
+    return {
+        restrict: 'A',
+        controller : 'layerTestsCtrl',
+        controllerAs : 'ctrl',
+        scope: true,
+        link: function (scope, element, attrs) {
+            // Hauteur du conteneur des onglets.
+            document.querySelector(".layer-test-dialog-modal-window .bootbox-body").style.height = "calc(100% - 3px)";
+            // Hauteur du conteneur des onglets.
+            element[0].querySelector(".tab-content").style.height = "calc(100% - 46px)";
+            // Création de l'élement codeMirror pour le fichier map.
+            scope["oMapFileCodeMirrorEditor"] = CodeMirror["fromTextArea"](document.getElementById("layer_map_file_textarea"), {
+                "lineNumbers": true,
+                "mode":"map",
+                "indentUnit": 4,
+                "readOnly": "true"
+            });
+            // Dimensions de l'éditeur CodeMirror.
+            scope["oMapFileCodeMirrorEditor"]["setSize"]("100%", "100%");
+            // Attends la suppression du scope.
+            scope.$on("$destroy", function () {
+                // Supprime tous les "listeners" enregistrés.
+                if (typeof(scope["aEventKey"]) != "undefined" && scope["aEventKey"].length > 0) {
+                    ol.Observable.unByKey(scope["aEventKey"]);
+                    scope["aEventKey"].length = 0;
+                }
+            });
+        }
+    }
+};
+vitisApp.module.directive("appLayerTests", vitisApp.appLayerTestsDrtv);
\ No newline at end of file
diff --git a/vmap/client/modules/vm4ms/javascript/directives/mapServerSymbolsDrtv.js b/vmap/client/modules/vm4ms/javascript/directives/mapServerSymbolsDrtv.js
new file mode 100755
index 0000000000000000000000000000000000000000..bb2b5c46a2fca14e12878893a7b942e5ce23d8a1
--- /dev/null
+++ b/vmap/client/modules/vm4ms/javascript/directives/mapServerSymbolsDrtv.js
@@ -0,0 +1,35 @@
+'use strict';
+
+// Google closure
+goog.provide("vitis.directives.mapServerSymbols");
+goog.require("vitis.modules.main");
+
+/**
+ * appMapServerSymbols directive.
+ * .
+ * @ngInject
+ **/
+vitisApp.appMapServerSymbolsDrtv = function() {
+    return {
+        restrict: 'A',
+        controller : 'mapServerSymbolsCtrl',
+        controllerAs : 'ctrl',
+        scope: true
+    }
+};
+vitisApp.module.directive("appMapServerSymbols", vitisApp.appMapServerSymbolsDrtv);
+
+/**
+ * appMapServerSymbolsCollapse directive.
+ * Cache toutes les définitions des symboles.
+ **/
+vitisApp.appMapServerSymbolsCollapseDrtv = function () {
+    return {
+        replace: true,
+        link: function (scope, element, attrs) {
+            if (scope["$index"])
+                $(element).parent().find(".collapse").collapse('hide');
+        }
+    }
+};
+vitisApp.module.directive("appMapServerSymbolsCollapse", vitisApp.appMapServerSymbolsCollapseDrtv);
\ No newline at end of file
diff --git a/vmap/client/modules/vm4ms/javascript/directives/wmsServiceTestsDrtv.js b/vmap/client/modules/vm4ms/javascript/directives/wmsServiceTestsDrtv.js
new file mode 100755
index 0000000000000000000000000000000000000000..3cd42f8961d85fb06e30966f4b7c936f286005e8
--- /dev/null
+++ b/vmap/client/modules/vm4ms/javascript/directives/wmsServiceTestsDrtv.js
@@ -0,0 +1,85 @@
+'use strict';
+
+// Google closure
+goog.provide("vitis.directives.wmsServiceTests");
+goog.require("vitis.modules.main");
+
+/**
+ * appWmsServiceTests directive.
+ * .
+ * @ngInject
+ **/
+vitisApp.appWmsServiceTestsDrtv = function () {
+    return {
+        restrict: 'A',
+        controller: 'wmsServiceTestsCtrl',
+        controllerAs: 'ctrl',
+        scope: true,
+        link: function (scope, element, attrs) {
+            // Hauteur du conteneur des onglets.
+            element[0].querySelector(".tab-content").style.height = "calc(100% - 46px)";
+            // Création de l'élement codeMirror pour le GetCapabilities.
+            var oGetCapabilitiesCmEditor = CodeMirror["fromTextArea"](document.getElementById("wms_service_tests_get_capabilities_textarea"), {
+                "lineNumbers": false,
+                "mode": "xml",
+                "readOnly": "true",
+                "indentUnit": 4
+            });
+            scope["aWmsServiceTestTabs"]["get_capabilities"]["oCodeMirrorEditor"] = oGetCapabilitiesCmEditor;
+            // Dimensions de l'éditeur CodeMirror.
+            oGetCapabilitiesCmEditor["setSize"]("100%", "100%");
+            // Lance un GetCapabilities (1er onglet affiché).
+            scope["showWmsServiceGetCapabilities"]();
+            // Création de l'élement codeMirror pour le fichier map.
+            var oMapFileCmEditor = CodeMirror["fromTextArea"](document.getElementById("wms_service_tests_wms_service_map_file_textarea"), {
+                "lineNumbers": true,
+                "mode":"map",
+                "indentUnit": 4,
+                "readOnly": "true"
+            });
+            scope["aWmsServiceTestTabs"]["map_file"]["oCodeMirrorEditor"] = oMapFileCmEditor;
+            // Dimensions de l'éditeur CodeMirror.
+            oMapFileCmEditor["setSize"]("100%", "100%");
+            // Attends la suppression du scope.
+            scope.$on("$destroy", function () {
+                // Supprime tous les "listeners" enregistrés.
+                if (typeof (scope["aEventKey"]) != "undefined" && scope["aEventKey"].length > 0) {
+                    ol.Observable.unByKey(scope["aEventKey"]);
+                    scope["aEventKey"].length = 0;
+                }
+            });
+        }
+    }
+};
+vitisApp.module.directive("appWmsServiceTests", vitisApp.appWmsServiceTestsDrtv);
+
+/**
+ * appWmsServiceTestsConnectionForm directive.
+ * Charge le template du formulaire de connexion.
+ * @param {angular.$templateRequest} $templateRequest Angular templateRequest service.
+ * @param {angular.$compile} $compile Angular compile.
+ * @param {service} envSrvc Paramètres d'environnement.
+ * @param {service} propertiesSrvc Paramètres des properties.
+ * @ngInject
+ **/
+vitisApp.appWmsServiceTestsConnectionFormDrtv = function ($templateRequest, $compile, envSrvc, propertiesSrvc) {
+    return {
+        replace: true,
+        link: function (scope, element, attrs) {
+            // Compile le formulaire si le flux WMS est privé.
+            if (envSrvc["sId"] == propertiesSrvc["private_wms_service"]) {
+                $templateRequest("templates/formTpl.html").then(function (sTemplate) {
+                    $compile($(element).html(sTemplate).contents())(scope);
+                    // Attends le chargement de la structure et des données du formulaire.
+                    var clearListener = scope.$root.$on('formExtracted', function (event, sFormDefinitionName) {
+                        // Supprime le listener.
+                        clearListener();
+                        // Hauteur du conteneur des onglets.
+                        element[0].parentNode.parentNode.firstChild.style.height = "Calc(100% - 60px)";
+                    });
+                });
+            }
+        }
+    }
+};
+vitisApp.module.directive("appWmsServiceTestsConnectionForm", vitisApp.appWmsServiceTestsConnectionFormDrtv);
\ No newline at end of file
diff --git a/vmap/client/modules/vm4ms/javascript/script_module.js b/vmap/client/modules/vm4ms/javascript/script_module.js
new file mode 100755
index 0000000000000000000000000000000000000000..1cc2443310f2d2ee6a13beff8838776363f3fe00
--- /dev/null
+++ b/vmap/client/modules/vm4ms/javascript/script_module.js
@@ -0,0 +1,1693 @@
+/* global vitisApp, goog */
+
+'use strict';
+
+goog.provide('vmap.vm4ms.script_module');
+goog.require('vmap.vm4ms');
+
+vitisApp.on('appMainDrtvLoaded', function () {
+    /**
+     * appWmsServiceDescriptionColumn directive.
+     * Mise en forme de la colonne "description" dans la liste des onglets "Flux WMS".
+     * @param {service} $translate Translate service.
+     * @ngInject
+     **/
+    vitisApp.appWmsServiceDescriptionColumnDrtv = function ($translate) {
+        return {
+            link: function (scope, element, attrs) {
+
+                // 1er affichage ou tri de la liste : maj de la mise en forme.
+                var clearObserver = attrs.$observe("appWmsServiceDescriptionColumn", function (value) {
+                    // Si le champ est vide : supprime l'icône.
+                    if (scope["row"]["entity"][scope["col"]["field"]] == null || scope["row"]["entity"][scope["col"]["field"]] == "")
+                        element[0].className = "";
+                    else {
+                        // Classes css (ui-grid + spécifiques).
+                        element[0].className = "ui-grid-cell-contents info-icon";
+                        // Traduction du titre et du contenu.
+                        $translate(["DESCRIPTION_TOOLTIP_TITLE_VMAP_MAP_MAP"]).then(function (translations) {
+                            // Création du "tooltip".
+                            $(element)["popover"]({
+                                "trigger": "hover",
+                                "container": "body",
+                                "title": function () {
+                                    return translations["DESCRIPTION_TOOLTIP_TITLE_VMAP_MAP_MAP"];
+                                },
+                                "content": function () {
+                                    return scope["row"]["entity"][scope["col"]["field"]];
+                                },
+                                // Placement du tooltip à gauche ou à droite suivant la position horizontale de l'élément.
+                                "placement": function (oPopoverNode, oElementNode) {
+                                    return scope.$root["workspaceTooltipPlacement"](oElementNode);
+                                },
+                                "html": true
+                            });
+                        });
+                    }
+                });
+                // Attends la suppression du scope.
+                scope.$on("$destroy", function () {
+                    // Supprime le tooltip.
+                    $(element)["popover"]("destroy");
+                    // Supprime l'observateur.
+                    clearObserver();
+                });
+            }
+        }
+    };
+    vitisApp["compileProvider"].directive('appWmsServiceDescriptionColumn', vitisApp.appWmsServiceDescriptionColumnDrtv);
+
+    /**
+     * beforeSendingLayerForm function.
+     * Traitement avant l'envoi du formulaire d'une couche.
+     */
+    angular.element(vitisApp.appMainDrtv).scope()['beforeSendingLayerForm'] = function () {
+        // Injection des services.
+        var $log = angular.element(vitisApp.appMainDrtv).injector().get(["$log"]);
+        var $q = angular.element(vitisApp.appHtmlFormDrtv).injector().get(["$q"]);
+        var envSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["envSrvc"]);
+        var propertiesSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["propertiesSrvc"]);
+        //
+        $log.info("beforeSendingLayerForm");
+        var scope = this;
+        var deferred = $q.defer();
+        var promise = deferred.promise;
+        ajaxRequest({
+            "method": "GET",
+            "url": propertiesSrvc["web_server_name"] + "/" + propertiesSrvc["services_alias"] + "/vm4ms/layerconnections/" + envSrvc["oFormValues"][envSrvc["sFormDefinitionName"]]["connection_id"]["selectedOption"]["value"],
+            "scope": scope,
+            "success": function (response) {
+                if (response["data"]["status"] == 1) {
+                    // Passage d'une connexion publique à privée.
+                    if (envSrvc["oFormValues"][envSrvc["sFormDefinitionName"]]["private_connection"] === false && envSrvc["extractWebServiceData"]("layerconnections", response["data"])[0]["private"] === true) {
+                        var oOptions = {
+                            "className": "modal-warning",
+                            "message": "FORM_PRIVATE_CONNECTION_TOOLTIP_CONTENT_VM4MS_VM4MS_LAYER",
+                            "callback": function (bResponse) {
+                                if (bResponse)
+                                    deferred.resolve();
+                                else
+                                    deferred.reject();
+                            }
+                        };
+                        scope["modalWindow"]("confirm", "FORM_PRIVATE_CONNECTION_TOOLTIP_TITLE_VM4MS_VM4MS_LAYER", oOptions);
+                    } else
+                        deferred.resolve();
+                } else {
+                    // Message d'erreur.
+                    var oOptions = {
+                        "className": "modal-danger",
+                        "buttons": {
+                            "ok": {
+                                label: "OK",
+                                className: "btn-default"
+                            }
+                        }
+                    };
+                    if (response["data"]["errorMessage"] != null)
+                        oOptions["message"] = response["data"]["errorMessage"];
+                    scope["modalWindow"]("alert", "REQUEST_ERROR", oOptions);
+                }
+            }
+        });
+        //
+        return promise;
+    };
+
+    /**
+     * testVm4msLayer function.
+     * Teste la couche en cours d'édition.
+     */
+    angular.element(vitisApp.appMainDrtv).scope()['testVm4msLayer'] = function () {
+        // Injection des services.
+        var $log = angular.element(vitisApp.appMainDrtv).injector().get(["$log"]);
+        var $compile = angular.element(vitisApp.appWorkspaceListDrtv).injector().get(["$compile"]);
+        var $templateRequest = angular.element(vitisApp.appWorkspaceListDrtv).injector().get(["$templateRequest"]);
+        var envSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["envSrvc"]);
+        var formSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["formSrvc"]);
+        var propertiesSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["propertiesSrvc"]);
+        //
+        $log.info("testVm4msLayer");
+        var scope = this;
+        // Ne crée pas les fichiers .map des flux WMS associés à la couche.
+        envSrvc["oFormValues"][envSrvc["sFormDefinitionName"]]["create_ws_map_file"] = "false";
+        // Sauvegarde la définition dans le champ "definitiontmp".
+        envSrvc["oFormValues"][envSrvc["sFormDefinitionName"]]["test_layer"] = true;
+        // Sauvegarde la définition de la couche avant le test.
+        var oFormData = formSrvc["getFormData"](envSrvc["sFormDefinitionName"]);
+        var sFormElementName = envSrvc["oFormDefinition"][envSrvc["sFormDefinitionName"]]["name"];
+        var formScope = angular.element("form[name='" + sFormElementName + "']").scope();
+        formScope[sFormElementName]["appFormSubmitted"] = false;
+        scope.$root["sendSimpleForm"](undefined, oFormData).then(function (bResponse) {
+            envSrvc["oFormValues"][envSrvc["sFormDefinitionName"]]["create_ws_map_file"] = "true";
+            envSrvc["oFormValues"][envSrvc["sFormDefinitionName"]]["test_layer"] = false;
+            if (bResponse) {
+                // Carte de test et url de MapServer obligatoires (section configuration).
+                var sErrorMessage;
+                if (!goog.isDefAndNotNull(propertiesSrvc["test_wms_service"]) || propertiesSrvc["test_wms_service"] == "")
+                    sErrorMessage = "ERROR_TEST_WMS_SERVICE_CONFIGURATION_CONFIGURATION_VM4MS_CONFIG";
+                else if (!goog.isDefAndNotNull(propertiesSrvc["ms_cgi_url"]) || propertiesSrvc["ms_cgi_url"] == "")
+                    sErrorMessage = "ERROR_MS_CGI_URL_CONFIGURATION_CONFIGURATION_VM4MS_CONFIG";
+                if (typeof (sErrorMessage) == "undefined") {
+                    // Si la couche est privée : login et mdp obligatoires.
+                    var bTestLayer = true;
+                    var sUserLogin = envSrvc["oFormValues"][envSrvc["sFormDefinitionName"]]["layer_login"];
+                    var sUserPassword = envSrvc["oFormValues"][envSrvc["sFormDefinitionName"]]["layer_password"];
+                    var bPrivateConnection = envSrvc["oFormValues"][envSrvc["sFormDefinitionName"]]["private_connection"];
+                    var oUserLogin = formSrvc["getFormElementDefinition"]("layer_login", envSrvc["sFormDefinitionName"], envSrvc["oFormDefinition"]);
+                    var oUserPassword = formSrvc["getFormElementDefinition"]("layer_password", envSrvc["sFormDefinitionName"], envSrvc["oFormDefinition"]);
+                    // Connexion privée : login et mdp spécifiés ou ceux de l'utilisateur en cours.
+                    if (bPrivateConnection) {
+                        document.getElementById(oUserLogin["id"]).parentNode.parentNode.parentNode.className = "";
+                        document.getElementById(oUserPassword["id"]).parentNode.parentNode.parentNode.className = "";
+                        if (!((!goog.isDefAndNotNull(sUserLogin) || sUserLogin == "") && (!goog.isDefAndNotNull(sUserPassword) || sUserPassword == ""))) {
+                            if ((!goog.isDefAndNotNull(sUserLogin) || sUserLogin == "") && bPrivateConnection) {
+                                document.getElementById(oUserLogin["id"]).parentNode.parentNode.parentNode.className = "has-error";
+                                bTestLayer = false;
+                            }
+                            if ((!goog.isDefAndNotNull(sUserPassword) || sUserPassword == "") && bPrivateConnection) {
+                                document.getElementById(oUserPassword["id"]).parentNode.parentNode.parentNode.className = "has-error";
+                                bTestLayer = false;
+                            }
+                        }
+                    }
+                    // Lance le test.
+                    if (bTestLayer) {
+                        // Affichage de la fenêtre modale.
+                        var oOptions = {
+                            "className": "dialog-modal-window layer-test-dialog-modal-window",
+                            "message": '<div id="layer_test_container" class="layer_test_container"></div>'
+                        };
+                        scope.$root["modalWindow"]("dialog", "FORM_MAP_SERVER_MODAL_TITLE_VM4MS_VM4MS_LAYER_DEFINITION", oOptions).then(function (oDialog) {
+                            // Ajoute le nom de la couche dans le titre.
+                            var sGeneralSectionFormDefinitionName = envSrvc["oSelectedObject"]["name"] + "_general_" + envSrvc["sMode"] + "_form";
+                            oDialog[0].querySelector(".modal-title").innerHTML += envSrvc["oFormValues"][sGeneralSectionFormDefinitionName]["name"];
+                            // Largeur et hauteur du widget.
+                            var iModalWidth = document.querySelector("body").clientWidth - 50;
+                            var iModalHeight = document.querySelector("body").clientHeight - 50;
+                            oDialog[0].querySelector(".modal-dialog").style.width = iModalWidth + "px";
+                            oDialog[0].querySelector(".modal-dialog").style.height = iModalHeight + "px";
+                            // Hauteur du header du widget.
+                            oDialog[0].querySelector(".modal-header").style.height = "56px";
+                            // Hauteur du body du widget.
+                            oDialog[0].querySelector(".modal-body").style.height = (iModalHeight - 56 - 4) + "px";
+                            // Compilation du template de test de la couche.
+                            $templateRequest("modules/vm4ms/template/layerTestsTpl.html").then(function (sTemplate) {
+                                $compile($("#layer_test_container").html(sTemplate).contents())(scope);
+                            });
+                        });
+                    }
+                } else {
+                    var oOptions = {
+                        "className": "modal-danger",
+                        "message": sErrorMessage
+                    };
+                    scope["modalWindow"]("dialog", "REQUEST_ERROR", oOptions);
+                }
+            }
+        })
+    };
+
+    /**
+     * showAddLayersToWmsServiceModalWindow function.
+     * Affichage de la liste des couches disponibles pour un service wms dans une fenêtre modale.
+     **/
+    angular.element(vitisApp.appMainDrtv).scope()['showAddLayersToWmsServiceModalWindow'] = function () {
+        // Injection des services.
+        var $log = angular.element(vitisApp.appMainDrtv).injector().get(["$log"]);
+        var $compile = angular.element(vitisApp.appWorkspaceListDrtv).injector().get(["$compile"]);
+        var $templateRequest = angular.element(vitisApp.appWorkspaceListDrtv).injector().get(["$templateRequest"]);
+        var $translate = angular.element(vitisApp.appWorkspaceListDrtv).injector().get(["$translate"]);
+        var envSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["envSrvc"]);
+        var uiGridConstants = angular.element(vitisApp.appWorkspaceListDrtv).injector().get(["uiGridConstants"]);
+        var modesSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["modesSrvc"]);
+        var propertiesSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["propertiesSrvc"]);
+        //
+        $log.info("showAddLayersToWmsServiceModalWindow");
+        var scope = this.$new();
+        // Sauve le nouveau scope crée dans la définition de l'onglet.
+        modesSrvc["addScopeToObject"](envSrvc["oSelectedObject"]["name"], envSrvc["oSelectedMode"]["mode_id"], scope);
+        // Sauve l'ancien onglet
+        //var oSaveSelectedObject = angular.copy(envSrvc["oSelectedObject"]);
+        var oSaveSelectedObject = modesSrvc["getObject"](envSrvc["oSelectedObject"]["name"], modesSrvc["getMode"](envSrvc["oSelectedMode"]["mode_id"]));
+        var sSaveMode = envSrvc["sMode"];
+        var sSaveSelectedGridOptionsName = envSrvc["sSelectedGridOptionsName"];
+        // Paramètres de l'onglet.
+        envSrvc["oSelectedObject"] = {
+            "actions": [],
+            "columns": [],
+            "mode_id": oSaveSelectedObject["mode_id"],
+            "name": oSaveSelectedObject["name"] + "_available_layers",
+            "ressource_id": "vm4ms/publiclayers",
+            "sections": "",
+            "template_name": "",
+            "sorted_by": "name",
+            "sorted_dir": "ASC"
+        };
+        envSrvc["sMode"] = "search";
+        scope['sSelectedObjectName'] = envSrvc["oSelectedObject"]["name"];
+
+        // Paramétrage du module ui-grid
+        scope["gridOptions"] = {
+            "enableRowSelection": true,
+            "enableSelectAll": true,
+            "enablePagination": true,
+            "enablePaginationControls": false,
+            "useExternalPagination": true,
+            "paginationPageSize": propertiesSrvc["rows_per_page"],
+            "enableColumnMenus": false,
+            "enableColumnResizing": true,
+            //"enableColumnMoving": true,
+            "paginationPageSizes": [10, 20, 50, 100],
+            "appHeader": true,
+            "appHeaderTitleBar": true,
+            "appHeaderSearchForm": false,
+            "appHeaderOptionBar": false,
+            "appLoadGridData": true,
+            "appGridTitle": "TITLE_GRID_AVAILABLE_LAYERS_VM4MS_PUBLIC_WMS_SERVICE_LAYERS",
+            "appResizeGrid": true,
+            "appFooter": true,
+            "appShowPagination": true,
+            "appActions": []
+        };
+        // Id de traduction des libellés des colonnes de la liste.
+        var aTranslationsId = ["FORM_LAYER_ID_VM4MS_VM4MS_LAYER", "FORM_LAYER_TITLE_VM4MS_VM4MS_LAYER", "FORM_LAYER_NAME_VM4MS_VM4MS_LAYER"];
+
+        // Définition des colonnes de la liste.
+        $translate(aTranslationsId).then(function (aTranslations) {
+            scope["gridOptions"]["columnDefs"] = [
+                {"name": aTranslations["FORM_LAYER_ID_VM4MS_VM4MS_LAYER"], "displayName": aTranslations["FORM_LAYER_ID_VM4MS_VM4MS_LAYER"], "field": "ms_layer_id", "width": 40, "enableSorting": true, "type": "string", "enableColumnMoving": true, "enableColumnResizing": true, "headerCellClass": "vm4ms_wms_service_layers_" + envSrvc["oSelectedObject"]["name"] + "_layer_id"},
+                {"name": aTranslations["FORM_LAYER_NAME_VM4MS_VM4MS_LAYER"], "displayName": aTranslations["FORM_LAYER_NAME_VM4MS_VM4MS_LAYER"], "field": "name", "width": 200, "enableSorting": true, "type": "string", "enableColumnMoving": true, "enableColumnResizing": true, "headerCellClass": "vm4ms_wms_service_layers_" + envSrvc["oSelectedObject"]["name"] + "_name", "sort": {"direction": uiGridConstants["ASC"], "ignoreSort": true, "priority": 0}},
+                {"name": aTranslations["FORM_LAYER_TITLE_VM4MS_VM4MS_LAYER"], "displayName": aTranslations["FORM_LAYER_TITLE_VM4MS_VM4MS_LAYER"], "field": "title", "width": 300, "enableSorting": true, "type": "string", "enableColumnMoving": true, "enableColumnResizing": true, "headerCellClass": "vm4ms_wms_service_layers_" + envSrvc["oSelectedObject"]["name"] + "_title"}
+            ];
+        });
+
+        // Boutons de la liste.
+        if (envSrvc["sMode"] != "display") {
+            $translate(["BTN_ADD_LAYERS_VM4MS_PUBLIC_WMS_SERVICE_LAYERS"]).then(function (oTranslations) {
+                scope["gridOptions"]["appActions"] = [
+                    {
+                        "label": oTranslations["BTN_ADD_LAYERS_VM4MS_PUBLIC_WMS_SERVICE_LAYERS"],
+                        "name": scope["sSelectedObjectName"] + "_add_layer_btn",
+                        "event": "addLayersToWmsService()"
+                    }
+                ];
+            });
+        }
+
+        // Couches à exclure (celles associées à la carte).
+        var aRows = envSrvc["oGridOptions"][envSrvc["sSelectedGridOptionsName"]]["data"];
+        if (aRows.length > 0) {
+            var i = 0, aLayersId = [];
+            while (i < aRows.length) {
+                aLayersId.push(aRows[i]["ms_layer_id"]);
+                i++;
+            }
+            envSrvc["oSelectedObject"]["filter"] = {
+                "relation": "AND",
+                "operators": [{
+                        "column": "ms_layer_id",
+                        "compare_operator": "NOT IN",
+                        "value": aLayersId
+                    }]
+            };
+        }
+
+        // Affichage de la fenêtre modale.
+        var sContainerId = "container_" + envSrvc["oSelectedObject"]["name"] + "_available_layers";
+        var oOptions = {
+            "className": "dialog-modal-window dialog-modal-window-workspace-list dialog-modal-window-available-layers",
+            "message": '<div id="' + sContainerId + '" class="col-xs-12"></div>'
+        };
+
+        scope["modalWindow"]("dialog", null, oOptions).then(function (oDialog) {
+            // Attends la fin de l'affichage de la fenêtre modale.
+            $(oDialog).on('shown.bs.modal', function (e) {
+                //
+                var oModalContainer = document.querySelector(".dialog-modal-window-available-layers > .modal-dialog");
+                oModalContainer.className = oModalContainer.className + " modal-lg";
+                // Compile le template de la liste.
+                var sTemplateUrl = 'templates/workspaceListTpl.html';
+                $templateRequest(sTemplateUrl).then(function (sTemplate) {
+                    $compile($("#" + sContainerId).html(sTemplate).contents())(scope);
+                });
+            });
+            // Attends la fermeture de la fenêtre modale.
+            $(oDialog).on('hide.bs.modal', function (e) {
+                // Restaure l'ancien onglet sauvé.
+                envSrvc["oSelectedObject"] = oSaveSelectedObject;
+                envSrvc["sMode"] = sSaveMode;
+                envSrvc["sSelectedGridOptionsName"] = sSaveSelectedGridOptionsName;
+                // Recharge la liste des couches associées à la carte.
+                scope.$root["refreshGrid"](scope.$root["gridApi"][envSrvc["sSelectedGridOptionsName"]]["grid"]["appScope"], envSrvc["oGridOptions"][envSrvc["sSelectedGridOptionsName"]]);
+            });
+        });
+    };
+
+    /**
+     * addLayersToWmsService function.
+     * Association d'une liste de couches à un flux wms.
+     **/
+    angular.element(vitisApp.appMainDrtv).scope()['addLayersToWmsService'] = function () {
+        // Injection des services.
+        var $log = angular.element(vitisApp.appMainDrtv).injector().get(["$log"]);
+        var $translate = angular.element(vitisApp.appMainDrtv).injector().get(["$translate"]);
+        var envSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["envSrvc"]);
+        var propertiesSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["propertiesSrvc"]);
+        //
+        $log.info("addLayersToWmsService");
+        var scope = this;
+        var oParams = {
+            "wmsservice_id": envSrvc["sId"]
+        };
+        // Liste des couches sélectionnées.
+        var aSelectedRows = scope.$root["gridApi"][envSrvc["sSelectedGridOptionsName"]]["selection"]["getSelectedRows"]();
+        if (aSelectedRows.length > 0) {
+            var i = 0, aLayersId = [];
+            while (i < aSelectedRows.length) {
+                aLayersId.push(aSelectedRows[i]["ms_layer_id"]);
+                i++;
+            }
+            oParams["wmsservice_ms_layers"] = aLayersId.join("|");
+            ajaxRequest({
+                "method": "PUT",
+                "url": propertiesSrvc["web_server_name"] + "/" + propertiesSrvc["services_alias"] + "/vm4ms/wmsservicelayers/" + envSrvc["sId"],
+                "data": oParams,
+                "scope": scope,
+                "success": function (response) {
+                    if (response["data"]["status"] == 0) {
+                        var oOptions = {
+                            "className": "modal-danger",
+                            "message": response["data"]["errorMessage"]
+                        };
+                        scope["modalWindow"]("dialog", "REQUEST_ERROR", oOptions);
+                    } else {
+                        // Efface la sélection.
+                        //scope.$root["gridApi"][envSrvc["sSelectedGridOptionsName"]]["selection"]["clearSelectedRows"]();
+                        // Recharge la liste.
+                        //scope["refreshGrid"](scope, scope["gridOptions"]);
+                        //
+                        bootbox["hideAll"]();
+                        // Affichage du message de succés.
+                        $translate("SUCCESSFUL_OPERATION").then(function (sTranslation) {
+                            $.notify(sTranslation, "success");
+                        });
+                        // Recharge la section "Tests".
+                        var oWmsServiceSectionForm = envSrvc["oSectionForm"][envSrvc["oSelectedObject"]["name"]];
+                        oWmsServiceSectionForm["sections"].forEach(function (aSection) {
+                            // Force le rechargement de la section "Répertoire projet".
+                            if (aSection["name"] == "tests")
+                                aSection["bLoaded"] = false;
+                        })
+                    }
+                }
+            });
+        }
+    };
+
+    /**
+     * deleteWmsServiceLayers function.
+     * Suppression des couches associées à un flux WMS.
+     **/
+    angular.element(vitisApp.appMainDrtv).scope()['deleteWmsServiceLayers'] = function () {
+        // Injection des services.
+        var $log = angular.element(vitisApp.appMainDrtv).injector().get(["$log"]);
+        var $translate = angular.element(vitisApp.appMainDrtv).injector().get(["$translate"]);
+        var envSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["envSrvc"]);
+        var propertiesSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["propertiesSrvc"]);
+        //
+        $log.info("deleteWmsServiceLayers");
+        var scope = this;
+        var oParams = {
+            "wmsservice_id": envSrvc["sId"]
+        };
+        // Liste des couches sélectionnées.
+        var aSelectedRows = scope.$root["gridApi"][envSrvc["sSelectedGridOptionsName"]]["selection"]["getSelectedRows"]();
+        if (aSelectedRows.length > 0) {
+            var i = 0, aLayersId = [];
+            while (i < aSelectedRows.length) {
+                aLayersId.push(aSelectedRows[i]["ms_layer_id"]);
+                i++;
+            }
+            oParams["idList"] = aLayersId.join("|");
+            // Suppression.
+            ajaxRequest({
+                "method": "DELETE",
+                "url": propertiesSrvc["web_server_name"] + "/" + propertiesSrvc["services_alias"] + "/vm4ms/wmsservicelayers/" + envSrvc["sId"],
+                "params": oParams,
+                "scope": scope,
+                "success": function (response) {
+                    if (response["data"]["status"] == 0) {
+                        var oOptions = {
+                            "className": "modal-danger",
+                            "message": response["data"]["errorMessage"]
+                        };
+                        scope["modalWindow"]("dialog", "REQUEST_ERROR", oOptions);
+                    } else {
+                        // Efface la sélection.
+                        scope.$root["gridApi"][envSrvc["sSelectedGridOptionsName"]]["selection"]["clearSelectedRows"]();
+                        // Recharge la liste.
+                        scope["refreshGrid"](scope, scope["gridOptions"]);
+                        // Affichage du message de succés.
+                        $translate("SUCCESSFUL_OPERATION").then(function (sTranslation) {
+                            $.notify(sTranslation, "success");
+                        });
+                        // Recharge la section "Tests".
+                        var oWmsServiceSectionForm = envSrvc["oSectionForm"][envSrvc["oSelectedObject"]["name"]];
+                        oWmsServiceSectionForm["sections"].forEach(function (aSection) {
+                            // Force le rechargement de la section "Répertoire projet".
+                            if (aSection["name"] == "tests")
+                                aSection["bLoaded"] = false;
+                        })
+                    }
+                }
+            });
+        }
+    };
+
+    /**
+     * cloneVm4msLayer function.
+     * Clonage d'une couche.
+     **/
+    angular.element(vitisApp.appMainDrtv).scope()['cloneVm4msLayer'] = function () {
+        // Injection des services.
+        var $log = angular.element(vitisApp.appWorkspaceListDrtv).injector().get(["$log"]);
+        var envSrvc = angular.element(vitisApp.appWorkspaceListDrtv).injector().get(["envSrvc"]);
+        //
+        $log.info("cloneVm4msLayer");
+        var scope = this;
+        var oFormValuesCopy = angular.copy(envSrvc["oFormValues"][envSrvc["sFormDefinitionName"]]);
+        this["AddSectionForm"]();
+        var clearListener = scope.$root.$on('formDefinitionLoaded', function (event, scope) {
+            // Supprime le "listener".
+            clearListener();
+            // Valeurs de l'enregistrement à cloner.
+            oFormValuesCopy['name'] = '';
+            oFormValuesCopy['title'] = '';
+            envSrvc["oFormValues"][envSrvc["sFormDefinitionName"]] = angular.copy(oFormValuesCopy);
+        });
+    };
+
+    /**
+     * initVm4msLayerForm function.
+     * Initialisation du formulaire de la section "général" de l'onglet "Couches".
+     */
+    angular.element(vitisApp.appMainDrtv).scope()['initVm4msLayerForm'] = function () {
+        // Injection des services.
+        var $log = angular.element(vitisApp.appMainDrtv).injector().get(["$log"]);
+        var $rootScope = angular.element(vitisApp.appMainDrtv).injector().get(["$rootScope"]);
+        var envSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["envSrvc"]);
+        var formSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["formSrvc"]);
+        var propertiesSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["propertiesSrvc"]);
+        //
+        $log.info("initVm4msLayerForm");
+        var scope = this;
+        if (envSrvc["sMode"] == "insert") {
+            // Filtrage du champ "name" de la couche.
+            var oLayerName = document.querySelector("form[name='" + envSrvc["oFormDefinition"][envSrvc["sFormDefinitionName"]]["name"] + "'] input[name='name']");
+            oLayerName.addEventListener("input", function () {
+                // Remplace les caractères interdits.
+                var sLayerName = this.value;
+                var oRules = {
+                    "a": "àáâãäå", "A": "ÀÁÂÃÄÅ", "e": "èéêë", "E": "ÈÉÊË", "i": "ìíîï", "I": "ÌÍÎÏ", "o": "òóôõöø", "O": "ÒÓÔÕÖØ", "u": "ùúûü", "U": "ÙÚÛÜ", "y": "ÿ", "Y": "Ÿ", "c": "ç", "C": "Ç", "n": "ñ", "N": "Ñ"
+                };
+                Object.keys(oRules).forEach(function (sCaracter) {
+                    sLayerName = sLayerName.replace(new RegExp("[" + oRules[sCaracter] + "]", "g"), sCaracter);
+                });
+                // Affiche le nom filtré.
+                envSrvc["oFormValues"][envSrvc["sFormDefinitionName"]]["name"] = sLayerName.replace(/[^a-zA-Z0-9]/g, '_');
+                // Rafraîchit le scope du formulaire.
+                var formScope = angular.element("form[name='" + envSrvc["oFormDefinition"][envSrvc["sFormDefinitionName"]]["name"]).scope();
+                formScope.$apply();
+            });
+            // Définition par défaut d'une couche.
+            var oFormValues = envSrvc["oFormValues"][envSrvc["sFormDefinitionName"]];
+            if (!goog.isDefAndNotNull(oFormValues["definition"]) || oFormValues["definition"] == "")
+                oFormValues["definition"] = "LAYER\r\tNAME \"{LAYER_NAME}\"\r\tTYPE {LAYER_TYPE}\r\tSTATUS ON\r\t{CONNECTION}\r\tDATA \"geom from {TABLE_SCHEMA}.{TABLE_NAME} USING SRID={SRID} USING UNIQUE {TABLE_ID}\"\r\tDEBUG 0\r\r\t{COORDSYS}\r\r\t{METADATA}\r\r\tCLASS\r\t\tNAME \"{LAYER_NAME}\"\r\t\tSTYLE\r\t\t\tSYMBOL \"circle\"\r\t\t\tSIZE 15\r\t\t\tOUTLINECOLOR 0 0 0\r\t\t\tCOLOR 204 204 204\r\t\t\tWIDTH 2\r\t\tEND\r\tEND\rEND";
+        }
+
+        // Schéma, table, colonne.
+        var clearListener = $rootScope.$on('formExtracted', function (event, sFormDefinitionName) {
+            // Supprime le "listener".
+            clearListener();
+            /**
+             * setLayerSchemaOptions function.
+             * Charge les paramètres de la connexion sélectionnée et la liste des schémas.
+             */
+            var setLayerSchemaOptions = function (sConnectionId) {
+                if (goog.isDefAndNotNull(sConnectionId) && sConnectionId != "") {
+                    ajaxRequest({
+                        "method": "GET",
+                        "url": propertiesSrvc["web_server_name"] + "/" + propertiesSrvc["services_alias"] + "/vm4ms/layerconnections/" + sConnectionId,
+                        "scope": scope,
+                        "success": function (response) {
+                            if (response["data"]["status"] == 1) {
+                                var oLayerConnection = envSrvc["extractWebServiceData"]("layerconnections", response["data"])[0];
+                                // Valeurs de connexion par défaut.
+                                if (!goog.isDefAndNotNull(oLayerConnection["server"]))
+                                    oLayerConnection["server"] = propertiesSrvc["server"];
+                                if (!goog.isDefAndNotNull(oLayerConnection["port"]))
+                                    oLayerConnection["port"] = propertiesSrvc["port"];
+                                if (!goog.isDefAndNotNull(oLayerConnection["database"]))
+                                    oLayerConnection["database"] = propertiesSrvc["database"];
+                                scope["oLayerConnection"] = angular.copy(oLayerConnection);
+                                // Charge la liste des schémas de la base de données de la connexion.
+                                var oUrlParams = {
+                                    "server": oLayerConnection["server"],
+                                    "port": oLayerConnection["port"],
+                                    "database": oLayerConnection["database"]
+                                };
+                                if (goog.isDefAndNotNull(oLayerConnection["user"]))
+                                    oUrlParams["login"] = oLayerConnection["user"];
+                                if (goog.isDefAndNotNull(oLayerConnection["password"]))
+                                    oUrlParams["password"] = oLayerConnection["password"];
+                                $rootScope["setOptionsFromWebService"]('tableschema', "vitis/genericquerys/" + oLayerConnection["database"] + "/schemas", oUrlParams);
+                            }
+                        }
+                    });
+                }
+            };
+
+            // Charge la liste des schémas de la connexion sélectionnée.
+            var iConnectionId = envSrvc["oFormValues"][envSrvc["sFormDefinitionName"]]["connection_id"]["selectedOption"]["value"];
+            if (!isNaN(iConnectionId))
+                setLayerSchemaOptions(iConnectionId);
+
+            // Paramètres de la connexion sélectionnée.
+            var oLayerConnectionDefinition = formSrvc["getFormElementDefinition"]("connection_id", envSrvc["sFormDefinitionName"]);
+            document.getElementById(oLayerConnectionDefinition["id"]).addEventListener("change", function (event) {
+                setLayerSchemaOptions(this.value);
+            });
+
+            // Initialise la palette.
+            var oFormElement = document.querySelector("form[name='" + envSrvc["oFormDefinition"][envSrvc["sFormDefinitionName"]]["name"] + "']");
+            oFormElement.className = oFormElement.className + " form-vm4ms-layer-general"
+            var oDefinitionFormRow = document.querySelector(".form-row-layer-palette > div > div > div > div");
+            var oPaletteElem = document.createElement("div");
+            oPaletteElem["id"] = envSrvc["sFormDefinitionName"] + "_palette";
+            oPaletteElem["className"] = "input-group colorpicker-component vm4ms-layer-palette"; //  + envSrvc["sMode"]
+            oPaletteElem.innerHTML = '<input type="text" name="color" value="#00AABB" class="form-control"><span class="input-group-addon"><i></i></span>';
+            oDefinitionFormRow.appendChild(oPaletteElem);
+            // Création du "color picker".
+            $(oPaletteElem).colorpicker({
+                "format": "hex"
+            });
+
+            // Bouton "plein écran" de l'éditeur CodeMirror.
+            var oContainerSectionElem = document.querySelector("#container_section_" + envSrvc["oSelectedObject"]["name"] + "_general > div");
+            scope["iCodeMirrorDefinitionHeight"] = parseInt(document.querySelector("form[name='" + envSrvc["oFormDefinition"][envSrvc["sFormDefinitionName"]]["name"] + "'] .CodeMirror").style.height);
+            var oFullScreenElem = document.createElement("button");
+            oFullScreenElem.id = envSrvc["sFormDefinitionName"] + "layer_definition_full_screen_icon";
+            oFullScreenElem.className = "btn btn-xs btn-primary layer-definition-full-screen-icon";
+            oFullScreenElem.type = "button";
+            oFullScreenElem.innerHTML = '<span class="glyphicon glyphicon-fullscreen"></span>';
+            oFullScreenElem.setAttribute("aria-label", "Left Align");
+            oDefinitionFormRow.appendChild(oFullScreenElem);
+            scope["bCodeMirrorDefinitionFullScreen"] = false;
+            // Calcule la hauteur de l'éditeur CodeMirror.
+            oFullScreenElem.addEventListener("click", function (event) {
+                var iCodeMirrorHeight;
+                if (scope["bCodeMirrorDefinitionFullScreen"])
+                    iCodeMirrorHeight = scope["iCodeMirrorDefinitionHeight"];
+                else {
+                    var iContainerSectionHeight = document.getElementById("container_section_" + envSrvc["oSelectedObject"]["name"] + "_general").clientHeight;
+                    if (document.querySelector(".form-row-layer-btn") != null)
+                        iContainerSectionHeight -= parseInt(document.querySelector(".form-row-layer-btn").offsetHeight);
+                    iContainerSectionHeight -= parseInt(document.querySelector(".form-row-layer-palette").offsetHeight);
+                    iContainerSectionHeight -= parseInt(document.querySelector(".form-row-layer-definition").offsetHeight);
+                    iContainerSectionHeight -= 20;
+                    iCodeMirrorHeight = scope["iCodeMirrorDefinitionHeight"] + iContainerSectionHeight;
+                }
+                scope["bCodeMirrorDefinitionFullScreen"] = !scope["bCodeMirrorDefinitionFullScreen"];
+                var oCodeMirrorElem = document.querySelector("form[name='" + envSrvc["oFormDefinition"][envSrvc["sFormDefinitionName"]]["name"] + "'] .CodeMirror");
+                oCodeMirrorElem.style.height = iCodeMirrorHeight + "px";
+                oContainerSectionElem.scrollTop = oContainerSectionElem.scrollHeight - oContainerSectionElem.clientHeight;
+                oCodeMirrorElem["CodeMirror"]["refresh"]();
+            }, false);
+
+            // Pas de section "Flux WMS" si la connexion est privée.
+            var oLayerFormValues = envSrvc["oFormValues"][envSrvc["sFormDefinitionName"]];
+            if (oLayerFormValues["private_connection"] === true)
+                angular.element(document.getElementById("container_mode_" + envSrvc["oSelectedMode"]["mode_id"]).querySelectorAll(".section-form-section")[1]).off('click')
+
+            // Pas de saisie de login ou mdp si la connexion de la couche est publique.
+            if (envSrvc["sMode"] == "update") {
+                var oLayerLoginDefinition = formSrvc["getFormElementDefinition"]("layer_login", envSrvc["sFormDefinitionName"]);
+                var oLayerPasswordDefinition = formSrvc["getFormElementDefinition"]("layer_password", envSrvc["sFormDefinitionName"]);
+                // Utilisateur + mdp : label.
+                if (oLayerFormValues["private_connection"] === false) {
+                    oLayerLoginDefinition["visible"] = false;
+                    oLayerPasswordDefinition["visible"] = false;
+                } else {
+                    oLayerLoginDefinition["visible"] = true;
+                    oLayerPasswordDefinition["visible"] = true;
+                    document.querySelector(".form-row-layer-palette > div:last-child").style.bottom = "80px";
+                }
+                // Rafraîchit le formulaire.
+                var formScope = angular.element("form[name='" + envSrvc["oFormDefinition"][envSrvc["sFormDefinitionName"]]["name"]).scope();
+                if (typeof(envSrvc["oFormDefinition"][envSrvc["sFormDefinitionName"]]["tabs"]) == "undefined")
+                    formScope["ctrl"]["initFormTabs"]();
+                formScope.$broadcast('$$rebind::refresh');
+                formScope.$apply();
+            }
+        });
+    };
+
+    /**
+     * displayMapServerSymbolsModal function.
+     * Affiche le fichier de symboles de MapServer dans une fenêtre modale.
+     */
+    angular.element(vitisApp.appMainDrtv).scope()['displayMapServerSymbolsModal'] = function () {
+        // Injection des services.
+        var $log = angular.element(vitisApp.appMainDrtv).injector().get(["$log"]);
+        var $compile = angular.element(vitisApp.appWorkspaceListDrtv).injector().get(["$compile"]);
+        var $templateRequest = angular.element(vitisApp.appWorkspaceListDrtv).injector().get(["$templateRequest"]);
+        //
+        $log.info("displayMapServerSymbolsModal");
+        var scope = this;
+        // Affichage de la fenêtre modale.
+        var oOptions = {
+            "className": "dialog-modal-window dialog-modal-window-mapserver-symbols", //  layer-test-dialog-modal-window
+            "message": '<div id="mapserver_symbols_container" class="mapserver-symbols-container"></div>'
+        };
+        scope.$root["modalWindow"]("dialog", "FORM_MAP_SERVER_SYMBOLS_MODAL_TITLE_VM4MS_VM4MS_LAYER", oOptions).then(function (oDialog) {
+            // Largeur et hauteur du widget.
+            var iModalWidth = parseInt(document.querySelector("body").clientWidth / 2);
+            var iModalHeight = document.querySelector("body").clientHeight - 50;
+            oDialog[0].querySelector(".modal-dialog").style.width = iModalWidth + "px";
+            oDialog[0].querySelector(".modal-dialog").style.height = iModalHeight + "px";
+            // Hauteur du header du widget.
+            oDialog[0].querySelector(".modal-header").style.height = "56px";
+            // Hauteur du body du widget.
+            oDialog[0].querySelector(".modal-body").style.height = (iModalHeight - 56 - 4) + "px";
+            // Compilation du template de la liste des symboles.
+            $templateRequest("modules/vm4ms/template/mapServerSymbolsTpl.html").then(function (sTemplate) {
+                $compile($("#mapserver_symbols_container").html(sTemplate).contents())(scope);
+            });
+        });
+    };
+
+    /**
+     * displayMapServerFontsModal function.
+     * Affiche la liste des polices de caractères du fichier fonts.list dans une fenêtre modale.
+     */
+    angular.element(vitisApp.appMainDrtv).scope()["displayMapServerFontsModal"] = function () {
+        // Injection des services.
+        var $log = angular.element(vitisApp.appMainDrtv).injector().get(["$log"]);
+        var $compile = angular.element(vitisApp.appWorkspaceListDrtv).injector().get(["$compile"]);
+        var $templateRequest = angular.element(vitisApp.appWorkspaceListDrtv).injector().get(["$templateRequest"]);
+        var propertiesSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["propertiesSrvc"]);
+        var envSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["envSrvc"]);
+        //
+        $log.info("displayMapServerFontsModal");
+        var scope = this;
+        // Affichage de la fenêtre modale.
+        var oOptions = {
+            "className": "dialog-modal-window dialog-modal-window-mapserver-fonts", //  layer-test-dialog-modal-window
+            "message": '<div id="mapserver_fonts_container" class="mapserver-fonts-container"></div>'
+        };
+        scope.$root["modalWindow"]("dialog", "FORM_MAP_SERVER_FONTS_MODAL_TITLE_VM4MS_VM4MS_LAYER", oOptions).then(function (oDialog) {
+            // Largeur et hauteur du widget.
+            var iModalWidth = parseInt(document.querySelector("body").clientWidth / 2);
+            var iModalHeight = document.querySelector("body").clientHeight - 50;
+            oDialog[0].querySelector(".modal-dialog").style.width = iModalWidth + "px";
+            oDialog[0].querySelector(".modal-dialog").style.height = iModalHeight + "px";
+            // Hauteur du header du widget.
+            oDialog[0].querySelector(".modal-header").style.height = "56px";
+            // Hauteur du body du widget.
+            oDialog[0].querySelector(".modal-body").style.height = (iModalHeight - 56 - 4) + "px";
+            //
+            ajaxRequest({
+                "method": "GET",
+                "url": propertiesSrvc["web_server_name"] + "/" + propertiesSrvc["services_alias"] + "/vm4ms/mapserver/Fonts",
+                "scope": scope,
+                "success": function (response) {
+                    if (response["data"]["status"] == 1) {
+                        scope["oMapServerFonts"] = envSrvc["extractWebServiceData"]("mapserver", response["data"])[0]["fonts"];
+                        // Compilation du template de test de la couche.
+                        $templateRequest("modules/vm4ms/template/mapServerFontsTpl.html").then(function (sTemplate) {
+                            $compile($("#mapserver_fonts_container").html(sTemplate).contents())(scope);
+                        });
+                    } else {
+                        //
+                        var oOptions = {
+                            "className": "modal-danger"
+                        };
+                        // Message d'erreur ?
+                        if (response["data"]["errorMessage"] != null)
+                            oOptions["message"] = response["data"]["errorMessage"];
+                        scope.$root["modalWindow"]("alert", "REQUEST_ERROR", oOptions);
+                    }
+                }
+            });
+        });
+    };
+
+    /**
+     * loadPrivateWmsServiceLayers function.
+     * Chargement de la section "Couches du flux" de l'onglet "Flux WMS privés".
+     */
+    angular.element(vitisApp.appMainDrtv).scope()['loadPrivateWmsServiceLayers'] = function () {
+        // Injection des services.
+        var $log = angular.element(vitisApp.appMainDrtv).injector().get(["$log"]);
+        var envSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["envSrvc"]);
+        var $translate = angular.element(vitisApp.appWorkspaceListDrtv).injector().get(["$translate"]);
+        //
+        $log.info("loadPrivateWmsServiceLayers");
+        var scope = this;
+        // Sauve la colonne et le sens de tri (onglet Flux WMS privé).
+        var sSortedBy = envSrvc["oSelectedObject"]["sorted_by"];
+        var sSortedDir = envSrvc["oSelectedObject"]["sorted_dir"];
+        // Colonne et sens de tri.
+        envSrvc["oSelectedObject"]["sorted_by"] = "name";
+        envSrvc["oSelectedObject"]["sorted_dir"] = "ASC";
+        // Affiche la liste des couches privées.
+        $translate("FORM_GRID_TITLE_VM4MS_PRIVATE_WMS_SERVICE_LAYERS").then(function (sTranslation) {
+            scope.$root["loadSectionList"]({
+                "appHeader": true,
+                "appHeaderSearchForm": false,
+                "appGridTitle": sTranslation
+            });
+        });
+        //
+        var clearListener = scope.$root.$on("workspaceListColumnsAdded", function (event, scope) {
+            // Supprime le "listener".
+            clearListener();
+            // Restaure la colonne et le sens de tri (onglet Flux WMS privé).
+            envSrvc["oSelectedObject"]["sorted_by"] = sSortedBy;
+            envSrvc["oSelectedObject"]["sorted_dir"] = sSortedDir;
+        });
+    };
+
+    /**
+     * loadPublicWmsServiceLayers function.
+     * Chargement de la section "Couches du flux" de l'onglet "Flux WMS publics".
+     */
+    angular.element(vitisApp.appMainDrtv).scope()['loadPublicWmsServiceLayers'] = function () {
+        // Injection des services.
+        var $log = angular.element(vitisApp.appMainDrtv).injector().get(["$log"]);
+        var envSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["envSrvc"]);
+        var $translate = angular.element(vitisApp.appWorkspaceListDrtv).injector().get(["$translate"]);
+        //
+        $log.info("loadPublicWmsServiceLayers");
+        var scope = this;
+        // Sauve la colonne et le sens de tri (onglet Flux WMS public).
+        var sSortedBy = envSrvc["oSelectedObject"]["sorted_by"];
+        var sSortedDir = envSrvc["oSelectedObject"]["sorted_dir"];
+        // Colonne et sens de tri.
+        envSrvc["oSelectedObject"]["sorted_by"] = "name";
+        envSrvc["oSelectedObject"]["sorted_dir"] = "ASC";
+        // Affiche la liste des couches publiques.
+        $translate("FORM_GRID_TITLE_VM4MS_PUBLIC_WMS_SERVICE_LAYERS").then(function (sTranslation) {
+            scope.$root["loadSectionList"]({
+                "appHeader": true,
+                "appHeaderSearchForm": false,
+                "appGridTitle": sTranslation,
+                "oFilter": {
+                    "relation": "AND",
+                    "operators": [{
+                            "column": "wmsservice_id",
+                            "compare_operator": "=",
+                            "value": envSrvc["sId"]
+                        }]
+                }
+            });
+        });
+        //
+        var clearListener = scope.$root.$on("workspaceListColumnsAdded", function (event, scope) {
+            // Supprime le "listener".
+            clearListener();
+            // Restaure la colonne et le sens de tri (onglet Flux WMS public).
+            envSrvc["oSelectedObject"]["sorted_by"] = sSortedBy;
+            envSrvc["oSelectedObject"]["sorted_dir"] = sSortedDir;
+        });
+    };
+
+    /**
+     * setOptionsFromWebService function.
+     * Remplit les options par une liste de valeur retournée par un web service.
+     * @param {string} Nom de l'élément
+     * @param {string} sWebService Id de la ressource du web service.
+     * @param {object} oUrlParams Paramètres pour le web service
+     */
+    angular.element(vitisApp.appMainDrtv).scope()['setOptionsFromWebService'] = function (sElemName, sWebService, oUrlParams) {
+        // Injection des services.
+        var $log = angular.element(vitisApp.appMainDrtv).injector().get(["$log"]);
+        var $q = angular.element(vitisApp.appHtmlFormDrtv).injector().get(["$q"]);
+        var envSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["envSrvc"]);
+        var propertiesSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["propertiesSrvc"]);
+        var formScope = angular.element("form[name='" + envSrvc["oFormDefinition"][envSrvc["sFormDefinitionName"]]["name"]).scope();
+        //
+        $log.info("setOptionsFromWebService");
+        var scope = this;
+        var deferred = $q.defer();
+        var promise = deferred.promise;
+        var aWebService = sWebService.split("/");
+        aWebService.shift();
+        ajaxRequest({
+            "method": "GET",
+            "url": propertiesSrvc["web_server_name"] + "/" + propertiesSrvc["services_alias"] + "/" + sWebService,
+            "params": oUrlParams,
+            "scope": scope,
+            "success": function (response) {
+                if (response["data"]["status"] != 0) {
+                    if (!goog.isDefAndNotNull(formScope['oFormValues'][envSrvc["sFormDefinitionName"]][sElemName]))
+                        formScope['oFormValues'][envSrvc["sFormDefinitionName"]][sElemName] = {};
+                    formScope['oFormValues'][envSrvc["sFormDefinitionName"]][sElemName]['options'] = [];
+                    envSrvc["extractWebServiceData"](aWebService[0], response["data"]).forEach(function (oRow) {
+                        formScope['oFormValues'][envSrvc["sFormDefinitionName"]][sElemName]['options'].push({
+                            'value': oRow[Object.keys(oRow)[0]],
+                            'label': oRow[Object.keys(oRow)[0]]
+                        });
+                    });
+                    deferred.resolve();
+                } else {
+                    formScope['oFormValues'][envSrvc["sFormDefinitionName"]][sElemName]['options'] = [];
+                    // Message d'erreur.
+                    var oOptions = {
+                        "className": "modal-danger",
+                        "buttons": {
+                            "ok": {
+                                label: "OK",
+                                className: "btn-default"
+                            }
+                        }
+                    };
+                    if (response["data"]["errorMessage"] != null)
+                        oOptions["message"] = response["data"]["errorMessage"];
+                    scope["modalWindow"]("alert", "REQUEST_ERROR", oOptions);
+                }
+            }
+        });
+        return promise;
+    };
+
+    /**
+     * loadVm4msConfig function.
+     * Chargement de la section "Configuration vMap4MapServer" dans l'onglet "Configuration".
+     */
+    angular.element(vitisApp.appMainDrtv).scope()['loadVm4msConfig'] = function () {
+        // Injection des services.
+        var $log = angular.element(vitisApp.appMainDrtv).injector().get(["$log"]);
+        var envSrvc = angular.element(vitisApp.appWorkspaceListDrtv).injector().get(["envSrvc"]);
+        var propertiesSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["propertiesSrvc"]);
+        //
+        $log.info("loadVm4msConfig");
+        // Supprime l'échappement des doubles quotes.
+        if (typeof (propertiesSrvc["test_wms_service_default_content"]) == "string")
+            propertiesSrvc["test_wms_service_default_content"] = propertiesSrvc["test_wms_service_default_content"].replace(/\\+"/g, '"');
+        // Paramètres des properties dans les valeurs du formulaire de config de vMap4MapServer.
+        angular.element(vitisApp.appMainDrtv).scope()["setPropertiesFormValues"](["mapserver_alias", "test_wms_service"]);
+        // Surcharge l'url du formulaire des properties de vMap4MapServer.
+        var scope = this;
+        var sTable = envSrvc["oSelectedObject"]["name"];
+        scope["oFormRequestParams"] = {
+            "sUrl": "modules/vm4ms/forms/" + envSrvc["oSelectedMode"]["mode_id"] + "/" + sTable + "_" + envSrvc["oSectionForm"][sTable]["sections"][envSrvc["oSectionForm"][sTable]["iSelectedSectionIndex"]]["name"] + ".json"
+        };
+    };
+
+    /**
+     * setLayerTableOptions function.
+     * Charge la liste des tables du schéma sélectionné
+     */
+    angular.element(vitisApp.appMainDrtv).scope()['setLayerTableOptions'] = function () {
+        // Injection des services.
+        var $log = angular.element(vitisApp.appMainDrtv).injector().get(["$log"]);
+        var envSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["envSrvc"]);
+        //
+        $log.info("setLayerTableOptions");
+        var sSchema = envSrvc['oFormValues'][envSrvc['sFormDefinitionName']]['tableschema']['selectedOption']['value'];
+        if (goog.isDefAndNotNull(sSchema) && sSchema != "") {
+            var scope = this;
+            // Charge la liste des tables du schéma.
+            var oUrlParams = {
+                'order_by': 'table_name',
+                "server": scope["oLayerConnection"]["server"],
+                "port": scope["oLayerConnection"]["port"],
+                'database': scope["oLayerConnection"]['database'],
+                'schema': sSchema,
+                'sort_order': 'ASC',
+                'attributs': 'table_name',
+                'distinct': true
+            };
+            // Identifiants de connexion.
+            if (goog.isDefAndNotNull(scope["oLayerConnection"]["user"]))
+                oUrlParams["login"] = scope["oLayerConnection"]["user"];
+            if (goog.isDefAndNotNull(scope["oLayerConnection"]["password"]))
+                oUrlParams["password"] = scope["oLayerConnection"]["password"];
+            scope.$root['setOptionsFromWebService']('tablename', 'vitis/genericquerys', oUrlParams);
+        }
+    };
+
+    /**
+     * setLayerIdFieldOptions function.
+     * Charge la liste des colonnes de la table sélectionnée
+     */
+    angular.element(vitisApp.appMainDrtv).scope()['setLayerIdFieldOptions'] = function () {
+        // Injection des services.
+        var $log = angular.element(vitisApp.appMainDrtv).injector().get(["$log"]);
+        var envSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["envSrvc"]);
+        //
+        $log.info("setLayerIdFieldOptions");
+        var sTable = envSrvc['oFormValues'][envSrvc['sFormDefinitionName']]['tablename']['selectedOption']['value'];
+        if (goog.isDefAndNotNull(sTable) && sTable != "") {
+            var scope = this;
+            // Charge la liste des colonnes de la table.
+            var oUrlParams = {
+                'order_by': 'column_name',
+                "server": scope["oLayerConnection"]["server"],
+                "port": scope["oLayerConnection"]["port"],
+                'database': scope["oLayerConnection"]['database'],
+                'schema': envSrvc['oFormValues'][envSrvc['sFormDefinitionName']]['tableschema']['selectedOption']['value'],
+                'table': sTable,
+                'sort_order': 'ASC',
+                'attributs': 'column_name',
+                'distinct': true
+            };
+            // Identifiants de connexion.
+            if (goog.isDefAndNotNull(scope["oLayerConnection"]["user"]))
+                oUrlParams["login"] = scope["oLayerConnection"]["user"];
+            if (goog.isDefAndNotNull(scope["oLayerConnection"]["password"]))
+                oUrlParams["password"] = scope["oLayerConnection"]["password"];
+            scope.$root['setOptionsFromWebService']('tableidfield', 'vitis/genericquerys/workspace/columns', oUrlParams);
+        }
+    };
+
+    /**
+     * afterSendingWmsServiceForm function.
+     * Traitement après l'envoi du formulaire des onglets "Flux WMS privés" et "Flux WMS publics".
+     */
+    angular.element(vitisApp.appMainDrtv).scope()['afterSendingWmsServiceForm'] = function () {
+        // Injection des services.
+        var $log = angular.element(vitisApp.appMainDrtv).injector().get(["$log"]);
+        var envSrvc = angular.element(vitisApp.appWorkspaceListDrtv).injector().get(["envSrvc"]);
+        //
+        $log.info("afterSendingWmsServiceForm");
+        // Recharge la section "Tests".
+        var oWmsServiceSectionForm = envSrvc["oSectionForm"][envSrvc["oSelectedObject"]["name"]];
+        oWmsServiceSectionForm["sections"].forEach(function (aSection) {
+            if (aSection["name"] == "tests")
+                aSection["bLoaded"] = false;
+        })
+    };
+
+    /**
+     * displayLayerLoadingError function.
+     * Affiche le message d'erreur au chargement d'une couche.
+     * @param {event} event Evènement d'erreur déclenché par OpenLayers.
+     */
+    angular.element(vitisApp.appMainDrtv).scope()['displayLayerLoadingError'] = function (event) {
+        // Injection des services.
+        var $log = angular.element(vitisApp.appMainDrtv).injector().get(["$log"]);
+        var $translate = angular.element(vitisApp.appMainDrtv).injector().get(["$translate"]);
+        var propertiesSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["propertiesSrvc"]);
+        //
+        $log.info("displayLayerLoadingError");
+
+        var scope = this;
+
+        if (typeof (scope['oVM4MSLayerLoadingErrorLayers']) == "undefined" || scope['oVM4MSLayerLoadingErrorLayers'] == null)
+            scope['oVM4MSLayerLoadingErrorLayers'] = {};
+
+        // liste des couches en erreur
+        if (goog.isObject(scope['oVM4MSLayerLoadingErrorLayers'])) {
+            // Nom générique si la couche n'a pas de nom.
+            var oLayerParams = event.target.getParams();
+            var sLayerName = oLayerParams['LAYERS'];
+            var sLayerIndex = sLayerName;
+            if (typeof (sLayerName) == "undefined") {
+                if (propertiesSrvc["language"] == "fr")
+                    sLayerName = "Couche sans nom";
+                else
+                    sLayerName = "Unnamed layer";
+                sLayerIndex = sLayerName + event.target.ol_uid;
+            }
+            //Infos de la couche.
+            if (!goog.isDefAndNotNull(scope['oVM4MSLayerLoadingErrorLayers'][sLayerIndex])) {
+                scope['oVM4MSLayerLoadingErrorLayers'][sLayerIndex] = {
+                    'layer': sLayerName,
+                    'url': event.image.src_,
+                    'errorMessage': null
+                };
+            }
+
+        } else {
+            scope['oVM4MSLayerLoadingErrorLayers'] = {};
+        }
+
+        // Affiche la modale si elle n'existe pas encore
+        if (!goog.isDefAndNotNull(scope['VM4MSLayerLoadingErrorModal'])) {
+            scope['VM4MSLayerLoadingErrorModal'] = {};
+            $translate(["ERROR_LOAD_IMAGE_OPEN_LAYERS_M4MS_WMS_SERVICE_TESTS_MULTIPLE"]).then(function (translations) {
+                angular.element(vitisApp.appMainDrtv).scope().$root["modalWindow"]("dialog", translations["ERROR_LOAD_IMAGE_OPEN_LAYERS_M4MS_WMS_SERVICE_TESTS_MULTIPLE"], {
+                    'className': 'modal-danger',
+                    'message': '',
+                    'appCallback': function ($rootScope, oDialog) {
+                        scope['VM4MSLayerLoadingErrorModal'] = oDialog;
+
+                        oDialog[0]['onblur'] = function () {
+                            scope['oVM4MSLayerLoadingErrorLayers'] = null;
+                            scope['VM4MSLayerLoadingErrorModal'] = null;
+                        };
+                    }
+                });
+            });
+        }
+
+        var changeErrorMessage = function () {
+            // Création & affichage du message
+            $translate(["ERROR_LOAD_IMAGE_OPEN_LAYERS_M4MS_WMS_SERVICE_TESTS_MULTIPLE_INFO"]).then(function (translations) {
+                var sMessage = translations["ERROR_LOAD_IMAGE_OPEN_LAYERS_M4MS_WMS_SERVICE_TESTS_MULTIPLE_INFO"];
+                var i = 0;
+                for (var key in scope['oVM4MSLayerLoadingErrorLayers']) {
+                    sMessage += '<div class="">';
+                    sMessage += '<li>';
+                    sMessage += '<a data-toggle="collapse" href="#ERROR_LOAD_IMAGE_OPEN_LAYERS_M4MS_WMS_SERVICE_TESTS_MULTIPLE_INFO_' + i + '">';
+                    sMessage += scope['oVM4MSLayerLoadingErrorLayers'][key]['layer'];
+                    sMessage += '</a>';
+                    sMessage += '</li>';
+                    sMessage += '</div>';
+                    sMessage += '<div id="ERROR_LOAD_IMAGE_OPEN_LAYERS_M4MS_WMS_SERVICE_TESTS_MULTIPLE_INFO_' + i + '" class="collapse">';
+                    sMessage += '<div class="">';
+                    sMessage += goog.isDefAndNotNull(scope['oVM4MSLayerLoadingErrorLayers'][key]['errorMessage']) ? scope['oVM4MSLayerLoadingErrorLayers'][key]['errorMessage'] : '-';
+                    sMessage += '</div>';
+                    sMessage += '</div>';
+                    i++;
+                }
+                scope['VM4MSLayerLoadingErrorModal'].find('.bootbox-body').html(sMessage);
+            });
+        };
+
+        // Change le message de la modale en cours
+        setTimeout(function () {
+            if (goog.isDefAndNotNull(scope['VM4MSLayerLoadingErrorModal'])) {
+                for (var key in scope['oVM4MSLayerLoadingErrorLayers']) {
+                    if (!goog.isDefAndNotNull(scope['oVM4MSLayerLoadingErrorLayers'][key]['errorMessage'])) {
+                        ajaxRequest({
+                            "method": "GET",
+                            "url": scope['oVM4MSLayerLoadingErrorLayers'][key]['url'],
+                            "scope": scope,
+                            "responseType": "text",
+                            "success": angular.bind(this, function (key, changeErrorMessage, response) {
+                                if (goog.isString(response["data"])) {
+                                    var parser = new DOMParser();
+                                    var xmlDoc = parser.parseFromString(response["data"], "text/xml");
+                                    var sErrorMessage = "";
+                                    xmlDoc.querySelectorAll("ServiceException").forEach(function (oServiceException) {
+                                        sErrorMessage += oServiceException.textContent;
+                                    });
+                                    scope['oVM4MSLayerLoadingErrorLayers'][key]['errorMessage'] = sErrorMessage;
+                                    changeErrorMessage();
+                                }
+                            }, key, changeErrorMessage)
+                        });
+                    }
+                }
+            }
+        });
+    };
+
+    /**
+     * appVm4msConnectionTypeColumn directive.
+     * Mise en forme de la colonne "type" dans l'onglet "connexions".
+     * @expose
+     **/
+    vitisApp.appVm4msConnectionTypeColumn = function () {
+        return {
+            link: function (scope, element, attrs) {
+                // 1er affichage ou tri de la liste : maj de la mise en forme.
+                var clearObserver = attrs.$observe("appVm4msConnectionTypeColumn", function (value) {
+                    var sEnabledClassName;
+                    if (scope["row"]["entity"][scope["col"]["field"]])
+                        sEnabledClassName = "icon-lock";
+                    else if (!scope["row"]["entity"][scope["col"]["field"]])
+                        sEnabledClassName = "icon-unlocked";
+                    // Classes css (ui-grid + spécifiques).
+                    element[0].className = "ui-grid-cell-contents ui-grid-cell-svg-icon " + sEnabledClassName;
+                });
+                // Attends la suppression du scope.
+                scope.$on("$destroy", function () {
+                    // Supprime l'observateur.
+                    clearObserver();
+                });
+            }
+        }
+    };
+    vitisApp["compileProvider"].directive("appVm4msConnectionTypeColumn", vitisApp.appVm4msConnectionTypeColumn);
+
+    /**
+     * appTestWmsServiceColumn directive.
+     * Mise en forme de la colonne "Flux de test" dans l'onglet "Flux WMS publics".
+     * @param {service} propertiesSrvc Paramètres des properties.
+     * @ngInject
+     * @expose
+     **/
+    vitisApp.appTestWmsServiceColumn = function (propertiesSrvc) {
+        return {
+            link: function (scope, element, attrs) {
+                // 1er affichage ou tri de la liste : maj de la mise en forme.
+                var clearObserver = attrs.$observe("appTestWmsServiceColumn", function (value) {
+                    var sEnabledClassName = "";
+                    if (scope["row"]["entity"]["wmsservice_id"] == propertiesSrvc["test_wms_service"])
+                        sEnabledClassName = "true-icon";
+                    // Classes css (ui-grid + spécifiques).
+                    element[0].className = "ui-grid-cell-contents ui-grid-cell-svg-icon " + sEnabledClassName;
+                });
+                // Attends la suppression du scope.
+                scope.$on("$destroy", function () {
+                    // Supprime l'observateur.
+                    clearObserver();
+                });
+            }
+        }
+    };
+    vitisApp["compileProvider"].directive("appTestWmsServiceColumn", vitisApp.appTestWmsServiceColumn);
+
+    /**
+     * appLayerTitleColumn directive.
+     * Mise en forme de la colonne "Titre" dans la liste de l'onglet "Couches".
+     * @param {service} $translate Translate service.
+     * @ngInject
+     **/
+    vitisApp.appLayerTitleColumnDrtv = function ($translate) {
+        return {
+            link: function (scope, element, attrs) {
+                // 1er affichage ou tri de la liste : maj de la mise en forme.
+                var clearObserver = attrs.$observe("appLayerTitleColumn", function (value) {
+                    // Si le champ est vide : supprime l'icône.
+                    if (scope["row"]["entity"][scope["col"]["field"]] == null || scope["row"]["entity"][scope["col"]["field"]] == "")
+                        element[0].className = "";
+                    else {
+                        // Classes css (ui-grid + spécifiques).
+                        element[0].className = "ui-grid-cell-contents info-icon";
+                        // Traduction du titre et du contenu.
+                        $translate(["TOOLTIP_TITLE_TITLE_VM4MS_VM4MS_LAYER"]).then(function (translations) {
+                            // Création du "tooltip".
+                            $(element)["popover"]({
+                                "trigger": "hover",
+                                "container": "body",
+                                "title": function () {
+                                    return translations["TOOLTIP_TITLE_TITLE_VM4MS_VM4MS_LAYER"];
+                                },
+                                "content": function () {
+                                    return scope["row"]["entity"][scope["col"]["field"]];
+                                },
+                                // Placement du tooltip à gauche ou à droite suivant la position horizontale de l'élément.
+                                "placement": function (oPopoverNode, oElementNode) {
+                                    return scope.$root["workspaceTooltipPlacement"](oElementNode);
+                                },
+                                "html": true
+                            });
+                        });
+                    }
+                });
+                // Attends la suppression du scope.
+                scope.$on("$destroy", function () {
+                    // Supprime le tooltip.
+                    $(element)["popover"]("destroy");
+                    // Supprime l'observateur.
+                    clearObserver();
+                });
+            }
+        }
+    };
+    vitisApp["compileProvider"].directive('appLayerTitleColumn', vitisApp.appLayerTitleColumnDrtv);
+
+    /**
+     * initVm4msConnectionForm function.
+     * Traitement après l'initialisation du formulaire d'une connexion.
+     */
+    angular.element(vitisApp.appMainDrtv).scope()['initVm4msConnectionForm'] = function () {
+        // Injection des services.
+        var $log = angular.element(vitisApp.appMainDrtv).injector().get(['$log']);
+        var envSrvc = angular.element(vitisApp.appMainDrtv).injector().get(['envSrvc']);
+        var $timeout = angular.element(vitisApp.appMainDrtv).injector().get(['$timeout']);
+        //
+        $log.info('initVm4msConnectionForm');
+        var scope = this;
+        var oPrivateConnectionRadios = document.querySelectorAll("form[name='" + envSrvc["oFormDefinition"][envSrvc["sFormDefinitionName"]]["name"] + "'] input[name='private']");
+        oPrivateConnectionRadios.forEach(function (oRadioElem) {
+            oRadioElem.addEventListener('click', function () {
+                scope.$root['setVm4msConnectionForm']();
+            });
+        });
+        if (envSrvc['sMode'] === 'update') {
+            var oConnectionFormValues = envSrvc['oFormValues'][envSrvc['sFormDefinitionName']];
+            oConnectionFormValues['private_database'] = oConnectionFormValues['database'];
+            oConnectionFormValues['public_database'] = oConnectionFormValues['database'];
+        }
+        // Affiche/cache les champs
+        this['setVm4msConnectionForm']();
+    };
+
+    /**
+     * setVm4msConnectionForm function.
+     * Affiche ou cache certains champs de form. en fonction du type de connexion.
+     */
+    angular.element(vitisApp.appMainDrtv).scope()['setVm4msConnectionForm'] = function () {
+        // Injection des services.
+        var $log = angular.element(vitisApp.appMainDrtv).injector().get(['$log']);
+        var envSrvc = angular.element(vitisApp.appMainDrtv).injector().get(['envSrvc']);
+        var formSrvc = angular.element(vitisApp.appMainDrtv).injector().get(['formSrvc']);
+        var $translate = angular.element(vitisApp.appMainDrtv).injector().get(['$translate']);
+        var $timeout = angular.element(vitisApp.appMainDrtv).injector().get(['$timeout']);
+        //
+        $log.info('setVm4msConnectionForm');
+        // Cache les champs serveur, port, utilisateur et mot de passe si la connexion est privée.
+        var formScope = angular.element("form[name='" + envSrvc["oFormDefinition"][envSrvc["sFormDefinitionName"]]["name"]).scope();
+        var oConnectionFormValues = envSrvc['oFormValues'][envSrvc['sFormDefinitionName']];
+        var oServerDef = formSrvc['getFormElementDefinition']('server', envSrvc['sFormDefinitionName']);
+        var oPortDef = formSrvc['getFormElementDefinition']('port', envSrvc['sFormDefinitionName']);
+        var oUserDef = formSrvc['getFormElementDefinition']('user', envSrvc['sFormDefinitionName']);
+        var oPasswordDef = formSrvc['getFormElementDefinition']('password', envSrvc['sFormDefinitionName']);
+        var oPublicDatabaseDef = formSrvc['getFormElementDefinition']('public_database', envSrvc['sFormDefinitionName']);
+        var oPrivateDatabaseDef = formSrvc['getFormElementDefinition']('private_database', envSrvc['sFormDefinitionName']);
+        if (oConnectionFormValues['private'] === true) {
+            if (goog.isDefAndNotNull(oServerDef)) {
+                oServerDef['visible'] = false;
+            }
+            if (goog.isDefAndNotNull(oPortDef)) {
+                oPortDef['visible'] = false;
+            }
+            if (goog.isDefAndNotNull(oUserDef)) {
+                oUserDef['visible'] = false;
+            }
+            if (goog.isDefAndNotNull(oPasswordDef)) {
+                oPasswordDef['visible'] = false;
+            }
+            if (goog.isDefAndNotNull(oPublicDatabaseDef)) {
+                oPublicDatabaseDef['visible'] = false;
+            }
+            if (goog.isDefAndNotNull(oPrivateDatabaseDef)) {
+                oPrivateDatabaseDef['visible'] = true;
+            }
+        } else {
+            if (goog.isDefAndNotNull(oServerDef)) {
+                oServerDef['visible'] = true;
+            }
+            if (goog.isDefAndNotNull(oPortDef)) {
+                oPortDef['visible'] = true;
+            }
+            if (goog.isDefAndNotNull(oUserDef)) {
+                oUserDef['visible'] = true;
+            }
+            if (goog.isDefAndNotNull(oPasswordDef)) {
+                oPasswordDef['visible'] = true;
+            }
+            if (goog.isDefAndNotNull(oPublicDatabaseDef)) {
+                oPublicDatabaseDef['visible'] = true;
+            }
+            if (goog.isDefAndNotNull(oPrivateDatabaseDef)) {
+                oPrivateDatabaseDef['visible'] = false;
+            }
+        }
+
+        // Rafraîchit la définition du formulaire.
+        formScope.$apply();
+    };
+
+    /**
+     * beforeSendingVm4msConnectionForm function.
+     * Traitement avant l'envoi du formulaire de connexion.
+     */
+    angular.element(vitisApp.appMainDrtv).scope()["beforeSendingVm4msConnectionForm"] = function () {
+        // Injection des services.
+        var $log = angular.element(vitisApp.appMainDrtv).injector().get(["$log"]);
+        var envSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["envSrvc"]);
+        //
+        $log.info("beforeSendingVm4msConnectionForm");
+        var oConnectionFormValues = envSrvc["oFormValues"][envSrvc["sFormDefinitionName"]];
+        if (oConnectionFormValues["private"] === true) {
+            oConnectionFormValues["database"] = oConnectionFormValues["private_database"]["selectedOption"]["value"];
+            oConnectionFormValues["server"] = "";
+            oConnectionFormValues["port"] = "";
+            oConnectionFormValues["user"] = "";
+            oConnectionFormValues["password"] = "";
+        } else {
+            oConnectionFormValues["database"] = oConnectionFormValues["public_database"];
+        }
+    };
+
+    /**
+     * updateVm4msProperties function.
+     * Traitement avant la mise à jour des properties de vm4ms.
+     */
+    angular.element(vitisApp.appMainDrtv).scope()["updateVm4msProperties"] = function () {
+        // Injection des services.
+        var $log = angular.element(vitisApp.appMainDrtv).injector().get(["$log"]);
+        var $rootScope = angular.element(vitisApp.appMainDrtv).injector().get(["$rootScope"]);
+        var $timeout = angular.element(vitisApp.appMainDrtv).injector().get(['$timeout']);
+        var envSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["envSrvc"]);
+        //
+        $log.info("updateVm4msProperties");
+        var oFormValues = envSrvc["oFormValues"][envSrvc["sFormDefinitionName"]];
+        // Echappement des quotes.
+        var sTestWmsServiceDefaultContent = oFormValues['test_wms_service_default_content'];
+        //oFormValues['test_wms_service_default_content'] = oFormValues['test_wms_service_default_content'].replace(/'/g, "\\'");
+        $rootScope["updateProperties"]('vm4ms');
+        $timeout(function () {
+            oFormValues['test_wms_service_default_content'] = sTestWmsServiceDefaultContent;
+        });
+    };
+
+    /**
+     * activateVm4msLayers function.
+     * Active / désactive une couche.
+     */
+    angular.element(vitisApp.appMainDrtv).scope()["activateVm4msLayers"] = function (bActivate) {
+        // Injection des services.
+        var $log = angular.element(vitisApp.appMainDrtv).injector().get(["$log"]);
+        var $q = angular.element(vitisApp.appMainDrtv).injector().get(["$q"]);
+        var envSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["envSrvc"]);
+        var propertiesSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["propertiesSrvc"]);
+        //
+        $log.info("activateVm4msLayers");
+        // Activation ou désactivation de la couche ?
+        if (typeof (bActivate) == "undefined")
+            bActivate = true;
+        //
+        var scope = this;
+        var deferred = $q.defer();
+        var promise = deferred.promise;
+        var oParams = {};
+        // Des couches sont sélectionnées ?
+        var aSelectedRows = scope.$root["gridApi"][scope["sSelectedObjectName"]]["selection"]["getSelectedRows"]();
+        var sOperationId;
+        if (aSelectedRows.length > 0) {
+            // Activation ou désactivation de la couche ?
+            var sErrorTitle;
+            if (bActivate) {
+                sOperationId = "activate";
+                sErrorTitle = "ERROR_ACTIVATE_VM4MS_VM4MS_LAYER";
+            } else {
+                sOperationId = "desactivate";
+                sErrorTitle = "ERROR_DESACTIVATE_VM4MS_VM4MS_LAYER";
+            }
+            // Liste des enregistrements à supprimer.
+            var i = 0, aIdToDelete = [];
+            while (i < aSelectedRows.length) {
+                aIdToDelete.push(aSelectedRows[i][envSrvc["oSelectedObject"]["sIdField"]]);
+                i++;
+            }
+            oParams["idList"] = aIdToDelete.join("|");
+            ajaxRequest({
+                "method": "PUT",
+                "url": propertiesSrvc["web_server_name"] + "/" + propertiesSrvc["services_alias"] + "/vm4ms/layers/" + sOperationId,
+                "data": oParams,
+                "scope": scope,
+                "success": function (response) {
+                    if (response["data"]["status"] == 0) {
+                        var oOptions = {
+                            "className": "modal-danger",
+                            "message": response["data"]["errorMessage"]
+                        };
+                        scope["modalWindow"]("dialog", sErrorTitle, oOptions);
+                    } else {
+                        // Ferme la fenêtre modale.
+                        bootbox["hideAll"]();
+                        // Recharge la liste des couches.
+                        var iPageNumber = goog.isDefAndNotNull(envSrvc["oSelectedObject"]["iPageNumber"]) ? envSrvc["oSelectedObject"]["iPageNumber"] : 1;
+                        scope.$root["gridApi"][scope["sSelectedObjectName"]]["pagination"]["raise"]["paginationChanged"](iPageNumber, scope["gridOptions"]["paginationPageSize"]);
+                    }
+                }
+            });
+        } else {
+            var oOptions = {
+                "className": "modal-danger",
+                "appDuration": 2000
+            };
+            scope["modalWindow"]("dialog", "ERROR_NO_SELECTION_RESET_VM4MS_VM4MS_LAYER", oOptions);
+        }
+        // Retourne la promesse.
+        return promise;
+    };
+
+    /**
+     * desactivateVm4msLayers function.
+     * Désactive une couche.
+     */
+    angular.element(vitisApp.appMainDrtv).scope()["desactivateVm4msLayers"] = function () {
+        // Injection des services.
+        var $log = angular.element(vitisApp.appMainDrtv).injector().get(["$log"]);
+        //
+        $log.info("desactivateVm4msLayers");
+        this["activateVm4msLayers"](false);
+    }
+
+    /**
+     * Affiche une modale pour éditer le template GetFeatureInfo
+     */
+    angular.element(vitisApp.appMainDrtv).scope()['editGetFeatureInfoTemplate'] = function () {
+
+        // Injection des services.
+        var $log = angular.element(vitisApp.appMainDrtv).injector().get(["$log"]);
+        var $compile = angular.element(vitisApp.appWorkspaceListDrtv).injector().get(["$compile"]);
+        var $templateRequest = angular.element(vitisApp.appWorkspaceListDrtv).injector().get(["$templateRequest"]);
+        var envSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["envSrvc"]);
+        var formSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["formSrvc"]);
+        var propertiesSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["propertiesSrvc"]);
+
+        $log.info("editGetFeatureInfoTemplate");
+
+        var this_ = this;
+        var scope = this;
+
+        scope['oLayerGetfeatureinfoForm'] = null;
+
+        // Affichage de la fenêtre modale.
+        var oOptions = {
+            "className": "dialog-modal-window layer-test-dialog-modal-window",
+            "message": '<div id="layer_getfeatureinfo_template_container" class="layer_getfeatureinfo_template_container"></div>'
+        };
+        scope.$root["modalWindow"]("dialog", "FORM_GETFEATUREINFO_TEMPLATE_VM4MS_VM4MS_LAYER", oOptions).then(function (oDialog) {
+            // Rempli le formulaire
+            this_['setFormGetFeatureInfoTemplate']();
+        });
+    }
+
+    /**
+     * Rempli la modale contenant le formulaire du template GetFeatureInfo
+     */
+    angular.element(vitisApp.appMainDrtv).scope()['setFormGetFeatureInfoTemplate'] = function () {
+
+        // Injection des services.
+        var $log = angular.element(vitisApp.appMainDrtv).injector().get(["$log"]);
+        var $compile = angular.element(vitisApp.appWorkspaceListDrtv).injector().get(["$compile"]);
+        var $templateRequest = angular.element(vitisApp.appWorkspaceListDrtv).injector().get(["$templateRequest"]);
+        var envSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["envSrvc"]);
+        var formSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["formSrvc"]);
+        var propertiesSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["propertiesSrvc"]);
+
+        $log.info("setFormGetFeatureInfoTemplate");
+
+        var this_ = this;
+        var scope = this;
+
+        var sGetFeatureInfoTemplate = '';
+
+        // Récupère le contenu actuel du template
+        ajaxRequest({
+            "method": "GET",
+            "url": propertiesSrvc["web_server_name"] + '/' + propertiesSrvc["services_alias"] + '/vm4ms/layers/' + envSrvc["oFormValues"][envSrvc["sFormDefinitionName"]]["ms_layer_id"] + '/GetFeatureInfoTemplate',
+            "params": {},
+            "scope": scope,
+            "success": function (response) {
+                if (goog.isDefAndNotNull(response['data'])) {
+                    if (goog.isDefAndNotNull(response['data']['layers'])) {
+                        if (goog.isDefAndNotNull(response['data']['layers'][0])) {
+                            if (goog.isDefAndNotNull(response['data']['layers'][0]['getfeatureinfo_template'])) {
+                                sGetFeatureInfoTemplate = response['data']['layers'][0]['getfeatureinfo_template'];
+                            }
+                        }
+                    }
+
+                    this_['setFormGetFeatureInfoTemplateFormFeader'](sGetFeatureInfoTemplate);
+
+                } else {
+                    $.notify('Erreur lors de la récupération du template actuel', 'error');
+                    console.error('could not get vm4ms_vm4ms_layer_getfeatureinfo_template.json');
+                }
+            },
+            "error": function(response){
+                $.notify('Erreur lors de la récupération du template GetFeatureInfo', 'error');
+                console.error('could not get GetFeatureInfo template');
+            }
+        });
+
+    }
+
+    /**
+     * Init the GetFeatureInfo FromReader
+     *
+     * @param  {string} sGetFeatureInfoTemplate GetFeatureInfo template content
+     */
+    angular.element(vitisApp.appMainDrtv).scope()['setFormGetFeatureInfoTemplateFormFeader'] = function (sGetFeatureInfoTemplate) {
+
+        // Injection des services.
+        var $log = angular.element(vitisApp.appMainDrtv).injector().get(["$log"]);
+        var $compile = angular.element(vitisApp.appWorkspaceListDrtv).injector().get(["$compile"]);
+        var $templateRequest = angular.element(vitisApp.appWorkspaceListDrtv).injector().get(["$templateRequest"]);
+        var envSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["envSrvc"]);
+        var formSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["formSrvc"]);
+        var propertiesSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["propertiesSrvc"]);
+
+        $log.info("setFormGetFeatureInfoTemplateFormFeader");
+
+        var this_ = this;
+        var scope = this;
+
+        // Récupère le JSON du formulaire
+        ajaxRequest({
+            "method": "GET",
+            "url": 'modules/vm4ms/forms/vm4ms/vm4ms_vm4ms_layer_getfeatureinfo_template.json',
+            "params": {},
+            "scope": scope,
+            "success": function (response) {
+                if (goog.isDefAndNotNull(response['data'])) {
+
+                    // Contient toutes les variables necessaires au FormReader
+                    scope['oLayerGetfeatureinfoForm'] = {
+                        'oProperties': propertiesSrvc,
+                        'oFormDefinitionName': 'update',
+                        'oFormDefinition': response['data'],
+                        'oFormValues': {
+                            'update': {
+                                'getFeatureInfo_template': sGetFeatureInfoTemplate
+                            }
+                        }
+                    }
+
+                    this_['compileFormGetFeatureInfoTemplate']();
+
+                } else {
+                    $.notify('Erreur lors de la récupération du formulaire', 'error');
+                    console.error('could not get vm4ms_vm4ms_layer_getfeatureinfo_template.json');
+                }
+            },
+            "error": function(response) {
+                $.notify('Erreur lors de la récupération du formulaire', 'error');
+                console.error('could not get vm4ms_vm4ms_layer_getfeatureinfo_template.json');
+            }
+        });
+    }
+
+    /**
+     * Compile the HTML GetFeatureInfo from template
+     *
+     */
+    angular.element(vitisApp.appMainDrtv).scope()['compileFormGetFeatureInfoTemplate'] = function () {
+
+        // Injection des services.
+        var $log = angular.element(vitisApp.appMainDrtv).injector().get(["$log"]);
+        var $compile = angular.element(vitisApp.appWorkspaceListDrtv).injector().get(["$compile"]);
+        var $templateRequest = angular.element(vitisApp.appWorkspaceListDrtv).injector().get(["$templateRequest"]);
+
+        $log.info("compileFormGetFeatureInfoTemplate");
+
+        var scope = this;
+
+        // Compilation du template
+        $templateRequest("modules/vm4ms/template/layerGetFeatureInfoTemplateTpl.html").then(function (sTemplate) {
+
+            // Compile le template
+            $compile($("#layer_getfeatureinfo_template_container").html(sTemplate).contents())(scope);
+
+            // Rafraichit le champ codemirror
+            setTimeout(function () {
+                $('#vm4ms_layer_form_getFeatureInfo_template').scope()['oCodeMirrorEditor']['undefined'].refresh();
+            }, 1000);
+        });
+    }
+
+    /**
+     * Régénère le template GetFeatureInfo de la couche
+     */
+    angular.element(vitisApp.appMainDrtv).scope()['regenLayerGetFeatureInfoTemplate'] = function () {
+        var $log = angular.element(vitisApp.appMainDrtv).injector().get(["$log"]);
+        var propertiesSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["propertiesSrvc"]);
+        var envSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["envSrvc"]);
+
+        $log.info("regenLayerGetFeatureInfoTemplate");
+
+        var this_ = this;
+        var scope = $('#layer_getfeatureinfo_template_form_reader').scope();
+        var sGetFeatureInfoTemplate = scope['oLayerGetfeatureinfoForm']['oFormValues']['update']['getFeatureInfo_template'];
+
+        ajaxRequest({
+            "method": "GET",
+            "url": propertiesSrvc["web_server_name"] + '/' + propertiesSrvc["services_alias"] + '/vm4ms/layers/' + envSrvc["oFormValues"][envSrvc["sFormDefinitionName"]]["ms_layer_id"] + '/GeneratedGetFeatureInfoTemplate',
+            "success": function (response) {
+
+                var sGeneratedTemplate = null;
+                if (goog.isDefAndNotNull(response['data'])) {
+                    if (goog.isDefAndNotNull(response['data']['layers'])) {
+                        if (goog.isDefAndNotNull(response['data']['layers'][0])) {
+                            if (goog.isDefAndNotNull(response['data']['layers'][0]['generated_getfeatureinfo_template'])) {
+                                sGeneratedTemplate = response['data']['layers'][0]['generated_getfeatureinfo_template'];
+                            }
+                        }
+                    }
+                }
+
+                if (goog.isDefAndNotNull(sGeneratedTemplate)) {
+                    this_['setFormGetFeatureInfoTemplateFormFeader'](sGeneratedTemplate);
+                } else {
+                    $.notify('Erreur lors de la génération du template GetFeatureInfo', 'error');
+                    console.error('could not generate GetFeatureInfo template');
+                }
+            },
+            "error": function(response){
+                $.notify('Erreur lors de la génération du template GetFeatureInfo', 'error');
+                console.error('could not generate GetFeatureInfo template');
+            }
+        });
+    }
+
+    /**
+     * Met à jour le template GetFeatureInfo de la couche
+     */
+    angular.element(vitisApp.appMainDrtv).scope()['sendLayerGetFeatureInfoTemplate'] = function () {
+        var $log = angular.element(vitisApp.appMainDrtv).injector().get(["$log"]);
+        var propertiesSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["propertiesSrvc"]);
+        var envSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["envSrvc"]);
+
+        $log.info("sendLayerGetFeatureInfoTemplate");
+
+        var this_ = this;
+        var scope = $('#layer_getfeatureinfo_template_form_reader').scope();
+        var sGetFeatureInfoTemplate = scope['oLayerGetfeatureinfoForm']['oFormValues']['update']['getFeatureInfo_template'];
+
+        ajaxRequest({
+            "method": "PUT",
+            "url": propertiesSrvc["web_server_name"] + '/' + propertiesSrvc["services_alias"] + '/vm4ms/layers/' + envSrvc["oFormValues"][envSrvc["sFormDefinitionName"]]["ms_layer_id"] + '/GetFeatureInfoTemplate',
+            "data": {
+                'getfeatureinfo_template': sGetFeatureInfoTemplate
+            },
+            "success": function (response) {
+                if (goog.isDefAndNotNull(response['data'])) {
+                    if (response['data']['status'] === 1) {
+                        $.notify('Template GetFeatureInfo mis à jour', 'success');
+                        this_['closeLayerGetFeatureInfoTemplateModal']();
+                    }
+                }
+            },
+            "error": function(response){
+                $.notify('Erreur lors de la sauvegarde du template GetFeatureInfo', 'error');
+                console.error('could not save GetFeatureInfo template');
+            }
+        });
+    }
+
+    /**
+     * Ferme la modale d'édition template GetFeatureInfo de la couche
+     */
+    angular.element(vitisApp.appMainDrtv).scope()['closeLayerGetFeatureInfoTemplateModal'] = function () {
+        var $log = angular.element(vitisApp.appMainDrtv).injector().get(["$log"]);
+
+        $log.info("closeLayerGetFeatureInfoTemplateModal");
+
+        var scope = this;
+        scope['oLayerGetfeatureinfoForm'] = null;
+        scope.$root["modalWindow"]("hideAll");
+    }
+});
diff --git a/vmap/client/modules/vm4ms/lang/lang-en.json b/vmap/client/modules/vm4ms/lang/lang-en.json
new file mode 100755
index 0000000000000000000000000000000000000000..5353874084094c095f23ead846782f6af9bae88f
--- /dev/null
+++ b/vmap/client/modules/vm4ms/lang/lang-en.json
@@ -0,0 +1,172 @@
+{
+    "TITLE_MODE_VM4MS" : "vMap4MapServer",
+    "TEXT_MODE_VM4MS" : "WMS Publication for MapServer",
+    "" : "",
+    "SECTION_UPDATE_TITLE_VM4MS_VM4MS_PUBLIC_WMS_SERVICE" : "Public WMS service {{sId}}",
+    "SECTION_INSERT_TITLE_VM4MS_VM4MS_PUBLIC_WMS_SERVICE" : "Public WMS service",
+    "SECTION_DISPLAY_TITLE_VM4MS_VM4MS_PUBLIC_WMS_SERVICE" : "Public WMS service {{sId}}",
+    "SECTION_UPDATE_TITLE_VM4MS_VM4MS_LAYER" : "Layer n°{{sId}}",
+    "SECTION_INSERT_TITLE_VM4MS_VM4MS_LAYER" : "Layer",
+    "SECTION_DISPLAY_TITLE_VM4MS_VM4MS_LAYER" : "Layer n°{{sId}}",
+    "SECTION_UPDATE_TITLE_VM4MS_VM4MS_PRIVATE_WMS_SERVICE" : "Private WMS service {{sId}}",
+    "SECTION_DISPLAY_TITLE_VM4MS_VM4MS_PRIVATE_WMS_SERVICE" : "Private WMS service {{sId}}",
+    "" : "",
+    "FORM_TITLE_VM4MS_VM4MS_PUBLIC_WMS_SERVICE" : "Public WMS service {{::wmsservice_id}}",
+    "FORM_WMSSERVICEID_VM4MS_VM4MS_PUBLIC_WMS_SERVICE" : "ID",
+    "FORM_WEB_ID_VM4MS_VM4MS_PUBLIC_WMS_SERVICE" : "Web object",
+    "FORM_DESCRIPTION_VM4MS_VM4MS_PUBLIC_WMS_SERVICE" : "Description",
+    "FORM_DEFINITION_VM4MS_VM4MS_PUBLIC_WMS_SERVICE" : "Definition",
+    "FORM_PALETTE_VM4MS_VM4MS_PUBLIC_WMS_SERVICE" : "Palette",
+    "FORM_WMS_SERVICE_URL_VM4MS_VM4MS_PUBLIC_WMS_SERVICE" : "Link",
+    "FORM_MSDEBUGLEVEL_ID_VM4MS_VM4MS_PUBLIC_WMS_SERVICE" : "Debug level for MapServer",
+    "FORM_BTN_WMS_SERVICE_URL_VM4MS_VM4MS_PUBLIC_WMS_SERVICE" : "Copy",
+    "" : "",
+    "FORM_TITLE_VM4MS_VM4MS_WEB_OBJECT" : "Web object {{::name}}",
+    "FORM_WEB_ID_VM4MS_VM4MS_WEB_OBJECT" : "ID",
+    "FORM_NAME_VM4MS_VM4MS_WEB_OBJECT" : "Nom",
+    "FORM_DEFINITION_VM4MS_VM4MS_WEB_OBJECT" : "Définition",
+    "" : "",
+    "FORM_TITLE_VM4MS_VM4MS_CONNECTION" : "Connection {{::name}}",
+    "FORM_CONNECTION_ID_VM4MS_VM4MS_CONNECTION" : "ID",
+    "FORM_NAME_VM4MS_VM4MS_CONNECTION" : "Name",
+    "FORM_DEFINITION_VM4MS_VM4MS_CONNECTION" : "Definition",
+    "FORM_PRIVATE_VM4MS_VM4MS_CONNECTION" : "Private connection",
+    "FORM_PRIVATE_YES_VM4MS_VM4MS_CONNECTION" : "Yes",
+    "FORM_PRIVATE_NO_VM4MS_VM4MS_CONNECTION" : "No",
+    "FORM_SERVER_VM4MS_VM4MS_CONNECTION" : "Server",
+    "FORM_PORT_VM4MS_VM4MS_CONNECTION" : "Port",
+    "FORM_DATABASE_VM4MS_VM4MS_CONNECTION" : "Database",
+    "FORM_USER_VM4MS_VM4MS_CONNECTION" : "Utilisateur",
+    "FORM_PASSWORD_VM4MS_VM4MS_CONNECTION" : "Mot de passe",
+    "" : "",
+    "FORM_TITLE_VM4MS_VM4MS_SOURCE" : "Source {{::name}}",
+    "FORM_SOURCE_ID_VM4MS_VM4MS_SOURCE" : "ID",
+    "FORM_NAME_VM4MS_VM4MS_SOURCE" : "Name",
+    "" : "",
+    "FORM_TITLE_VM4MS_VM4MS_COORDSYS" : "Coordinate systems {{::coordsys_id}}",
+    "FORM_SRID_VM4MS_VM4MS_COORDSYS" : "Srid",
+    "FORM_EPSG_VM4MS_VM4MS_COORDSYS" : "EPSG code",
+    "FORM_DEFINITION_VM4MS_VM4MS_COORDSYS" : "MapServer definition",
+    "FORM_EPSG_DEFINITION_VM4MS_VM4MS_COORDSYS" : "EPSG definition",
+    "FORM_EPSG_DEFINITION_DESCRIPTION_VM4MS_VM4MS_COORDSYS" : "Définition Proj4: pour utiliser cette projection au lieu de celles définies par défaut dans MapServer la ligne suivante doit être présente dans la définition du flux: CONFIG \"PROJ_LIB\" \"{MS_PROJ_DIR}\"",
+    "FORM_LABEL_VM4MS_VM4MS_COORDSYS" : "Label",
+    "" : "",
+    "FORM_TITLE_VM4MS_VM4MS_LAYER" : "Layer {{::name}}",
+    "FORM_LAYER_ID_VM4MS_VM4MS_LAYER" : "ID",
+    "FORM_NAME_VM4MS_VM4MS_LAYER" : "Nom",
+    "FORM_LAYER_TITLE_VM4MS_VM4MS_LAYER" : "Title",
+    "FORM_LAYER_NAME_VM4MS_VM4MS_LAYER" : "Name",
+    "FORM_COORDSYS_ID_VM4MS_VM4MS_LAYER" : "Coordinate system",
+    "FORM_SOURCE_ID_VM4MS_VM4MS_LAYER" : "Source",
+    "FORM_CONNECTION_ID_VM4MS_VM4MS_LAYER" : "Connection PostgreSql/Postgis",
+    "FORM_LAYERTYPE_ID_VM4MS_VM4MS_LAYER" : "Layer type",
+    "FORM_TABLESCHEMA_VM4MS_VM4MS_LAYER" : "Schema",
+    "FORM_TABLENAME_VM4MS_VM4MS_LAYER" : "Table",
+    "FORM_TABLEIDFIELD_VM4MS_VM4MS_LAYER" : "Identifier",
+    "FORM_OPACITY_VM4MS_VM4MS_LAYER" : "Opacity",
+    "FORM_ACTIVE_VM4MS_VM4MS_LAYER" : "Active layer",
+    "FORM_ACTIVE_YES_VM4MS_VM4MS_LAYER" : "Yes",
+    "FORM_ACTIVE_NO_VM4MS_VM4MS_LAYER" : "No",
+    "FORM_WMSSERVICE_VM4MS_VM4MS_LAYER" : "WMS Services",
+    "FORM_AVAILABLE_WMSSERVICE_VM4MS_VM4MS_LAYER" : "Available WMS services",
+    "FORM_LINKED_WMSSERVICE_VM4MS_VM4MS_LAYER" : "WMS services linked to layer",
+    "FORM_PRIVATE_CONNECTION_TOOLTIP_TITLE_VM4MS_VM4MS_LAYER" : "Private connection",
+    "FORM_PRIVATE_CONNECTION_TOOLTIP_CONTENT_VM4MS_VM4MS_LAYER" : "Attention, cette couche est exploitée par un flux WMS Public et ne sera plus visible si elle est associée à une connexion privée",
+    "FORM_BTN_SAVE_LAYER_VM4MS_VM4MS_LAYER" : "Save",
+    "FORM_BTN_TABLE_VM4MS_VM4MS_LAYER" : "Table",
+    "TOOLTIP_TITLE_TITLE_VM4MS_VM4MS_LAYER" : "Title",
+    "FORM_BTN_IDENTIFIER_VM4MS_VM4MS_LAYER" : "Identifier",
+    "FORM_DEFINITION_VM4MS_VM4MS_LAYER" : "Definition",
+    "FORM_PUBLISHED_VM4MS_VM4MS_LAYER" : "Published",
+    "FORM_TEMPORARY_VM4MS_VM4MS_LAYER" : "Temporary",
+    "FORM_TEST_LAYER_VM4MS_VM4MS_LAYER" : "Test",
+    "FORM_GETFEATUREINFO_TEMPLATE_VM4MS_VM4MS_LAYER" : "Template GetFeatureInfo",
+    "FORM_LAYER_GETFEATUREINFO_TEMPLATE_CONTENT" : "Template GetFeatureInfo",
+    "FORM_SAVE_GETFEATUREINFO_TEMPLATE_VM4MS_VM4MS_LAYER" : "Sauvegarder",
+    "FORM_REGEN_GETFEATUREINFO_TEMPLATE_VM4MS_VM4MS_LAYER" : "Régénérer le template",
+    "FORM_CANCEL_GETFEATUREINFO_TEMPLATE_VM4MS_VM4MS_LAYER" : "Annuler",
+    "MODAL_TITLE_PUBLISH_LAYER_VM4MS_VM4MS_LAYER" : "Publication of a layer",
+    "MODAL_CONTENT_PUBLISH_LAYER_VM4MS_VM4MS_LAYER" : "The temporary definition will definitely replace the published definition. Carry on ?",
+    "FORM_MAP_SERVER_SYMBOLS_MODAL_TITLE_VM4MS_VM4MS_LAYER" : "List of fonts in the fonts.list file",
+    "FORM_BTN_SYMBOLS_VM4MS_VM4MS_LAYER" : "Symboles",
+    "FORM_BTN_FONTS_VM4MS_VM4MS_LAYER" : "Polices",
+    "FORM_MAP_SERVER_FONTS_MODAL_TITLE_VM4MS_VM4MS_LAYER" : "Liste des polices du fichier fonts.sym",
+    "FORM_LAYER_NAME_TOOLTIP_CONTENT_VM4MS_VM4MS_LAYER" : "Layer name without spaces, accents and special characters.",
+    "FORM_LAYER_TITLE_TOOLTIP_CONTENT_VM4MS_VM4MS_LAYER" : "Layer name without any character restriction.",
+    "FORM_METADATA_ID_VM4MS_VM4MS_LAYER" : "Metadata",
+    "ERROR_ACTIVATE_VM4MS_VM4MS_LAYER" : "Error while activating a layer",
+    "ERROR_DESACTIVATE_VM4MS_VM4MS_LAYER" : "Error while deactivating a layer",
+    "ERROR_NO_SELECTION_RESET_VM4MS_VM4MS_LAYER" : "Please select or one several layers",
+    "MISSING_END_TAG" : "Missing END tag",
+    "TOO_MUCH_END_TAGS" : "Too much END tags",
+    "INDETERMINATED_ERROR" : "Indeterminated error",
+    "" : "",
+    "FORM_PALETTE_VM4MS_VM4MS_LAYER_DEFINITION" : "Palette",
+    "FORM_LAYER_LOGIN_VM4MS_VM4MS_LAYER_DEFINITION" : "User",
+    "FORM_LAYER_PASSWORD_VM4MS_VM4MS_LAYER_DEFINITION" : "Password",
+    "FORM_UPDATE_MAP_SERVER_TEST_VM4MS_VM4MS_LAYER_DEFINITION" : "Update and test with MapServer",
+    "FORM_UPDATE_OPENLAYERS_TEST_VM4MS_VM4MS_LAYER_DEFINITION" : "Update and test with OpenLayers 3",
+    "FORM_MAP_SERVER_MODAL_TITLE_VM4MS_VM4MS_LAYER_DEFINITION" : "Layer visualization test ",
+    "FORM_OPENLAYERS_MODAL_TITLE_VM4MS_VM4MS_LAYER_DEFINITION" : "Layer visualization test ",
+    "FORM_PUBLISH_MAP_SERVER_TEST_VM4MS_VM4MS_LAYER_DEFINITION" : "Publish and test with MapServer",
+    "FORM_PUBLISH_OPENLAYERS_TEST_VM4MS_VM4MS_LAYER_DEFINITION" : "Publish and test with OpenLayers 3",
+    "TAB_TITLE_TEST_LAYER_MAP_SERVER_VM4MS_LAYER_DEFINITION" : "MapServer",
+    "TAB_TITLE_TEST_LAYER_OPENLAYERS_VM4MS_LAYER_DEFINITION" : "OpenLayers 3",
+    "TAB_TITLE_TEST_LAYER_MAP_SERVER_LOG_VM4MS_LAYER_DEFINITION" : "Log",
+    "TAB_TITLE_TEST_LAYER_MAP_FILE_VM4MS_LAYER_DEFINITION" : "Map file",
+    "FORM_TEST_WMS_SERVICE_VM4MS_VM4MS_LAYER_DEFINITION" : "WMS Service used for the test",
+    "" : "",
+    "FORM_TITLE_VM4MS_VM4MS_LAYER_WMS_SERVICE" : "Couche {{::name}}",
+    "FORM_LAYER_ID_VM4MS_VM4MS_LAYER_WMS_SERVICE" : "ID",
+    "" : "",
+    "TITLE_GRID_AVAILABLE_LAYERS_VM4MS_PUBLIC_WMS_SERVICE_LAYERS" : "Available layers (public connection)",
+    "BTN_ADD_LAYERS_VM4MS_PUBLIC_WMS_SERVICE_LAYERS" : "Add layers",
+    "FORM_PRIVATE_VM4MS_VM4MS_PUBLIC_WMS_SERVICE_LAYERS" : "Layer type",
+    "FORM_PRIVATE_YES_VM4MS_VM4MS_PUBLIC_WMS_SERVICE_LAYERS" : "Private layer",
+    "FORM_PRIVATE_NO_VM4MS_VM4MS_PUBLIC_WMS_SERVICE_LAYERS" : "Public layer",
+    "FORM_LAYER_ID_VM4MS_VM4MS_PUBLIC_WMS_SERVICE_LAYERS" : "ID",
+    "FORM_GRID_TITLE_VM4MS_PUBLIC_WMS_SERVICE_LAYERS" : "WMS service layers",
+    "" : "",
+    "TAB_TITLE_GETCAPABILITIES_VM4MS_WMS_SERVICE_TESTS" : "GetCapabilities",
+    "TAB_TITLE_TEST_WMS_SERVICE_OL3_VM4MS_WMS_SERVICE_TESTS" : "Tester le flux WMS (avec OL3)",
+    "TAB_TITLE_TEST_WMS_SERVICE_MAP_SERVER_M4MS_WMS_SERVICE_TESTS" : "Tester le flux WMS (avec MapServer)",
+    "ERROR_LOAD_IMAGE_OPEN_LAYERS_M4MS_WMS_SERVICE_TESTS" : "Error : layer \"{{::LAYERS}}\"",
+    "ERROR_LOAD_IMAGE_OPEN_LAYERS_M4MS_WMS_SERVICE_TESTS_MULTIPLE" : "Error:",
+    "ERROR_LOAD_IMAGE_OPEN_LAYERS_M4MS_WMS_SERVICE_TESTS_MULTIPLE_INFO" : "The following layers are on error",
+    "TAB_TITLE_MAPSERVER_LOG_VM4MS_WMS_SERVICE_TESTS" : "Log",
+    "TAB_TITLE_MAPSERVER_LAYERS_VM4MS_WMS_SERVICE_TESTS" : "Couches à tester",
+    "TAB_TITLE_MAP_FILE_VM4MS_WMS_SERVICE_TESTS" : "Map file",
+    "" : "",
+    "FORM_TITLE_VM4MS_VM4MS_PRIVATE_WMS_SERVICE" : "Private WMS service {{::wmsservice_id}}",
+    "FORM_WMSSERVICEID_VM4MS_VM4MS_PRIVATE_WMS_SERVICE" : "ID",
+    "FORM_WEB_ID_VM4MS_VM4MS_PRIVATE_WMS_SERVICE" : "Web object",
+    "FORM_DESCRIPTION_VM4MS_VM4MS_PRIVATE_WMS_SERVICE" : "Description",
+    "FORM_DEFINITION_VM4MS_VM4MS_PRIVATE_WMS_SERVICE" : "Definition",
+    "FORM_LOGIN_VM4MS_VM4MS_PRIVATE_WMS_SERVICE_TESTS" : "User",
+    "FORM_PASSWORD_VM4MS_VM4MS_PRIVATE_WMS_SERVICE_TESTS" : "Password",
+    "FORM_WMS_SERVICE_URL_VM4MS_VM4MS_PRIVATE_WMS_SERVICE" : "Link",
+    "FORM_MSDEBUGLEVEL_ID_VM4MS_VM4MS_PRIVATE_WMS_SERVICE" : "Debug level for MapServer",
+    "FORM_PRIVATE_WMS_SERVICE_TOOLTIP_TITLE_VM4MS_VM4MS_PRIVATE_WMS_SERVICE" : "Flux WMS privé",
+    "FORM_PRIVATE_WMS_SERVICE_TOOLTIP_CONTENT_VM4MS_VM4MS_PRIVATE_WMS_SERVICE" : "You must reconnect to create the production map file with your changes.",
+    "FORM_PASSWORD_TOOLTIP_CONTENT_VM4MS_VM4MS_PRIVATE_WMS_SERVICE" : "The password for a public account is freely visible and can be known to all. If you want to protect your data including reading, use a private connection.",
+    "FORM_BTN_WMS_SERVICE_URL_VM4MS_VM4MS_PRIVATE_WMS_SERVICE" : "Copy",
+    "" : "",
+    "FORM_LAYER_ID_VM4MS_VM4MS_PRIVATE_WMS_SERVICE_LAYERS" : "ID",
+    "FORM_GRID_TITLE_VM4MS_PRIVATE_WMS_SERVICE_LAYERS" : "Couches privées",
+    "" : "",
+    "FORM_NAME_VM4MS_VM4MS_PUBLIC_WMS_SERVICE_AVAILABLE_LAYERS" : "Name",
+    "" : "",
+    "TITLE_PROPERTIES_CONFIGURATION_CONFIGURATION_VM4MS_CONFIG" : "General",
+    "FORM_TEST_WMS_SERVICE_CONFIGURATION_CONFIGURATION_VM4MS_CONFIG" : "WMS service for testing a layer",
+    "FORM_MAPSERVER_ALIAS_CONFIGURATION_CONFIGURATION_VM4MS_CONFIG" : "MapServer alias",
+	"FORM_DATADIR_CONFIGURATION_CONFIGURATION_VM4MS_CONFIG" : "Data directory",
+    "FORM_TEST_WMS_SERVICE_DEFAULT_CONTENT_CONFIGURATION_CONFIGURATION_VM4MS_CONFIG" : "Contenu par défaut du flux de test",
+    "FORM_GETFEATUREINFO_DEFAULT_CONTENT_CONFIGURATION_CONFIGURATION_VM4MS_CONFIG" : "Template GetFeatureInfo par défaut",
+    "ERROR_TEST_WMS_SERVICE_CONFIGURATION_CONFIGURATION_VM4MS_CONFIG" : "You must specify a test WMS service in the \"vMap4MapServer config\" section",
+    "ERROR_MS_CGI_URL_CONFIGURATION_CONFIGURATION_VM4MS_CONFIG" : "The url to MapServer is not specified.",
+    "" : "",
+    "FORM_TITLE_VM4MS_VM4MS_METADATA" : "Metadata {{::name}}",
+    "FORM_METADATA_ID_VM4MS_VM4MS_METADATA" : "ID",
+    "FORM_NAME_VM4MS_VM4MS_METADATA" : "Nom",
+    "FORM_DEFINITION_VM4MS_VM4MS_METADATA" : "Définition"
+}
diff --git a/vmap/client/modules/vm4ms/lang/lang-fr.json b/vmap/client/modules/vm4ms/lang/lang-fr.json
new file mode 100755
index 0000000000000000000000000000000000000000..67e42054b35640ff588457030b1ac9ca70d34767
--- /dev/null
+++ b/vmap/client/modules/vm4ms/lang/lang-fr.json
@@ -0,0 +1,172 @@
+{
+    "TITLE_MODE_VM4MS" : "MapServer",
+    "TEXT_MODE_VM4MS" : "Publication de flux WMS avec MapServer",
+    "" : "",
+    "SECTION_UPDATE_TITLE_VM4MS_VM4MS_PUBLIC_WMS_SERVICE" : "Flux WMS public {{sId}}",
+    "SECTION_INSERT_TITLE_VM4MS_VM4MS_PUBLIC_WMS_SERVICE" : "Flux WMS public",
+    "SECTION_DISPLAY_TITLE_VM4MS_VM4MS_PUBLIC_WMS_SERVICE" : "Flux WMS public {{sId}}",
+    "SECTION_UPDATE_TITLE_VM4MS_VM4MS_LAYER" : "Couche n°{{sId}}",
+    "SECTION_INSERT_TITLE_VM4MS_VM4MS_LAYER" : "Couche",
+    "SECTION_DISPLAY_TITLE_VM4MS_VM4MS_LAYER" : "Couche n°{{sId}}",
+    "SECTION_UPDATE_TITLE_VM4MS_VM4MS_PRIVATE_WMS_SERVICE" : "Flux WMS privé {{sId}}",
+    "SECTION_DISPLAY_TITLE_VM4MS_VM4MS_PRIVATE_WMS_SERVICE" : "Flux WMS privé {{sId}}",
+    "" : "",
+    "FORM_TITLE_VM4MS_VM4MS_PUBLIC_WMS_SERVICE" : "Flux WMS public {{::wmsservice_id}}",
+    "FORM_WMSSERVICEID_VM4MS_VM4MS_PUBLIC_WMS_SERVICE" : "ID",
+    "FORM_WEB_ID_VM4MS_VM4MS_PUBLIC_WMS_SERVICE" : "Objet web",
+    "FORM_DESCRIPTION_VM4MS_VM4MS_PUBLIC_WMS_SERVICE" : "Description",
+    "FORM_DEFINITION_VM4MS_VM4MS_PUBLIC_WMS_SERVICE" : "Définition",
+    "FORM_PALETTE_VM4MS_VM4MS_PUBLIC_WMS_SERVICE" : "Palette",
+    "FORM_WMS_SERVICE_URL_VM4MS_VM4MS_PUBLIC_WMS_SERVICE" : "Lien",
+    "FORM_MSDEBUGLEVEL_ID_VM4MS_VM4MS_PUBLIC_WMS_SERVICE" : "Niveau de log pour MapServer",
+    "FORM_BTN_WMS_SERVICE_URL_VM4MS_VM4MS_PUBLIC_WMS_SERVICE" : "Copier",
+    "" : "",
+    "FORM_TITLE_VM4MS_VM4MS_WEB_OBJECT" : "Objet web {{::name}}",
+    "FORM_WEB_ID_VM4MS_VM4MS_WEB_OBJECT" : "ID",
+    "FORM_NAME_VM4MS_VM4MS_WEB_OBJECT" : "Nom",
+    "FORM_DEFINITION_VM4MS_VM4MS_WEB_OBJECT" : "Définition",
+    "" : "",
+    "FORM_TITLE_VM4MS_VM4MS_CONNECTION" : "Connexion {{::name}}",
+    "FORM_CONNECTION_ID_VM4MS_VM4MS_CONNECTION" : "ID",
+    "FORM_NAME_VM4MS_VM4MS_CONNECTION" : "Nom",
+    "FORM_DEFINITION_VM4MS_VM4MS_CONNECTION" : "Définition",
+    "FORM_PRIVATE_VM4MS_VM4MS_CONNECTION" : "Connexion privée",
+    "FORM_PRIVATE_YES_VM4MS_VM4MS_CONNECTION" : "Oui",
+    "FORM_PRIVATE_NO_VM4MS_VM4MS_CONNECTION" : "Non",
+    "FORM_SERVER_VM4MS_VM4MS_CONNECTION" : "Serveur",
+    "FORM_PORT_VM4MS_VM4MS_CONNECTION" : "Port",
+    "FORM_DATABASE_VM4MS_VM4MS_CONNECTION" : "Base de données",
+    "FORM_USER_VM4MS_VM4MS_CONNECTION" : "Utilisateur",
+    "FORM_PASSWORD_VM4MS_VM4MS_CONNECTION" : "Mot de passe",
+    "" : "",
+    "FORM_TITLE_VM4MS_VM4MS_SOURCE" : "Source {{::name}}",
+    "FORM_SOURCE_ID_VM4MS_VM4MS_SOURCE" : "ID",
+    "FORM_NAME_VM4MS_VM4MS_SOURCE" : "Nom",
+    "" : "",
+    "FORM_TITLE_VM4MS_VM4MS_COORDSYS" : "Système de coordonnées {{::coordsys_id}}",
+    "FORM_SRID_VM4MS_VM4MS_COORDSYS" : "Srid",
+    "FORM_EPSG_VM4MS_VM4MS_COORDSYS" : "Code EPSG",
+    "FORM_DEFINITION_VM4MS_VM4MS_COORDSYS" : "Définition MapServer",
+    "FORM_EPSG_DEFINITION_VM4MS_VM4MS_COORDSYS" : "Définition EPSG",
+    "FORM_EPSG_DEFINITION_DESCRIPTION_VM4MS_VM4MS_COORDSYS" : "Définition Proj4: pour utiliser cette projection au lieu de celles définies par défaut dans MapServer la ligne suivante doit être présente dans la définition du flux: CONFIG \"PROJ_LIB\" \"{MS_PROJ_DIR}\"",
+    "FORM_LABEL_VM4MS_VM4MS_COORDSYS" : "Libellé",
+    "" : "",
+    "FORM_TITLE_VM4MS_VM4MS_LAYER" : "Couche {{::name}}",
+    "FORM_LAYER_ID_VM4MS_VM4MS_LAYER" : "ID",
+    "FORM_NAME_VM4MS_VM4MS_LAYER" : "Nom",
+    "FORM_LAYER_TITLE_VM4MS_VM4MS_LAYER" : "Titre",
+    "FORM_LAYER_NAME_VM4MS_VM4MS_LAYER" : "Nom",
+    "FORM_COORDSYS_ID_VM4MS_VM4MS_LAYER" : "Système de coordonnées",
+    "FORM_SOURCE_ID_VM4MS_VM4MS_LAYER" : "Source",
+    "FORM_CONNECTION_ID_VM4MS_VM4MS_LAYER" : "Connexion PostgreSql/Postgis",
+    "FORM_LAYERTYPE_ID_VM4MS_VM4MS_LAYER" : "Type de géométrie",
+    "FORM_TABLESCHEMA_VM4MS_VM4MS_LAYER" : "Schéma",
+    "FORM_TABLENAME_VM4MS_VM4MS_LAYER" : "Table",
+    "FORM_TABLEIDFIELD_VM4MS_VM4MS_LAYER" : "Identifiant",
+    "FORM_OPACITY_VM4MS_VM4MS_LAYER" : "Opacité",
+    "FORM_ACTIVE_VM4MS_VM4MS_LAYER" : "Couche active",
+    "FORM_ACTIVE_YES_VM4MS_VM4MS_LAYER" : "Oui",
+    "FORM_ACTIVE_NO_VM4MS_VM4MS_LAYER" : "Non",
+    "FORM_WMSSERVICE_VM4MS_VM4MS_LAYER" : "Flux WMS",
+    "FORM_AVAILABLE_WMSSERVICE_VM4MS_VM4MS_LAYER" : "Flux WMS disponibles",
+    "FORM_LINKED_WMSSERVICE_VM4MS_VM4MS_LAYER" : "Flux WMS liés à la couche",
+    "FORM_PRIVATE_CONNECTION_TOOLTIP_TITLE_VM4MS_VM4MS_LAYER" : "Connexion privée",
+    "FORM_PRIVATE_CONNECTION_TOOLTIP_CONTENT_VM4MS_VM4MS_LAYER" : "Attention, cette couche est exploitée par un flux WMS Public et ne sera plus visible si elle est associée à une connexion privée",
+    "FORM_BTN_SAVE_LAYER_VM4MS_VM4MS_LAYER" : "Sauvegarder",
+    "FORM_BTN_TABLE_VM4MS_VM4MS_LAYER" : "Table",
+    "TOOLTIP_TITLE_TITLE_VM4MS_VM4MS_LAYER" : "Titre",
+    "FORM_BTN_IDENTIFIER_VM4MS_VM4MS_LAYER" : "Identifiant",
+    "FORM_DEFINITION_VM4MS_VM4MS_LAYER" : "Définition",
+    "FORM_PUBLISHED_VM4MS_VM4MS_LAYER" : "Publiée",
+    "FORM_TEMPORARY_VM4MS_VM4MS_LAYER" : "Temporaire",
+    "FORM_TEST_LAYER_VM4MS_VM4MS_LAYER" : "Tester",
+    "FORM_GETFEATUREINFO_TEMPLATE_VM4MS_VM4MS_LAYER" : "Template GetFeatureInfo",
+    "FORM_LAYER_GETFEATUREINFO_TEMPLATE_CONTENT" : "Template GetFeatureInfo",
+    "FORM_SAVE_GETFEATUREINFO_TEMPLATE_VM4MS_VM4MS_LAYER" : "Sauvegarder",
+    "FORM_REGEN_GETFEATUREINFO_TEMPLATE_VM4MS_VM4MS_LAYER" : "Régénérer le template",
+    "FORM_CANCEL_GETFEATUREINFO_TEMPLATE_VM4MS_VM4MS_LAYER" : "Annuler",
+    "MODAL_TITLE_PUBLISH_LAYER_VM4MS_VM4MS_LAYER" : "Publication d'une couche",
+    "MODAL_CONTENT_PUBLISH_LAYER_VM4MS_VM4MS_LAYER" : "La définition temporaire va définitivement remplacer la définition publiée. Continuer ?",
+    "FORM_MAP_SERVER_SYMBOLS_MODAL_TITLE_VM4MS_VM4MS_LAYER" : "Liste des symboles du fichier symbols.sym",
+    "FORM_BTN_SYMBOLS_VM4MS_VM4MS_LAYER" : "Symbols",
+    "FORM_BTN_FONTS_VM4MS_VM4MS_LAYER" : "Fonts",
+    "FORM_MAP_SERVER_FONTS_MODAL_TITLE_VM4MS_VM4MS_LAYER" : "Liste des polices du fichier fonts.list",
+    "FORM_LAYER_NAME_TOOLTIP_CONTENT_VM4MS_VM4MS_LAYER" : "Nom de la couche sans espaces, accents et caractères spéciaux.",
+    "FORM_LAYER_TITLE_TOOLTIP_CONTENT_VM4MS_VM4MS_LAYER" : "Nom de la couche sans restriction de caractères.",
+    "FORM_METADATA_ID_VM4MS_VM4MS_LAYER" : "Métadonnées",
+    "ERROR_ACTIVATE_VM4MS_VM4MS_LAYER" : "Erreur pendant l'activation d'une couche",
+    "ERROR_DESACTIVATE_VM4MS_VM4MS_LAYER" : "Erreur pendant la désactivation d'une couche",
+    "ERROR_NO_SELECTION_RESET_VM4MS_VM4MS_LAYER" : "Veuillez sélectionner une ou plusieurs couches",
+    "MISSING_END_TAG" : "Balise END manquante",
+    "TOO_MUCH_END_TAGS" : "Balise END en trop",
+    "INDETERMINATED_ERROR" : "Erreur indéterminée",
+    "" : "",
+    "FORM_PALETTE_VM4MS_VM4MS_LAYER_DEFINITION" : "Palette",
+    "FORM_LAYER_LOGIN_VM4MS_VM4MS_LAYER_DEFINITION" : "Utilisateur",
+    "FORM_LAYER_PASSWORD_VM4MS_VM4MS_LAYER_DEFINITION" : "Mot de passe",
+    "FORM_UPDATE_MAP_SERVER_TEST_VM4MS_VM4MS_LAYER_DEFINITION" : "Mettre à jour et tester avec MapServer",
+    "FORM_UPDATE_OPENLAYERS_TEST_VM4MS_VM4MS_LAYER_DEFINITION" : "Mettre à jour et tester avec OpenLayers 3",
+    "FORM_MAP_SERVER_MODAL_TITLE_VM4MS_VM4MS_LAYER_DEFINITION" : "Test de visualisation de la couche ",
+    "FORM_OPENLAYERS_MODAL_TITLE_VM4MS_VM4MS_LAYER_DEFINITION" : "Test de visualisation de la couche ",
+    "FORM_PUBLISH_MAP_SERVER_TEST_VM4MS_VM4MS_LAYER_DEFINITION" : "Publier et tester avec MapServer",
+    "FORM_PUBLISH_OPENLAYERS_TEST_VM4MS_VM4MS_LAYER_DEFINITION" : "Publier et tester avec OpenLayers 3",
+    "TAB_TITLE_TEST_LAYER_MAP_SERVER_VM4MS_LAYER_DEFINITION" : "MapServer",
+    "TAB_TITLE_TEST_LAYER_OPENLAYERS_VM4MS_LAYER_DEFINITION" : "OpenLayers 3",
+    "TAB_TITLE_TEST_LAYER_MAP_SERVER_LOG_VM4MS_LAYER_DEFINITION" : "Log",
+    "TAB_TITLE_TEST_LAYER_MAP_FILE_VM4MS_LAYER_DEFINITION" : "Fichier map",
+    "FORM_TEST_WMS_SERVICE_VM4MS_VM4MS_LAYER_DEFINITION" : "Flux WMS utilisé pour le test",
+    "" : "",
+    "FORM_TITLE_VM4MS_VM4MS_LAYER_WMS_SERVICE" : "Couche {{::name}}",
+    "FORM_LAYER_ID_VM4MS_VM4MS_LAYER_WMS_SERVICE" : "ID",
+    "" : "",
+    "TITLE_GRID_AVAILABLE_LAYERS_VM4MS_PUBLIC_WMS_SERVICE_LAYERS" : "Couches disponibles (connexion de type public)",
+    "BTN_ADD_LAYERS_VM4MS_PUBLIC_WMS_SERVICE_LAYERS" : "Ajouter les couches",
+    "FORM_PRIVATE_VM4MS_VM4MS_PUBLIC_WMS_SERVICE_LAYERS" : "Type de couches",
+    "FORM_PRIVATE_YES_VM4MS_VM4MS_PUBLIC_WMS_SERVICE_LAYERS" : "Couches privées",
+    "FORM_PRIVATE_NO_VM4MS_VM4MS_PUBLIC_WMS_SERVICE_LAYERS" : "Couches publiques",
+    "FORM_LAYER_ID_VM4MS_VM4MS_PUBLIC_WMS_SERVICE_LAYERS" : "ID",
+    "FORM_GRID_TITLE_VM4MS_PUBLIC_WMS_SERVICE_LAYERS" : "Couches du flux WMS",
+    "" : "",
+    "TAB_TITLE_GETCAPABILITIES_VM4MS_WMS_SERVICE_TESTS" : "GetCapabilities",
+    "TAB_TITLE_TEST_WMS_SERVICE_OL3_VM4MS_WMS_SERVICE_TESTS" : "Tester le flux WMS (avec OL3)",
+    "TAB_TITLE_TEST_WMS_SERVICE_MAP_SERVER_VM4MS_WMS_SERVICE_TESTS" : "Tester le flux WMS (avec MapServer)",
+    "ERROR_LOAD_IMAGE_OPEN_LAYERS_M4MS_WMS_SERVICE_TESTS" : "Erreur : couche \"{{::LAYERS}}\"",
+    "ERROR_LOAD_IMAGE_OPEN_LAYERS_M4MS_WMS_SERVICE_TESTS_MULTIPLE" : "Erreur:",
+    "ERROR_LOAD_IMAGE_OPEN_LAYERS_M4MS_WMS_SERVICE_TESTS_MULTIPLE_INFO" : "Les couches suivantes sont en erreur",
+    "TAB_TITLE_MAPSERVER_LOG_VM4MS_WMS_SERVICE_TESTS" : "Log",
+    "TAB_TITLE_MAPSERVER_LAYERS_VM4MS_WMS_SERVICE_TESTS" : "Couches à tester",
+    "TAB_TITLE_MAP_FILE_VM4MS_WMS_SERVICE_TESTS" : "Fichier map",
+    "" : "",
+    "FORM_TITLE_VM4MS_VM4MS_PRIVATE_WMS_SERVICE" : "Flux WMS privé {{::wmsservice_id}}",
+    "FORM_WMSSERVICEID_VM4MS_VM4MS_PRIVATE_WMS_SERVICE" : "ID",
+    "FORM_WEB_ID_VM4MS_VM4MS_PRIVATE_WMS_SERVICE" : "Objet web",
+    "FORM_DESCRIPTION_VM4MS_VM4MS_PRIVATE_WMS_SERVICE" : "Description",
+    "FORM_DEFINITION_VM4MS_VM4MS_PRIVATE_WMS_SERVICE" : "Définition",
+    "FORM_LOGIN_VM4MS_VM4MS_PRIVATE_WMS_SERVICE_TESTS" : "Utilisateur",
+    "FORM_PASSWORD_VM4MS_VM4MS_PRIVATE_WMS_SERVICE_TESTS" : "Mot de passe",
+    "FORM_WMS_SERVICE_URL_VM4MS_VM4MS_PRIVATE_WMS_SERVICE" : "Lien",
+    "FORM_MSDEBUGLEVEL_ID_VM4MS_VM4MS_PRIVATE_WMS_SERVICE" : "Niveau de log pour MapServer",
+    "FORM_PRIVATE_WMS_SERVICE_TOOLTIP_TITLE_VM4MS_VM4MS_PRIVATE_WMS_SERVICE" : "Flux WMS privé",
+    "FORM_PRIVATE_WMS_SERVICE_TOOLTIP_CONTENT_VM4MS_VM4MS_PRIVATE_WMS_SERVICE" : "Vous devez vous reconnecter pour créer le fichier map de production avec vos modifications.",
+    "FORM_PASSWORD_TOOLTIP_CONTENT_VM4MS_VM4MS_PRIVATE_WMS_SERVICE" : "Le mot de passe d'un compte public est librement visible et peut être connu de tous. Si vous souhaitez protéger vos données y compris en lecture, utilisez une connexion privée.",
+    "FORM_BTN_WMS_SERVICE_URL_VM4MS_VM4MS_PRIVATE_WMS_SERVICE" : "Copier",
+    "" : "",
+    "FORM_LAYER_ID_VM4MS_VM4MS_PRIVATE_WMS_SERVICE_LAYERS" : "ID",
+    "FORM_GRID_TITLE_VM4MS_PRIVATE_WMS_SERVICE_LAYERS" : "Couches privées",
+    "" : "",
+    "FORM_NAME_VM4MS_VM4MS_PUBLIC_WMS_SERVICE_AVAILABLE_LAYERS" : "Nom",
+    "" : "",
+    "TITLE_PROPERTIES_CONFIGURATION_CONFIGURATION_VM4MS_CONFIG" : "Général",
+    "FORM_TEST_WMS_SERVICE_CONFIGURATION_CONFIGURATION_VM4MS_CONFIG" : "Flux WMS pour tester une couche",
+    "FORM_MAPSERVER_ALIAS_CONFIGURATION_CONFIGURATION_VM4MS_CONFIG" : "Alias de MapServer",
+	"FORM_DATADIR_CONFIGURATION_CONFIGURATION_VM4MS_CONFIG" : "Répertoire des données",
+	"FORM_TEST_WMS_SERVICE_DEFAULT_CONTENT_CONFIGURATION_CONFIGURATION_VM4MS_CONFIG" : "Contenu par défaut du flux de test",
+	"FORM_GETFEATUREINFO_DEFAULT_CONTENT_CONFIGURATION_CONFIGURATION_VM4MS_CONFIG" : "Template GetFeatureInfo par défaut",
+    "ERROR_TEST_WMS_SERVICE_CONFIGURATION_CONFIGURATION_VM4MS_CONFIG" : "Vous devez spécifier un flux WMS de test dans la section \"configuration vMap4MapServer\".",
+    "ERROR_MS_CGI_URL_CONFIGURATION_CONFIGURATION_VM4MS_CONFIG" : "L'url vers MapServer n'est pas spécifiée.",
+    "" : "",
+    "FORM_TITLE_VM4MS_VM4MS_METADATA" : "Metadonnée {{::name}}",
+    "FORM_METADATA_ID_VM4MS_VM4MS_METADATA" : "ID",
+    "FORM_NAME_VM4MS_VM4MS_METADATA" : "Nom",
+    "FORM_DEFINITION_VM4MS_VM4MS_METADATA" : "Définition"
+}
diff --git a/vmap/client/modules/vm4ms/less/layer.less b/vmap/client/modules/vm4ms/less/layer.less
new file mode 100755
index 0000000000000000000000000000000000000000..82271f45879e74b8a07c2490814ba00ab812a0c7
--- /dev/null
+++ b/vmap/client/modules/vm4ms/less/layer.less
@@ -0,0 +1,106 @@
+// Connexion, base de données, schéma, table, identifiant.
+.layer-connexion-row > div:nth-child(even) {
+    width: 18%;
+    padding-right: 0;
+}
+.layer-connexion-row > div:nth-child(odd) {
+    padding-right: 0;
+}
+.layer-connexion-row > div:nth-child(1) {
+    padding-right: 16px;
+    width: 24%;
+}
+.layer-connexion-row > div:nth-child(3) {
+    width: 82px;
+}
+.layer-connexion-row > div:nth-child(5) {
+    width: 106px;
+}
+
+// Icônes de redimensionnement de l'éditeur CodeMirror'.
+.layer-definition-full-screen-icon {
+    position: absolute;
+    bottom: 40px;
+    cursor: pointer;
+    z-index: 999;
+}
+.layer-definition-full-screen-icon {
+    right: 45px;
+}
+
+// Formulaire de la section "Informations générales".
+.form-vm4ms-layer-general {
+    position: absolute;
+    width: 100%;
+    padding-right: 15px;
+}
+
+// Palette pour la définition de la couche.
+.vm4ms-layer-palette {
+    position: absolute;
+    right: 15px;
+    bottom: 0;
+    width: 150px;
+}
+.vm4ms-layer-palette > input {
+    height: 30px !important;
+}
+// Lien vers la liste des symboles.
+.vm4ms-layer-symbols-update, .vm4ms-layer-symbols-insert {
+    position: absolute;
+    right: 0;
+}
+.vm4ms-layer-symbols-update {
+    bottom: 40px;
+}
+.vm4ms-layer-symbols-insert {
+    bottom: 0;
+}
+
+// Boutons "Symboles" et "Polices".
+.form-row-layer-palette > div:last-child {
+    position: absolute;
+    right: 0;
+    width: 310px;
+    bottom: 18px;
+}
+
+// Fenêtre modale des polices de MapServer.
+.dialog-modal-window-mapserver-fonts .modal-body {
+    overflow-x: hidden;
+    overflow-y: auto;
+    margin-bottom: 4px;
+}
+.dialog-modal-window-mapserver-fonts .bootbox-body {
+    height: 100%;
+}
+.mapserver-fonts-container {
+    height: 100%;
+}
+.mapserver-fonts-container > div {
+    padding-left: 0;
+    padding-right: 0;
+}
+.mapserver-fonts-container .panel-heading {
+    background-color: #f5f5f5;
+}
+// Liste des symboles.
+.mapserver-fonts-container .panel-body {
+    padding: 10px;
+}
+.mapserver-fonts-container .panel-body > ul {
+    padding-left: 0;
+    list-style-type: none;
+}
+.mapserver-fonts-container .panel-group {
+    margin-bottom: 5px;
+}
+.mapserver-fonts-container .list-group-item {
+    height: 32px;
+}
+.mapserver-fonts-container .list-group-item > span {
+    line-height: 28px;
+}
+.mapserver-fonts-container .list-group-item > span:nth-child(1) {
+    font-weight: bold;
+}
\ No newline at end of file
diff --git a/vmap/client/modules/vm4ms/less/layerTests.less b/vmap/client/modules/vm4ms/less/layerTests.less
new file mode 100755
index 0000000000000000000000000000000000000000..75d52252fd3b667703fd300fb5286f049cc51af0
--- /dev/null
+++ b/vmap/client/modules/vm4ms/less/layerTests.less
@@ -0,0 +1,148 @@
+.layer-tests {
+    width: 100%;
+    height: 100%;
+    padding: 13px 0;
+    margin: 0;
+    background-color: #f8f8f8;
+}
+.layer-tests > div, .layer-tests .tab-pane {
+    height: 100%;
+}
+.layer-tests .tab-content {
+    background-color: #fff;
+    border: 1px solid #ddd;
+    border-top: none;
+    border-radius: 0 4px 4px 4px;
+    //overflow: hidden;
+}
+.layer-tests .tab-pane {
+    //overflow: hidden;
+}
+// Test du flux WMS (OpenLayers).
+#layer_tests_layer_ol_map {
+    width: 100%;
+    height: 100%;
+}
+// 
+.layer-tests a[role='tab'] {
+    padding: 5px 10px 5px 10px;
+}
+// Boutons de raffraichissement des onglets.
+.layer-tests .btn-refresh-tab {
+    display: none;
+}
+.layer-tests .active .btn-refresh-tab {
+    display: initial;
+}
+//
+.layer-tests .nav-tabs > li > a {
+    line-height: 34px;
+}
+// Test du flux WMS (MapServer).
+#layer_tests_layer_ms_iframe {
+    width: 100%;
+    height: 100%;
+    border: none;
+    //overflow-y: scroll;
+}
+
+// Tous les parents de la carte vmap (formulaire) : hauteur à 100%.
+#layer_tests_layer_ol_map > div,
+#layer_tests_layer_ol_map > div > div,
+#layer_tests_layer_ol_map > div > div > form,
+#layer_tests_layer_ol_map > div > div > form > div,
+#layer_tests_layer_ol_map > div > div > form > div > div:last-child,
+#layer_tests_layer_ol_map > div > div > form > div > div > div,
+#layer_tests_layer_ol_map > div > div > form > div > div > div > div,
+#layer_tests_layer_ol_map > div > div > form > div > div > div > div > div,
+#layer_tests_layer_ol_map > div > div > form > div > div > div > div > div > div,
+#layer_tests_layer_ol_map > div > div > form > div > div > div > div > div > div > div,
+#layer_tests_layer_ol_map > div > div > form > div > div > div > div > div > div > div > div,
+#layer_tests_layer_ol_map > div > div > form > div > div > div > div > div > div > div > div > div,
+#layer_tests_layer_ol_map > div > div > form > div > div > div > div > div > div > div > div > div > div {
+    height: 100%;
+}
+
+// Pas de marge dans le form.
+#layer_openlayers_test_update_form {
+    margin: 0 !important;
+}
+
+// Pas de label pour la carte vmap.
+#layer_test_map_label {
+    display: none;
+}
+
+// Onglet des logs de MapServer.
+.layer-mapserver-log > textarea{
+    width: 100%;
+    height: 100%;
+    resize: none;
+    font-size: 11px;
+}
+
+// Test d'une couche avec MapServer.
+.mapserver-layer-test-popup .modal-body {
+    padding: 5px;
+}
+.mapserver-layer-test-iframe {
+    width: 100%;
+    height: 100%;
+    border: none;
+}
+.mapserver-layer-test-popup .modal-content {
+    height: 100%;
+}
+.mapserver-layer-test-popup .bootbox-body, .mapserver-layer-test-popup .mapserver-layer-test-container {
+    width: 100%;
+    height: 100%;
+}
+
+// Test d'une couche avec OpenLAyers.
+.openlayers-layer-test-popup .bootbox-body, .openlayers-layer-test-popup .openlayers-layer-test-container, .openlayers-layer-test-container > div, .openlayers-layer-test-container .ng-isolate-scope {
+    width: 100%;
+    height: 100%;
+}
+.openlayers-layer-test-container form, .openlayers-layer-test-popup form, .openlayers-layer-test-popup .form-row {
+    margin: 0;
+}
+.openlayers-layer-test-container form, .openlayers-layer-test-container form > div, .openlayers-layer-test-container form .form-group, .openlayers-layer-test-container form .form-group > div, .openlayers-layer-test-container form .form-group > div > div {
+    width: 100%;
+    height: 100%;
+}
+.openlayers-layer-test-popup form div[ng-switch-when^='map_'] {
+    width: 100%;
+    height: 100%;
+}
+// Pas de label au-dessus de la carte.
+.openlayers-layer-test-popup form div[ng-switch-when^='map_'] > label {
+    display: none;
+}
+/*
+.openlayers-layer-test-popup form, .openlayers-layer-test-popup .form-row {
+    margin: 0;
+}
+*/
+.openlayers-layer-test-container form .form-group {
+    padding: 0;
+}
+// Boutons de la carte (zoom, édition...)
+.openlayers-layer-test-popup .form-map-Group-btn-zoom {
+    left: 25px;
+    top: 25px;
+}
+.openlayers-layer-test-popup .form-map-Group-btn-interact {
+    right: 25px;
+    top: 25px;
+}
+
+// Test d'une couche (fenêtre modale).
+.layer-test-dialog-modal-window .modal-body {
+    padding: 0;
+}
+.layer-test-dialog-modal-window .bootbox-body {
+    //height: 100%;
+}
+.layer_test_container {
+    height: 100%;
+}
\ No newline at end of file
diff --git a/vmap/client/modules/vm4ms/less/main.less b/vmap/client/modules/vm4ms/less/main.less
new file mode 100755
index 0000000000000000000000000000000000000000..828bd274503a147a91d5a9853952aaf3754b02f0
--- /dev/null
+++ b/vmap/client/modules/vm4ms/less/main.less
@@ -0,0 +1,9 @@
+// LESS
+@ui-grid-bg-image: "../images/ui-grid/wbg.gif";
+@font-color-purple: #6d1a67;
+@test-color: black;
+@import 'wmsServiceTests.less';
+@import 'layer.less';
+@import 'layerTests.less';
+@import 'mapServerSymbols.less';
+@import 'wmsService.less';
\ No newline at end of file
diff --git a/vmap/client/modules/vm4ms/less/mapServerSymbols.less b/vmap/client/modules/vm4ms/less/mapServerSymbols.less
new file mode 100755
index 0000000000000000000000000000000000000000..db909604f1afe8b27246ea4a1ce6dfc4991fea29
--- /dev/null
+++ b/vmap/client/modules/vm4ms/less/mapServerSymbols.less
@@ -0,0 +1,29 @@
+.dialog-modal-window-mapserver-symbols .modal-body {
+    overflow-x: hidden;
+    overflow-y: auto;
+    margin-bottom: 4px;
+}
+.dialog-modal-window-mapserver-symbols .bootbox-body {
+    height: 100%;
+}
+.mapserver-symbols-container {
+    height: 100%;
+}
+.mapserver-symbols-container > div {
+    padding-left: 0;
+    padding-right: 0;
+}
+.mapserver-symbols-container .panel-heading {
+    background-color: #f5f5f5;
+}
+// Liste des symboles.
+.mapserver-symbols-container .panel-body {
+    padding: 10px;
+}
+.mapserver-symbols-container .panel-body > ul {
+    padding-left: 0;
+    list-style-type: none;
+}
+.mapserver-symbols-container .panel-group {
+    margin-bottom: 5px;
+}
\ No newline at end of file
diff --git a/vmap/client/modules/vm4ms/less/wmsService.less b/vmap/client/modules/vm4ms/less/wmsService.less
new file mode 100755
index 0000000000000000000000000000000000000000..3dd83122dd589fda90b965885d6e4321108a92d2
--- /dev/null
+++ b/vmap/client/modules/vm4ms/less/wmsService.less
@@ -0,0 +1,5 @@
+// Lien vers le flux WMS.
+.wms-service-url > div:nth-child(2) {
+    width: auto;
+    max-width: 58%;
+}
\ No newline at end of file
diff --git a/vmap/client/modules/vm4ms/less/wmsServiceTests.less b/vmap/client/modules/vm4ms/less/wmsServiceTests.less
new file mode 100755
index 0000000000000000000000000000000000000000..7b099ddab83396a2c33f00496b7d9c41f7694e25
--- /dev/null
+++ b/vmap/client/modules/vm4ms/less/wmsServiceTests.less
@@ -0,0 +1,81 @@
+.wms-service-tests {
+    width: 100%;
+    height: 100%;
+    padding: 13px 0;
+    margin: 0;
+}
+.wms-service-tests > div, .wms-service-tests .tab-pane {
+    height: 100%;
+}
+.wms-service-tests .tab-content {
+    background-color: #fff;
+    border: 1px solid #ddd;
+    border-top: none;
+    border-radius: 0 4px 4px 4px;
+}
+// GetCapabilities
+#wms_service_tests_get_capabilities_textarea {
+    width: 100%;
+    height: 100%;
+    border: none;
+}
+// Test du flux WMS (OpenLayers).
+#wms_service_tests_wms_service_ol_map {
+    width: 100%;
+    height: 100%;
+}
+// 
+.wms-service-tests a[role='tab'] {
+    padding: 5px 5px 5px 10px;
+}
+// Boutons de raffraichissement des onglets.
+.wms-service-tests .btn-refresh-tab {
+    display: none;
+}
+.wms-service-tests .active .btn-refresh-tab {
+    display: initial;
+}
+//
+.wms-service-tests .nav-tabs > li > a {
+    line-height: 34px;
+}
+// Test du flux WMS (MapServer).
+#wms_service_tests_wms_service_ms_iframe {
+    width: 100%;
+    height: 100%;
+    border: none;
+}
+
+// Tous les parents de la carte vmap (formulaire) : hauteur à 100%.
+#wms_service_tests_wms_service_ol_map > div,
+#wms_service_tests_wms_service_ol_map > div > div,
+#wms_service_tests_wms_service_ol_map > div > div > form,
+#wms_service_tests_wms_service_ol_map > div > div > form > div,
+#wms_service_tests_wms_service_ol_map > div > div > form > div > div:last-child,
+#wms_service_tests_wms_service_ol_map > div > div > form > div > div > div,
+#wms_service_tests_wms_service_ol_map > div > div > form > div > div > div > div,
+#wms_service_tests_wms_service_ol_map > div > div > form > div > div > div > div > div,
+#wms_service_tests_wms_service_ol_map > div > div > form > div > div > div > div > div > div,
+#wms_service_tests_wms_service_ol_map > div > div > form > div > div > div > div > div > div > div,
+#wms_service_tests_wms_service_ol_map > div > div > form > div > div > div > div > div > div > div > div,
+#wms_service_tests_wms_service_ol_map > div > div > form > div > div > div > div > div > div > div > div > div,
+#wms_service_tests_wms_service_ol_map > div > div > form > div > div > div > div > div > div > div > div > div > div {
+    height: 100%;
+}
+// Pas de marge dans le form.
+#wms_service_openlayers_test_update_form {
+    margin: 0 !important;
+}
+
+// Pas de label pour la carte vmap.
+#wms_service_test_map_label {
+    display: none;
+}
+
+// Onglet des logs de MapServer.
+.wms_service-mapserver-log > textarea{
+    width: 100%;
+    height: 100%;
+    resize: none;
+    font-size: 11px;
+}
diff --git a/vmap/client/modules/vm4ms/template/layerGetFeatureInfoTemplateTpl.html b/vmap/client/modules/vm4ms/template/layerGetFeatureInfoTemplateTpl.html
new file mode 100755
index 0000000000000000000000000000000000000000..fcfd7c9664088a2238711041162a090101f1c450
--- /dev/null
+++ b/vmap/client/modules/vm4ms/template/layerGetFeatureInfoTemplateTpl.html
@@ -0,0 +1,11 @@
+<div class="row">
+    <div class="col-xs-12">
+        <!--Form reader-->
+        <div id="layer_getfeatureinfo_template_form_reader"
+             app-form-reader
+             app-properties="oLayerGetfeatureinfoForm.oProperties"
+             app-form-definition="oLayerGetfeatureinfoForm.oFormDefinition"
+             app-form-definition-name="oLayerGetfeatureinfoForm.oFormDefinitionName"
+             app-form-values="oLayerGetfeatureinfoForm.oFormValues"></div>
+    </div>
+</div>
diff --git a/vmap/client/modules/vm4ms/template/layerTestsTpl.html b/vmap/client/modules/vm4ms/template/layerTestsTpl.html
new file mode 100755
index 0000000000000000000000000000000000000000..54459c1775eed756a78698966fd4329c36f63a8e
--- /dev/null
+++ b/vmap/client/modules/vm4ms/template/layerTestsTpl.html
@@ -0,0 +1,34 @@
+<div class="row layer-tests">
+    <div data-app-layer-tests="" class="col-xs-12">
+        <!-- Menu -->
+        <ul class="nav nav-tabs" role="tablist">
+            <li role="presentation" class="active">
+                <a href="#layer_tests_layer_mapserver" aria-controls="layer_tests_layer_mapserver" role="tab" data-toggle="tab" ng-click="testLayerWithMapServer()">{{ 'TAB_TITLE_TEST_LAYER_MAP_SERVER_VM4MS_LAYER_DEFINITION' | translate }}</a>
+            </li>
+            <li role="presentation">
+                <a href="#layer_tests_layer_ol" aria-controls="layer_tests_layer_ol" role="tab" data-toggle="tab" ng-click="testLayerWithOpenLayers()">{{ 'TAB_TITLE_TEST_LAYER_OPENLAYERS_VM4MS_LAYER_DEFINITION' | translate }}</a>
+            </li>
+            <li role="presentation">
+                <a href="#layer_mapserver_log" aria-controls="layer_mapserver_log" role="tab" data-toggle="tab" ng-click="loadLayerMapServerLog()">{{ 'TAB_TITLE_TEST_LAYER_MAP_SERVER_LOG_VM4MS_LAYER_DEFINITION' | translate }}</a>
+            </li>
+            <li role="presentation">
+                <a href="#layer_map_file" aria-controls="layer_map_file" role="tab" data-toggle="tab" ng-click="loadLayerMapFile()">{{ 'TAB_TITLE_TEST_LAYER_MAP_FILE_VM4MS_LAYER_DEFINITION' | translate }}</a>
+            </li>
+        </ul>
+        <!-- Onglets -->
+        <div class="tab-content">
+            <div role="tabpanel" class="tab-pane active" id="layer_tests_layer_mapserver">
+                <iframe src="" id="layer_tests_layer_ms_iframe"></iframe>
+            </div>
+            <div role="tabpanel" class="tab-pane" id="layer_tests_layer_ol">
+                <div id="layer_tests_layer_ol_map"></div>
+            </div>
+            <div role="tabpanel" class="tab-pane layer-mapserver-log" id="layer_mapserver_log">
+                <textarea id="layer_mapserver_log_textarea" readonly>{{aLayerTestTabs.mapserver_log.file_content}}</textarea>
+            </div>
+            <div role="tabpanel" class="tab-pane" id="layer_map_file">
+                <textarea id="layer_map_file_textarea"></textarea>
+            </div>
+        </div>
+    </div>
+</div>
\ No newline at end of file
diff --git a/vmap/client/modules/vm4ms/template/mapServerFontsTpl.html b/vmap/client/modules/vm4ms/template/mapServerFontsTpl.html
new file mode 100755
index 0000000000000000000000000000000000000000..da5762ab2ae42f4285d24c61ad0fb79d75f1edeb
--- /dev/null
+++ b/vmap/client/modules/vm4ms/template/mapServerFontsTpl.html
@@ -0,0 +1,5 @@
+<div class="col-xs-12">
+    <ul class="list-group">
+        <li ng-repeat="oFont in oMapServerFonts track by $index" class="list-group-item"><span>{{oFont.name}}</span>&nbsp;<span>({{oFont.filename}})</span></li>
+    </ul>
+</div>
\ No newline at end of file
diff --git a/vmap/client/modules/vm4ms/template/mapServerSymbolsTpl.html b/vmap/client/modules/vm4ms/template/mapServerSymbolsTpl.html
new file mode 100755
index 0000000000000000000000000000000000000000..323bbfa4be7319764ea8dd269788f61af55b4b1f
--- /dev/null
+++ b/vmap/client/modules/vm4ms/template/mapServerSymbolsTpl.html
@@ -0,0 +1,18 @@
+<div data-app-map-server-symbols="" class="col-xs-12">
+    <div ng-repeat="oSymbol in oMapServerSymbols track by $index" data-app-map-server-symbols-collapse="" class="panel-group" id="accordion" role="tablist" aria-multiselectable="true">
+        <div class="panel panel-default">
+            <div class="panel-heading" role="tab" id="heading_symbol_{{oSymbol.id}}">
+                <h4 class="panel-title">
+                    <a class="collapsed" role="button" data-toggle="collapse" data-parent="#accordion" href="#collapse_symbol_{{oSymbol.id}}" aria-expanded="false" aria-controls="collapse_symbol_{{oSymbol.id}}">{{oSymbol.name}}</a>
+                </h4>
+            </div>
+            <div id="collapse_symbol_{{oSymbol.id}}" class="panel-collapse collapse in" role="tabpanel" aria-labelledby="heading_symbol_{{oSymbol.id}}">
+                <div class="panel-body">
+                    <ul>
+                        <li ng-repeat="sDefinitionLine in oSymbol.definition track by $index" ng-bind-html="trustAsHtml(sDefinitionLine)"></li>
+                    </ul>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
\ No newline at end of file
diff --git a/vmap/client/modules/vm4ms/template/wmsServiceTestsTpl.html b/vmap/client/modules/vm4ms/template/wmsServiceTestsTpl.html
new file mode 100755
index 0000000000000000000000000000000000000000..42f75c7c9ac94876a33a5a19111484580be069b2
--- /dev/null
+++ b/vmap/client/modules/vm4ms/template/wmsServiceTestsTpl.html
@@ -0,0 +1,109 @@
+<div class="row wms-service-tests">
+    <div data-app-wms-service-tests="" class="col-xs-12">
+        <!-- Menu -->
+        <ul class="nav nav-tabs" role="tablist">
+            <li role="presentation" class="active">
+                <a href="#wms_service_tests_get_capabilities" aria-controls="wms_service_tests_get_capabilities" role="tab" data-toggle="tab" ng-click="showWmsServiceGetCapabilities()">{{ 'TAB_TITLE_GETCAPABILITIES_VM4MS_WMS_SERVICE_TESTS' | translate }}
+                    <button type="button" class="btn btn-primary btn-refresh-tab" aria-label="Left Align" ng-click="showWmsServiceGetCapabilities(true)">
+                        <span class="glyphicon glyphicon-refresh" aria-hidden="true"></span>
+                    </button>
+                </a>
+            </li>
+            <li role="presentation">
+                <a href="#wms_service_tests_wms_service_mapserver" aria-controls="wms_service_tests_wms_service_mapserver" role="tab" data-toggle="tab" ng-click="testWmsServiceWithMapServer()">{{ 'TAB_TITLE_TEST_WMS_SERVICE_MAP_SERVER_VM4MS_WMS_SERVICE_TESTS' | translate }}
+                    <button type="button" class="btn btn-primary btn-refresh-tab" aria-label="Left Align" ng-click="testWmsServiceWithMapServer(true)">
+                        <span class="glyphicon glyphicon-refresh" aria-hidden="true"></span>
+                    </button>
+                </a>
+            </li>
+            <li role="presentation">
+                <a href="#wms_service_tests_wms_service_ol" aria-controls="wms_service_tests_wms_service_ol" role="tab" data-toggle="tab" ng-click="testWmsServiceWithOpenLayers()">{{ 'TAB_TITLE_TEST_WMS_SERVICE_OL3_VM4MS_WMS_SERVICE_TESTS' | translate }}
+                    <button type="button" class="btn btn-primary btn-refresh-tab" aria-label="Left Align" ng-click="testWmsServiceWithOpenLayers(true)">
+                        <span class="glyphicon glyphicon-refresh" aria-hidden="true"></span>
+                    </button>
+                </a>
+            </li>
+            <li role="presentation">
+                <a href="#wms_service_tests_wms_service_log" aria-controls="wms_service_tests_wms_service_log" role="tab" data-toggle="tab" ng-click="loadWmsServiceMapServerLog()">{{ 'TAB_TITLE_MAPSERVER_LOG_VM4MS_WMS_SERVICE_TESTS' | translate }}
+                    <button type="button" class="btn btn-primary btn-refresh-tab" aria-label="Left Align" ng-click="loadWmsServiceMapServerLog(true)">
+                        <span class="glyphicon glyphicon-refresh" aria-hidden="true"></span>
+                    </button>
+                </a>
+            </li>
+            <li role="presentation">
+                <a href="#wms_service_tests_wms_service_map_file" aria-controls="wms_service_tests_wms_service_map_file" role="tab" data-toggle="tab" ng-click="loadWmsServiceMapFile()">{{ 'TAB_TITLE_MAP_FILE_VM4MS_WMS_SERVICE_TESTS' | translate }}
+                    <button type="button" class="btn btn-primary btn-refresh-tab" aria-label="Left Align" ng-click="loadWmsServiceMapFile(true)">
+                        <span class="glyphicon glyphicon-refresh" aria-hidden="true"></span>
+                    </button>
+                </a>
+            </li>
+        </ul>
+        <!-- Onglets -->
+        <div class="tab-content">
+            <div role="tabpanel" class="tab-pane active" id="wms_service_tests_get_capabilities">
+                <textarea id="wms_service_tests_get_capabilities_textarea"></textarea>
+            </div>
+            <div role="tabpanel" class="tab-pane" id="wms_service_tests_wms_service_mapserver">
+                <iframe src="" id="wms_service_tests_wms_service_ms_iframe"></iframe>
+            </div>
+            <div role="tabpanel" class="tab-pane" id="wms_service_tests_wms_service_ol">
+                <div id="wms_service_tests_wms_service_ol_map"></div>
+            </div>
+            <div role="tabpanel" class="tab-pane wms_service-mapserver-log" id="wms_service_tests_wms_service_log">
+                <textarea id="wms_service_tests_wms_service_log_textarea" readonly>{{aWmsServiceTestTabs.mapserver_log.file_content}}</textarea>
+            </div>
+            <div role="tabpanel" class="tab-pane wms_service-mapserver-map_file" id="wms_service_tests_wms_service_map_file">
+                <textarea id="wms_service_tests_wms_service_map_file_textarea"></textarea>
+            </div>
+        </div>
+        <!-- Modale de sélection de couches -->
+        <div class="modal fade" id="wms_service_tests_layer_select_modal" role="dialog">
+            <div class="modal-dialog">
+                <div class="modal-content">
+                    <div class="modal-header">
+                        <button type="button" class="close" data-dismiss="modal">&times;</button>
+                        <h4 class="modal-title">{{ 'TAB_TITLE_MAPSERVER_LAYERS_VM4MS_WMS_SERVICE_TESTS' | translate }}</h4>
+                    </div>
+                    <div class="modal-body">                
+                        <!-- Checkbox visible -->
+                        <div class="checkbox checkbox-info text-right">
+                            <input id="wms_service_tests_all_layers_checkbox" 
+                                   type="checkbox" 
+                                   style="cursor:pointer; position: absolute" 
+                                   title="Definit si la couche est visible"
+                                   ng-checked="aMSTestLayers.length === oGetCapabilities.json.Capability.Layer.Layer.length" 
+                                   ng-click="aMSTestLayers.length === oGetCapabilities.json.Capability.Layer.Layer.length ? aMSTestLayers.length = 0 : testWmsServiceSelectAllLayers()">
+                            <label for="wms_service_tests_all_layers_checkbox" style="cursor:pointer" title=""></label>
+                        </div> 
+                        <ul class="form-map-layertree-ul">
+                            <li ng-repeat="oLayer in oGetCapabilities.json.Capability.Layer.Layer | orderBy: 'Title'" class="margin-3">
+                                <div class="list-group-item auto-height">
+                                    <span class="font-11 layer-name layer-name-tree" ng-attr-title="{{oLayer.Title}}">{{oLayer.Title}}</span>                     
+                                    <!-- Checkbox visible -->
+                                    <div class="checkbox checkbox-info inline-checkbox">
+                                        <input id="{{oLayer.Name}}_wms_service_tests_layer_checkbox" 
+                                               type="checkbox" 
+                                               style="cursor:pointer; position: absolute" 
+                                               title="Definit si la couche est visible"
+                                               ng-checked="aMSTestLayers.indexOf(oLayer.Name) !== -1" 
+                                               ng-click="aMSTestLayers.indexOf(oLayer.Name) === -1 ? aMSTestLayers.push(oLayer.Name) : aMSTestLayers.splice(aMSTestLayers.indexOf(oLayer.Name), 1)">
+                                        <label for="{{oLayer.Name}}_wms_service_tests_layer_checkbox" style="cursor:pointer" title="Definit si la couche est visible"></label>
+                                    </div> 
+                                </div>
+                            </li>
+                        </ul>
+                    </div>
+                    <div class="modal-footer">
+                        <!--<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>-->
+                        <button type="button" class="btn btn-primary" ng-click="testWmsServiceSelectedLayersWithMapServer(aMSTestLayers)">Ok</button>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+<div class="row wms-service-tests-connection-form">
+    <div data-app-wms-service-tests-connection-form="" class="col-xs-12">
+    </div>
+</div>
+