Skip to content

Commit

Permalink
[IMP] web: add new "field" field widget
Browse files Browse the repository at this point in the history
Allow to select a field chain associated to a given model in views.

This is designed to replace the use of char fields where needed,
this commit only does that for the "related" field of the
"ir.model.field" view.
  • Loading branch information
qsm-odoo committed Oct 18, 2017
1 parent d8b8c86 commit 5a77032
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 3 deletions.
125 changes: 125 additions & 0 deletions addons/web/static/src/js/fields/basic_fields.js
Expand Up @@ -17,6 +17,7 @@ var Domain = require('web.Domain');
var DomainSelector = require('web.DomainSelector');
var DomainSelectorDialog = require('web.DomainSelectorDialog');
var framework = require('web.framework');
var ModelFieldSelector = require('web.ModelFieldSelector');
var session = require('web.session');
var utils = require('web.utils');
var view_dialogs = require('web.view_dialogs');
Expand Down Expand Up @@ -2339,6 +2340,129 @@ var FieldDomain = AbstractField.extend({
},
});

/**
* The "Field" field allows the user to construct a field chain for a specific
* model (e.g. user_id.partner_id.name).
*/
var FieldModelField = AbstractField.extend({
resetOnAnyFieldChange: true,
supportedFieldTypes: ['char'],
custom_events: {
field_chain_changed: '_onFieldChainChange',
},

/**
* @constructor
*/
init: function () {
this._super.apply(this, arguments);

this.fsFilters = this.nodeOptions.fs_filters || {};
this._setModel();
},

//--------------------------------------------------------------------------
// Public
//--------------------------------------------------------------------------

/**
* The field selector internal widget can check if the chain can be used
* with the associated model.
*
* @override
* @returns {boolean}
*/
isValid: function () {
return this._super.apply(this, arguments)
&& this.fieldSelector
&& this.fieldSelector.isValid();
},

//--------------------------------------------------------------------------
// Private
//--------------------------------------------------------------------------

/**
* Creates the internal field selector widget if not already created (or if
* it was destroyed). Simply changes its value otherwise.
*
* @private
* @override
* @returns {Deferred}
*/
_render: function () {
if (!this._modelName) {
return;
}

var chain = this.value ? this.value.split('.') : [];

if (!this.fieldSelector) {
this.fieldSelector = new ModelFieldSelector(this, this._modelName, chain, {
readonly: this.mode === 'readonly',
fs_filters: this.fsFilters,
debugMode: session.debug,
});
return this.fieldSelector.appendTo(this.$el);
}

return this.fieldSelector.setChain(chain);
},
/**
* Checks if the model has changed. The field is set as a
* 'resetOnAnyFieldChange' field so that it can detect if the model field
* it is associated to changes.
*
* @private
* @override
*/
_reset: function () {
this._super.apply(this, arguments);
this._setModel();
},
/**
* Checks the model the field must use. It is given by the 'model' node
* options. It is either the name of a model or the name of a field in the
* view which has the model name as value.
*
* Note that if the model name changes, the internal field selector is
* destroyed by this function. So a rerender might be needed after this
* function is called.
*
* @private
*/
_setModel: function () {
var oldModelName = this._modelName;

// Set model name (either the value of another field or an option)
this._modelName = this.nodeOptions.model;
if (this._modelName in this.recordData) {
this._modelName = this.recordData[this._modelName];
}

// Destroy the field selector if the model name has changed
if (this.fieldSelector && this._modelName !== oldModelName) {
this.fieldSelector.destroy();
delete this.fieldSelector;
}
},

//--------------------------------------------------------------------------
// Handlers
//--------------------------------------------------------------------------

/**
* Called when the internal field selector widget notifies its changes.
*
* @private
* @param {OdooEvent} ev
*/
_onFieldChainChange: function (ev) {
ev.stopPropagation();
this._setValue(ev.data.chain.join('.'));
},
});

/**
* This widget is intended to be used on Text fields. It will provide Ace Editor
* for editing XML and Python.
Expand Down Expand Up @@ -2502,6 +2626,7 @@ return {
FieldDate: FieldDate,
FieldDateTime: FieldDateTime,
FieldDomain: FieldDomain,
FieldModelField: FieldModelField,
FieldFloat: FieldFloat,
FieldFloatTime: FieldFloatTime,
FieldInteger: FieldInteger,
Expand Down
3 changes: 2 additions & 1 deletion addons/web/static/src/js/fields/field_registry.js
Expand Up @@ -6,7 +6,7 @@ var Registry = require('web.Registry');
return new Registry();
});

odoo.define('web._field_registry', function(require) {
odoo.define('web._field_registry', function (require) {
"use strict";

var AbstractField = require('web.AbstractField');
Expand All @@ -26,6 +26,7 @@ registry
.add('datetime', basic_fields.FieldDateTime)
.add('domain', basic_fields.FieldDomain)
.add('text', basic_fields.FieldText)
.add('field', basic_fields.FieldModelField)
.add('float', basic_fields.FieldFloat)
.add('char', basic_fields.FieldChar)
.add('link_button', basic_fields.LinkButton)
Expand Down
1 change: 1 addition & 0 deletions addons/web/static/src/less/model_field_selector.less
Expand Up @@ -8,6 +8,7 @@
.o-align-items(center);
height: 100%;
min-height: 20px; // needed when there is no value in it and used standalone

&:active, &:focus, &:active:focus {
outline: none;
}
Expand Down
5 changes: 3 additions & 2 deletions odoo/addons/base/ir/ir_model_view.xml
Expand Up @@ -225,6 +225,7 @@
<field name="name"/>
<field name="field_description"/>
<field name="model_id" attrs="{'readonly': [('state','!=', 'manual')]}"/>
<field name="model" invisible="1"/>
</group>
<group>
<field name="ttype"/>
Expand Down Expand Up @@ -278,7 +279,7 @@
</group>
</group>
<group string="Advanced Properties" groups="base.group_no_one">
<field name="related"/>
<field name="related" widget="field" options="{'model': 'model'}"/>
<field name="depends" attrs="{'required': [('compute', '!=', False)] }"/>
<field name="compute" widget="ace" options="{'mode': 'python'}"/>
</group>
Expand Down Expand Up @@ -539,7 +540,7 @@
<field name="perm_create"/>
<field name="perm_unlink"/>
</group>
</sheet>
</sheet>
</form>
</field>
</record>
Expand Down

0 comments on commit 5a77032

Please sign in to comment.