diff --git a/languages/fr-fr.py b/languages/fr-fr.py
index c7f28d0ea809582f5096ce6ad25d379360d53501..9cf0428796bbec89e88520a06d426bbd613457c2 100644
--- a/languages/fr-fr.py
+++ b/languages/fr-fr.py
@@ -21,6 +21,7 @@
 'Dates': 'Dates',
 'Definition': 'Définition',
 'dev': 'dev',
+'Dictionary': 'Dictionary',
 'Doi': 'Doi',
 'domain': 'domaine',
 'E Print': 'E Print',
@@ -51,6 +52,7 @@
 'Json': 'Json',
 'Last Page': 'Dernière Page',
 'List': 'List',
+'List String': 'List String',
 'Max Records': 'Max Records',
 'My Axes': 'My Axes',
 'My Axis': 'My Axis',
@@ -60,6 +62,7 @@
 'My Int': 'My Int',
 'My List': 'My List',
 'My String': 'My String',
+'new_fields': 'new_fields',
 'Pages': 'Pages',
 'plugin not install': 'plugin not install',
 'Project': 'Projet',
diff --git a/models/db_core.py b/models/db_core.py
index 7f9bbfb430279428ef98c7159072cdcecfa19c97..c05efceaf07d22f1d1e9b9db1906962ac17bb7f8 100644
--- a/models/db_core.py
+++ b/models/db_core.py
@@ -89,15 +89,6 @@ db.define_table("teams",
 
 db.teams.team.filter_in = dbui.CLEAN_SPACES
 
-db.define_table("dev",
-    Field("string", "string"),
-    Field("list", "list:string"),
-    Field("json", "json"),
-    migrate="dev.table")
-
-# NOTE: if we remove the json validator its seem to work ?
-db.dev.json.requires = None
-
 #-------------------------------------------------------------------------------
 #
 # Publications table
@@ -163,3 +154,21 @@ IS_IN_DB(db, 'reports.id', 'reports.type')
 
 db.publications.id_teams.requires = \
 IS_IN_DB(db, 'teams.id', 'teams.team')
+
+
+#-------------------------------------------------------------------------------
+#
+# new_fields
+# table to play with list and disctionary (json) fields
+#
+#-------------------------------------------------------------------------------
+
+db.define_table("new_fields",
+    Field("string", "string"),
+    Field("list_string", "list:string"),
+    Field("dictionary", "json"),
+    migrate="new_fields.table")
+
+# NOTE: if we remove the json validator its seem to work ?
+db.new_fields.dictionary.requires = None
+
diff --git a/models/widgets_fields.py b/models/widgets_fields.py
index 9ac819919123d0e965178562e73bde5adf6fbd02..4bbb923db46068bceb2717f626a510d6572ce58a 100644
--- a/models/widgets_fields.py
+++ b/models/widgets_fields.py
@@ -10,6 +10,16 @@ fieldsModifier.configure_field('year_start', flex=1)
 fieldsModifier.configure_field('year_end', flex=1)
 fieldsModifier.merge_fields('year_start', 'year_end', fieldLabel=T('Year'))
 
+#
+# new_fields
+#
+fieldsModifier = dbui.FieldsModifier('new_fields')
+fieldsModifier.configure_field('dictionary', dictCfg={"string": "test",
+                                                      "boolean": False,
+                                                      "integer": 0,
+                                                      "float": 0.01,
+                                                      "date": "not implemented"})
+
 #
 # publications
 #
@@ -27,9 +37,3 @@ fieldsModifier.merge_fields('conference_start',
                             'conference_end',
                             fieldLabel=T('Dates'), 
                             defaults={'flex': 1})
-
-#
-# dev
-#
-fieldsModifier = dbui.FieldsModifier('dev')
-fieldsModifier.configure_field('json', dictCfg={"foo": "test", "faa": False, "fii": 0})
diff --git a/models/widgets_viewport.py b/models/widgets_viewport.py
index 2a84acb84188f2797f9904e1259fc5bb5e76a9cf..fa00f87c68f7a32e0029a79614fa283048273211 100644
--- a/models/widgets_viewport.py
+++ b/models/widgets_viewport.py
@@ -55,4 +55,5 @@ viewportModifier.append_plugins('pViewportLogin')
 viewportModifier.configure(logged=True)
 viewportModifier.add_node(helpNode, casNode, formNode, gridNode, reportNode)
 
-viewportModifier.default_node(T('Tables'), T('publications'))
+# viewportModifier.default_node(T('Tables'), T('publications'))
+viewportModifier.default_node(T('Tables'), 'new_fields')
diff --git a/static/plugin_dbui/CHANGELOG b/static/plugin_dbui/CHANGELOG
index ed716781fcf595fff4f7369d870caf1ba7470f28..bd5d69bae9b07451f795af2b20958523f96c056e 100644
--- a/static/plugin_dbui/CHANGELOG
+++ b/static/plugin_dbui/CHANGELOG
@@ -1,13 +1,15 @@
 --------------------------------- CHANGE LOG ----------------------------------
 
 HEAD
+  - New widget Ext.Form.DictField
 
-0.4.14.0 (Sep 2013)
+0.4.14.1 (Sep 2013)
   - The viewport can open a tab at startup.
   - Automatic loggout when the page is refreshed and closed.
   - In the App.GridPanel a new record is inserted after the selected one.
   - None node can be added in the ViewportModifier.
   - Redesign the App.ViewportLogin plugin.
+  - Fix a bug in the converter to_gridfilter related to LinkedCombox.
 
 0.4.13.2 (Jul 2013)
   - Table callback _before_delete, _before_insert and  _before_update
diff --git a/static/plugin_dbui/locale/dbui-lang-fr.js b/static/plugin_dbui/locale/dbui-lang-fr.js
index 47873237df489b1f2d4c9363e64a3cd4b5b8e3c5..d56b8a1022e371ea58fc9ab6adba5ae488a3dcb0 100644
--- a/static/plugin_dbui/locale/dbui-lang-fr.js
+++ b/static/plugin_dbui/locale/dbui-lang-fr.js
@@ -10,6 +10,20 @@ if (App.BasePanelWithSelector) {
     });
 }
 
