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);