+if (App.form.DictField) {
+    Ext.apply(App.form.DictField.prototype, {
+        textAdd: 'Ajouter',
+        textAddTitle: 'Entrer une clé ...',
+        textAddMsg: 'Entrez le nom de la clé :',
+
+        textDestroy: 'Détruire',
+        textDestroytitle: 'Détruire une clé ...',
+        textDestroyMsg: 'Voulez-vous vraiment détruire la clé :',
+        textErrorTitle: 'Erreur ...',
+        textErrorMsg: 'Cette clé existe !'
+    });
+}
+
 if (App.form.FormPanel) {
     Ext.apply(App.form.FormPanel.prototype, {
         textCreate      : 'Créer',
diff --git a/static/plugin_dbui/src/base.js b/static/plugin_dbui/src/base.js
index 491bef6e9be717b2318fcd4cc21b84e91514065d..ab9e51faf2b9708a9f5b6f6d5ed06cbc59bac90b 100644
--- a/static/plugin_dbui/src/base.js
+++ b/static/plugin_dbui/src/base.js
@@ -20,7 +20,7 @@ Ext.namespace('App');
 /**
  * @param {String} App.version version of the library
  */
-App.version = '0.4.14.0';
+App.version = '0.4.14.1';
 
 /**
  * Helper function mimicking the encode_field function running on the server
diff --git a/static/plugin_dbui/src/dictfield.js b/static/plugin_dbui/src/dictfield.js
index 4a02b1a28be1502061f344692a67822095988662..c2e31823357b212b4f19ef2701ad03596229ecab 100644
--- a/static/plugin_dbui/src/dictfield.js
+++ b/static/plugin_dbui/src/dictfield.js
@@ -1,8 +1,15 @@
 /**
- * The DictField is an Ext.grid.PropertyGrid with which is ran as a form.Field.
+ * The DictField is an Ext.grid.PropertyGrid which is associated
+ * to a JSON field.
  *
- * NOTE: see Ect.form.SliderField a good example to understand
- * how to build a custom field.
+ * The JSON object is a dictionary. It can only contains boolean,
+ * date, float and string objects.
+ *
+ * The default structure of the dictionary can be defined via
+ * the property dictCfg. It is possible to add / delete key value pairs.
+ *
+ * NOTE: The Ext.form.SliderField is a good example to understand
+ * how to build the custom field.
  *
  * The type of this component is xdictfield.
  *
@@ -13,8 +20,8 @@
 Ext.namespace('App.form');
 
 /**
- * Extend the predefined renders of the Ext.grid.column by adding jsoncolumn.
- * It render properly json object in the grid and well adapted for a DictField.
+ * Extend the default type for Ext.grid.column in order to render JSON object.
+ * The new type can be access using xtype = jsoncolumn in the column mdel.
  *
  */
 Ext.grid.JsonColumn = Ext.extend(Ext.grid.Column, {
@@ -37,15 +44,42 @@ Ext.grid.Column.types.jsoncolumn = Ext.grid.JsonColumn;
 App.form.DictField = Ext.extend(Ext.form.Field, {
 
     /**
-     * default configuration of the dictionary
+     * @cfg {object} dictCfg default configuration for the dictionary
+     * Example:
+     * {
+     *   "(name)": "My Object",
+     *   "Created": new Date(Date.parse('10/15/2006')),
+     *   "Available": false,
+     *   "Version": .01,
+     *   "Description": "A test object"
+     * }
      */
     dictCfg: {},
 
+    /**
+     * @cfg {boolean} modifyKeys Dictionary keys can be added or deleted.
+     * By default false.
+     */
+    modifyKeys: false,
+
     /**
      * private attributes
      */
     grid: null,
-    store: null,
+    menu: null,
+    rowIndex: undefined,
+
+    /**
+     * private attributes for internationalization
+     */
+    textAdd: 'Add',
+    textAddTitle: 'Enter key ...',
+    textAddMsg: 'Please enter the key name:',
+    textDestroy: 'Delete',
+    textDestroytitle: 'Delete key ...',
+    textDestroyMsg: 'Are you sure to destroy the key:',
+    textErrorTitle: 'Error ...',
+    textErrorMsg: 'The key already exists!',
 
     /**
      * private method requests by the component model of ExtJS
@@ -54,7 +88,7 @@ App.form.DictField = Ext.extend(Ext.form.Field, {
 
         "use strict";
 
-        // create the property grid
+        // property grid
         this.grid = new Ext.grid.PropertyGrid({
             autoHeight: true,
             hideHeaders: true,
@@ -65,8 +99,28 @@ App.form.DictField = Ext.extend(Ext.form.Field, {
             }
         });
 
-        // inhibit the contextmenu in the PropertyGrid
-        this.grid.on('contextmenu', function (e) {e.stopEvent(); });
+        // context menu to modify the keys
+        if (this.modifyKeys) {
+            this.menu = new Ext.menu.Menu();
+
+            this.menu.add({
+                text: this.textAdd,
+                iconCls: 'xaction-create',
+                handler: this.onAddRow,
+                scope: this
+            }, '-', {
+                text: this.textDestroy,
+                iconCls: 'xaction-destroy',
+                handler: this.onDeleteRow,
+                scope: this
+            });
+
+            this.grid.on('rowcontextmenu', this.onRowContextMenu, this);
+
+        // inhibit context menu
+        } else {
+            this.grid.on('contextmenu', this.onContextMenu, this);
+        }
 
         // instantiate the underlying class
         App.form.DictField.superclass.initComponent.call(this);
@@ -79,6 +133,15 @@ App.form.DictField = Ext.extend(Ext.form.Field, {
 
         "use strict";
 
+        if (this.modifyKeys) {
+            this.grid.un('rowcontextmenu', this.onRowContextMenu, this);
+        } else {
+            this.grid.un('contextmenu', this.onContextMenu, this);
+        }
+
+        Ext.destroyMembers(this, 'grid');
+        Ext.destroyMembers(this, 'menu');
+
         App.form.DictField.superclass.beforeDestroy.call(this);
     },
 
@@ -92,8 +155,66 @@ App.form.DictField = Ext.extend(Ext.form.Field, {
     },
 
     /**
-     * private
-     * supersede the base class method to render the grid
+     * private handler to add a key
+     */
+    onAddRow: function () {
+
+        "use strict";
+
+        var errorTitle = this.textErrorTitle,
+            errorMsg = this.textErrorMsg,
+            grid = this.grid;
+
+        // prompt the user to get the key name
+        Ext.Msg.prompt(this.textAddTitle, this.textAddMsg, function (btn, text) {
+
+            if (btn === 'ok') {
+
+                // check that the key is unique
+                if (grid.getSource().hasOwnProperty(text)) {
+                    Ext.Msg.alert(errorTitle, errorMsg);
+                    return;
+                }
+                // add the new key
+                grid.setProperty(text, null, true);
+            }
+        });
+    },
+
+    /**
+     * Private handler to inhibit context menu
+     * @param {Ext.EventObject} event
+     */
+    onContextMenu: function (event) {
+
+        "use strict";
+        event.stopEvent();
+    },
+
+    /**
+     * private handler to delete a key
+     */
+    onDeleteRow: function () {
+
+        "use strict";
+
+        var grid = this.grid,
+            msg,
+            prop,
+            record = this.grid.getStore().getAt(this.rowIndex);
+
+        prop = record.get("name");
+        msg = this.textDestroyMsg + ' ' + prop;
+
+        Ext.Msg.confirm(this.textDestroyTitle, msg, function (btn) {
+            if (btn === 'yes') {
+                grid.removeProperty(prop);
+            }
+        });
+    },
+
+    /**
+     * private hanlder to render the grid super seeding he base class method
      *
      * @param {Ext.Element} ct The container to render to.
      * @param {Object} position The position in the container to render to.
@@ -117,6 +238,21 @@ App.form.DictField = Ext.extend(Ext.form.Field, {
         this.grid.render(this.wrap);
     },
 
+    /**
+     * private handler to handle the row context menu
+     * @param {Ext.grid.PropertyGrid} grid
+     * @param {Number} rowIndex
+     * @param {Ext.EventObject} event
+     */
+    onRowContextMenu: function (grid, rowIndex, event) {
+
+        "use strict";
+
+        event.stopEvent();
+        this.rowIndex = rowIndex;
+        this.menu.showAt(event.getXY());
+    },
+
     /**
      * Set the value for this field
      * @param {Object} value
@@ -125,7 +261,7 @@ App.form.DictField = Ext.extend(Ext.form.Field, {
 
         "use strict";
 
-        var source  = Ext.apply({}, value || this.dictCfg);
+        var source  = Ext.apply({}, value, this.dictCfg);
         this.grid.setSource(source);
 
         return App.form.DictField.superclass.setValue.call(this, source);