'auto_install': True,
'post_load': 'wsgi_postload',
'js' : [
++ "static/src/fixbind.js",
"static/lib/datejs/globalization/en-US.js",
"static/lib/datejs/core.js",
"static/lib/datejs/parser.js",
"static/lib/spinjs/spin.js",
"static/lib/jquery.autosize/jquery.autosize.js",
"static/lib/jquery.blockUI/jquery.blockUI.js",
+ "static/lib/jquery.placeholder/jquery.placeholder.js",
"static/lib/jquery.ui/js/jquery-ui-1.9.1.custom.js",
"static/lib/jquery.ui.timepicker/js/jquery-ui-timepicker-addon.js",
+ "static/lib/jquery.ui.timepicker/js/jquery-ui-sliderAccess.js",
"static/lib/jquery.ui.notify/js/jquery.notify.js",
"static/lib/jquery.deferred-queue/jquery.deferred-queue.js",
"static/lib/jquery.scrollTo/jquery.scrollTo-min.js",
"static/test/class.js",
"static/test/registry.js",
"static/test/form.js",
++ "static/test/data.js",
"static/test/list-utils.js",
"static/test/formats.js",
"static/test/rpc.js",
content, checksum = concat_files((f[0] for f in files), reader)
++ # move up all @import and @charset rules to the top
++ matches = []
++ def push(matchobj):
++ matches.append(matchobj.group(0))
++ return ''
++
++ content = re.sub(re.compile("(@charset.+;$)", re.M), push, content)
++ content = re.sub(re.compile("(@import.+;$)", re.M), push, content)
++
++ matches.append(content)
++ content = '\n'.join(matches)
++
return make_conditional(
req, req.make_response(content, [('Content-Type', 'text/css')]),
last_modified, checksum)
elif dbname is None:
dbname = db_monodb(req)
-- if uid is None:
++ if not uid:
uid = openerp.SUPERUSER_ID
if not dbname:
image_data = self.placeholder(req, 'logo.png')
else:
-- registry = openerp.modules.registry.RegistryManager.get(dbname)
-- with registry.cursor() as cr:
-- user = registry.get('res.users').browse(cr, uid, uid)
-- if user.company_id.logo_web:
-- image_data = user.company_id.logo_web.decode('base64')
-- else:
-- image_data = self.placeholder(req, 'nologo.png')
++ try:
++ # create an empty registry
++ registry = openerp.modules.registry.Registry(dbname.lower())
++ with registry.cursor() as cr:
++ cr.execute("""SELECT c.logo_web
++ FROM res_users u
++ LEFT JOIN res_company c
++ ON c.id = u.company_id
++ WHERE u.id = %s
++ """, (uid,))
++ row = cr.fetchone()
++ if row and row[0]:
++ image_data = str(row[0]).decode('base64')
++ else:
++ image_data = self.placeholder(req, 'nologo.png')
++ except Exception:
++ image_data = self.placeholder(req, 'logo.png')
++
headers = [
('Content-Type', 'image/png'),
('Content-Length', len(image_data)),
else:
return False
--class Export(View):
++class Export(openerpweb.Controller):
_cp_path = "/web/export"
@openerpweb.jsonrequest
(prefix + '/' + k, prefix_string + '/' + v)
for k, v in self.fields_info(req, model, export_fields).iteritems())
-- #noinspection PyPropertyDefinition
++class ExportFormat(object):
@property
def content_type(self):
""" Provides the format's content type """
('Content-Type', self.content_type)],
cookies={'fileToken': int(token)})
--class CSVExport(Export):
++class CSVExport(ExportFormat, http.Controller):
_cp_path = '/web/export/csv'
fmt = {'tag': 'csv', 'label': 'CSV'}
fp.close()
return data
--class ExcelExport(Export):
++class ExcelExport(ExportFormat, http.Controller):
_cp_path = '/web/export/xls'
fmt = {
'tag': 'xls',
fp.close()
return data
--class Reports(View):
++class Reports(openerpweb.Controller):
_cp_path = "/web/report"
POLLING_DELAY = 0.25
TYPES_MAPPING = {
font-size: 1px
letter-spacing: -1px
color: transparent
++ text-shadow: none
font-weight: normal
&:before
font: 21px "mnmliconsRegular"
font-size: 1px
letter-spacing: -1px
color: transparent
++ text-shadow: none
font-weight: normal
&:before
font: $size "entypoRegular"
.oe_form_field_float input
width: 7em
.oe_form_field_date input
-- width: 7.5em
++ width: 100px
.oe_form_field_datetime input
-- width: 11.5em
++ width: 150px
// }}}
// FormView.fields_binary {{{
/* http://www.quirksmode.org/dom/inputfile.html
@include radius(3px)
// }}}
+ .openerp
+ .db_option_table
+ td
+ padding-bottom: 10px !important
+
// Internet Explorer 9+ specifics {{{
.openerp_ie
+ .placeholder
+ color: $tag-border !important
+ font-style: italic !important
++ .oe_form_binary_file
++ width: 80px
.oe_form_field_boolean input
background: #fff
.db_option_table .oe_form_field_selection
--- /dev/null
--- /dev/null
++// Fix old versions of Webkit (such as ones used on iOS < 6 or PhantomJS <= 1.7)
++// which does not have Function.prototype.bind function
++
++// Use moz polyfill:
++// https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/bind#Compatibility
++if (!Function.prototype.bind) {
++ Function.prototype.bind = function (oThis) {
++ if (typeof this !== "function") {
++ // closest thing possible to the ECMAScript 5 internal IsCallable function
++ throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
++ }
++
++ var aArgs = Array.prototype.slice.call(arguments, 1),
++ fToBind = this,
++ fNOP = function () {},
++ fBound = function () {
++ return fToBind.apply(this instanceof fNOP && oThis
++ ? this
++ : oThis,
++ aArgs.concat(Array.prototype.slice.call(arguments)));
++ };
++
++ fNOP.prototype = this.prototype;
++ fBound.prototype = new fNOP();
++
++ return fBound;
++ };
++}
if (handler) {
new (handler)(this, error).display();
return;
-- };
++ }
if (error.data.name === "openerp.addons.web.session SessionExpiredException") {
-- this.show_warning({type: "Session Expired", data: { message: "Your OpenERP session expired. Please refresh the current web page." }});
++ this.show_warning({type: "Session Expired", data: { message: _t("Your OpenERP session expired. Please refresh the current web page.") }});
return;
}
if (error.data.exception_type === "except_osv" || error.data.exception_type === "warning"
'login': 'admin',
'password': form_obj['create_admin_pwd'],
'login_successful': function() {
- self.do_action("reload");
- var action = {
- type: "ir.actions.client",
- tag: 'reload',
- params: {
- url_search : {
- db: form_obj['db_name'],
- },
- }
- };
- self.do_action(action);
++ var url = '/?db=' + form_obj['db_name'];
++ if (self.session.debug) {
++ url += '&debug';
++ }
++ instance.web.redirect(url);
},
},
_push_me: false,
* @returns {jQuery.Deferred<Array<openerp.web.QueryGroup>> | null}
*/
group_by: function (grouping) {
-- if (grouping === undefined) {
-- return null;
++ var ctx = instance.web.pyeval.eval(
++ 'context', this._model.context(this._context));
++
++ // undefined passed in explicitly (!)
++ if (_.isUndefined(grouping)) {
++ grouping = [];
}
if (!(grouping instanceof Array)) {
grouping = _.toArray(arguments);
}
-- if (_.isEmpty(grouping)) { return null; }
++ if (_.isEmpty(grouping) && !ctx['group_by_no_leaf']) {
++ return null;
++ }
var self = this;
--
-- var ctx = instance.web.pyeval.eval(
-- 'context', this._model.context(this._context));
return this._model.call('read_group', {
groupby: grouping,
fields: _.uniq(grouping.concat(this._fields || [])),
domain: this._model.domain(this._filter),
-- context: this._model.context(this._context),
++ context: ctx,
offset: this._offset,
limit: this._limit,
orderby: instance.web.serialize_sort(this._order_by) || false
* Fetches the model's domain, combined with the provided domain if any
*
* @param {Array} [domain] to combine with the model's internal domain
-- * @returns The model's internal domain, or the AND-ed union of the model's internal domain and the provided domain
++ * @returns {instance.web.CompoundDomain} The model's internal domain, or the AND-ed union of the model's internal domain and the provided domain
*/
domain: function (domain) {
if (!domain) { return this._domain; }
* combined with the provided context if any
*
* @param {Object} [context] to combine with the model's internal context
-- * @returns The union of the user's context and the model's internal context, as well as the provided context if any. In that order.
++ * @returns {instance.web.CompoundContext} The union of the user's context and the model's internal context, as well as the provided context if any. In that order.
*/
context: function (context) {
return new instance.web.CompoundContext(
alter_ids: function(n_ids) {
this.ids = n_ids;
},
++ remove_ids: function (ids) {
++ this.alter_ids(_(this.ids).difference(ids));
++ },
/**
* Resequence records.
*
get_domain: function (other_domain) {
this._model.domain(other_domain);
},
++ alter_ids: function (ids) {
++ this._super(ids);
++ if (this.index !== null && this.index >= this.ids.length) {
++ this.index = this.ids.length > 0 ? this.ids.length - 1 : 0;
++ }
++ },
++ remove_ids: function (ids) {
++ var before = this.ids.length;
++ this._super(ids);
++ if (this._length) {
++ this._length -= (before - this.ids.length);
++ }
++ },
unlink: function(ids, callback, error_callback) {
var self = this;
return this._super(ids).done(function(result) {
-- self.ids = _(self.ids).difference(ids);
-- if (self._length) {
-- self._length -= 1;
-- }
-- if (self.index !== null) {
-- self.index = self.index <= self.ids.length - 1 ?
-- self.index : (self.ids.length > 0 ? self.ids.length -1 : 0);
-- }
++ self.remove_ids( ids);
self.trigger("dataset_changed", ids, callback, error_callback);
});
},
size: function () {
-- if (this._length !== undefined) {
++ if (this._length != null) {
return this._length;
}
return this._super();
}
};
++/**
++ * performs a half up rounding with arbitrary precision, correcting for float loss of precision
++ * See the corresponding float_round() in server/tools/float_utils.py for more info
++ * @param {Number} the value to be rounded
++ * @param {Number} a non zero precision parameter. eg: 0.01 rounds to two digits.
++ */
++instance.web.round_precision = function(value, precision){
++ if(!value){
++ return 0;
++ }else if(!precision){
++ throw new Error('round_precision(...): Cannot round value: '+value+' with a precision of zero (or undefined)');
++ }
++ var normalized_value = value / precision;
++ var epsilon_magnitude = Math.log(Math.abs(normalized_value))/Math.log(2);
++ var epsilon = Math.pow(2, epsilon_magnitude - 53);
++ normalized_value += normalized_value >= 0 ? epsilon : -epsilon;
++ var rounded_value = Math.round(normalized_value);
++ return rounded_value * precision;
++};
++
++/**
++ * performs a half up rounding with a fixed amount of decimals, correcting for float loss of precision
++ * See the corresponding float_round() in server/tools/float_utils.py for more info
++ * @param {Number} the value to be rounded
++ * @param {Number} the number of decimals. eg: round_decimals(3.141592,2) -> 3.14
++ */
++instance.web.round_decimals = function(value, decimals){
++ return instance.web.round_precision(value, Math.pow(10,-decimals));
++};
++
};
e.preventDefault();
break;
}
- }
+ },
+ 'autocompleteopen': function () {
- this.$el.autocomplete('widget').css('z-index', 3);
++ this.$el.autocomplete('widget').css('z-index', 1004);
+ },
},
/**
* @constructs instance.web.SearchView
facet.values.each(function (v) {
var i = _(self.filters).indexOf(v.get('value'));
if (i === -1) { return; }
-- $filters.eq(i).addClass('oe_selected');
++ $filters.filter(function () {
++ return Number($(this).data('index')) === i;
++ }).addClass('oe_selected');
});
},
/**
});
},
toggle_filter: function (e) {
-- this.toggle(this.filters[$(e.target).index()]);
++ this.toggle(this.filters[Number($(e.target).data('index'))]);
},
toggle: function (filter) {
this.view.query.toggle(this.make_facet([this.make_value(filter)]));
}
});
instance.web.search.NumberField = instance.web.search.Field.extend(/** @lends instance.web.search.NumberField# */{
-- value_from: function () {
-- if (!this.$el.val()) {
-- return null;
-- }
-- var val = this.parse(this.$el.val()),
-- check = Number(this.$el.val());
-- if (isNaN(val) || val !== check) {
-- this.$el.addClass('error');
-- throw new instance.web.search.Invalid(
-- this.attrs.name, this.$el.val(), this.error_message);
-- }
-- this.$el.removeClass('error');
-- return val;
-- }
++ complete: function (value) {
++ var val = this.parse(value);
++ if (isNaN(val)) { return $.when(); }
++ var label = _.str.sprintf(
++ _t("Search %(field)s for: %(value)s"), {
++ field: '<em>' + this.attrs.string + '</em>',
++ value: '<strong>' + _.str.escapeHTML(value) + '</strong>'});
++ return $.when([{
++ label: label,
++ facet: {
++ category: this.attrs.string,
++ field: this,
++ values: [{label: value, value: val}]
++ }
++ }]);
++ },
});
/**
* @class
});
QUnit.module(testing.current_module + '.' + name, {_oe: options});
-- body(testing.case);
++ body(testing['case']);
};
-- testing.case = function (name, options, callback) {
++ testing['case'] = function (name, options, callback) {
if (_.isFunction(options)) {
callback = options;
options = {};
this.has_been_loaded.done(function() {
if (self.datarecord.id && confirm(_t("Do you really want to delete this record?"))) {
self.dataset.unlink([self.datarecord.id]).done(function() {
-- self.execute_pager_action('next');
++ if (self.dataset.size()) {
++ self.execute_pager_action('next');
++ } else {
++ self.do_action('history_back');
++ }
def.resolve();
});
} else {
if (save_obj.error)
return $.Deferred().reject();
return $.when.apply($, save_obj.ret);
++ }).done(function() {
++ self.$el.removeClass('oe_form_dirty');
});
},
_process_save: function(save_obj) {
return value;
}
var fields = _.chain(this.fields)
-- .map(function (field, name) {
++ .map(function (field) {
var value = field.get_value();
// ignore fields which are empty, invisible, readonly, o2m
// or m2m
}
return {
-- name: name,
++ name: field.name,
string: field.string,
value: value,
displayed: display(field, value),
.value();
var conditions = _.chain(self.fields)
.filter(function (field) { return field.field.change_default; })
-- .map(function (field, name) {
++ .map(function (field) {
var value = field.get_value();
return {
-- name: name,
++ name: field.name,
string: field.string,
value: value,
displayed: display(field, value),
$(this).children().each(function() {
var $td = $(this),
$child = $td.children(':first');
++ if ($child.attr('cell-class')) {
++ $td.addClass($child.attr('cell-class'));
++ }
switch ($child[0].tagName.toLowerCase()) {
case 'separator':
break;
if (! page.__ic)
return;
page.__ic.on("change:effective_invisible", null, function() {
-- if (!page.__ic.get('effective_invisible')) {
++ if (!page.__ic.get('effective_invisible') && page.autofocus) {
$new_notebook.tabs('select', i);
return;
}
value without triggering a re-rendering.
*/
internal_set_value: function(value_) {
-- var tmp = this.no_render;
++ var tmp = this.no_rerender;
this.no_rerender = true;
this.set({'value': value_});
this.no_rerender = tmp;
return this.get('value') === '' || this._super();
},
focus: function() {
-- this.$('input:first')[0].focus();
++ var input = this.$('input:first')[0];
++ return input ? input.focus() : false;
},
set_dimensions: function (height, width) {
this._super(height, width);
this._super.apply(this, [value_]);
},
focus: function () {
-- this.$('input:first').select();
++ var $input = this.$('input:first');
++ return $input.length ? $input.select() : false;
}
});
changeYear: true,
showWeek: true,
showButtonPanel: true,
- firstDay: Date.CultureInfo.firstDayOfWeek
+ firstDay: Date.CultureInfo.firstDayOfWeek,
+ controlType: value,
+ };
+ },
+ start: function() {
+ var self = this;
+ this.$input = this.$el.find('input.oe_datepicker_master');
+ this.$input_picker = this.$el.find('input.oe_datepicker_container');
+
++ $.datepicker.setDefaults({
++ clearText: _t('Clear'),
++ clearStatus: _t('Erase the current date'),
++ closeText: _t('Done'),
++ closeStatus: _t('Close without change'),
++ prevText: _t('<Prev'),
++ prevStatus: _t('Show the previous month'),
++ nextText: _t('Next>'),
++ nextStatus: _t('Show the next month'),
++ currentText: _t('Today'),
++ currentStatus: _t('Show the current month'),
++ monthNames: Date.CultureInfo.monthNames,
++ monthNamesShort: Date.CultureInfo.abbreviatedMonthNames,
++ monthStatus: _t('Show a different month'),
++ yearStatus: _t('Show a different year'),
++ weekHeader: _t('Wk'),
++ weekStatus: _t('Week of the year'),
++ dayNames: Date.CultureInfo.dayNames,
++ dayNamesShort: Date.CultureInfo.abbreviatedDayNames,
++ dayNamesMin: Date.CultureInfo.shortestDayNames,
++ dayStatus: _t('Set DD as first week day'),
++ dateStatus: _t('Select D, M d'),
++ firstDay: Date.CultureInfo.firstDayOfWeek,
++ initStatus: _t('Select a date'),
++ isRTL: false
+ });
++ $.timepicker.setDefaults({
++ timeOnlyTitle: _t('Choose Time'),
++ timeText: _t('Time'),
++ hourText: _t('Hour'),
++ minuteText: _t('Minute'),
++ secondText: _t('Second'),
++ currentText: _t('Now'),
++ closeText: _t('Done')
++ });
++
+ this.picker(this.config_plugin());
+ // Some clicks in the datepicker dialog are not stopped by the
+ // datepicker and "bubble through", unexpectedly triggering the bus's
+ // click event. Prevent that.
+ this.picker('widget').click(function (e) { e.stopPropagation(); });
+
this.$el.find('img.oe_datepicker_trigger').click(function() {
if (self.get("effective_readonly") || self.picker('widget').is(':visible')) {
self.$input.focus();
return this.get('value') === '' || this._super();
},
focus: function() {
-- if (this.datewidget && this.datewidget.$input) {
-- this.datewidget.$input[0].focus();
-- }
++ var input = this.datewidget && this.datewidget.$input[0];
++ return input ? input.focus() : false;
},
set_dimensions: function (height, width) {
this._super(height, width);
return this.get('value') === '' || this._super();
},
focus: function($el) {
- this.$textarea[0].focus();
- if (!this.get("effective_readonly") && this.$textarea) {
- this.$textarea[0].focus();
- }
++ var input = !this.get("effective_readonly") && this.$textarea && this.$textarea[0];
++ return input ? input.focus() : false;
},
set_dimensions: function (height, width) {
this._super(height, width);
this.$checkbox[0].checked = this.get('value');
},
focus: function() {
-- this.$checkbox[0].focus();
++ var input = this.$checkbox && this.$checkbox[0];
++ return input ? input.focus() : false;
}
});
}
},
focus: function() {
-- this.$('select:first')[0].focus();
++ var input = this.$('select:first')[0];
++ return input ? input.focus() : false;
},
set_dimensions: function (height, width) {
this._super(height, width);
this.$input.keydown(input_changed);
this.$input.change(input_changed);
this.$drop_down.click(function() {
+ self.$input.focus();
if (self.$input.autocomplete("widget").is(":visible")) {
- self.$input.autocomplete("close");
+ self.$input.autocomplete("close");
- self.$input.focus();
} else {
if (self.get("value") && ! self.floating) {
self.$input.autocomplete("search", "");
}
if (! no_recurse) {
var dataset = new instance.web.DataSetStatic(this, this.field.relation, self.build_context());
-- dataset.name_get([self.get("value")]).done(function(data) {
++ this.alive(dataset.name_get([self.get("value")])).done(function(data) {
self.display_value["" + self.get("value")] = data[0][1];
self.render_value(true);
});
return ! this.get("value");
},
focus: function () {
-- if (!this.get('effective_readonly')) {
- this.$input[0].focus();
- }
- this.$input && this.$input[0].focus();
- }
++ var input = !this.get('effective_readonly') && this.$input && this.$input[0];
++ return input ? input.focus() : false;
},
_quick_create: function() {
this.no_ed = true;
this.set({'value': _.uniq(this.get('value').concat([id]))});
},
focus: function () {
-- this.$text[0].focus();
++ var input = this.$text && this.$text[0];
++ return input ? input.focus() : false;
+ },
+ set_dimensions: function (height, width) {
- this._super(height, width);
++ this._super(height, width);
+ this.$("textarea").css({
+ width: width,
+ minHeight: height
+ });
},
});
},
render_value: function() {
var self = this;
- self.get_selection().done(function() {
- var content = QWeb.render("FieldStatus.content", {widget: self});
- self.$el.html(content);
- var colors = JSON.parse((self.node.attrs || {}).statusbar_colors || "{}");
- var color = colors[self.get('value')];
- if (color) {
- self.$("oe_active").css("color", color);
- }
- });
+ var content = QWeb.render("FieldStatus.content", {widget: self});
+ self.$el.html(content);
+ },
+ calc_domain: function() {
+ var d = instance.web.pyeval.eval('domain', this.build_domain());
+ var domain = []; //if there is no domain defined, fetch all the records
-
++
+ if (d.length) {
+ domain = ['|',['id', '=', this.get('value')]].concat(d);
+ }
-
++
+ if (! _.isEqual(domain, this.get("evaluated_selection_domain"))) {
+ this.set("evaluated_selection_domain", domain);
+ }
},
/** Get the selection and render it
* selection: [[identifier, value_to_display], ...]
this.no_leaf = !!context['group_by_no_leaf'];
this.grouped = !!group_by;
-- return this.load_view(context).then(
++ return this.alive(this.load_view(context)).then(
this.proxy('reload_content'));
},
/**
this.record_callbacks = {
'remove': function (event, record) {
-- var $row = self.$current.children(
-- '[data-id=' + record.get('id') + ']');
++ var id = record.get('id');
++ self.dataset.remove_ids([id])
++ var $row = self.$current.children('[data-id=' + id + ']');
var index = $row.data('index');
$row.remove();
},
switch_mode: function (view_type, no_store, options) {
var self = this;
-- return $.when(this._super.apply(this, arguments)).done(function () {
++ return this.alive($.when(this._super.apply(this, arguments))).done(function () {
var controller = self.views[self.active_view].controller;
self.$el.find('.oe_debug_view').html(QWeb.render('ViewManagerDebug', {
view: controller,
<li t-if="section.name == 'files'" class="oe_sidebar_add_attachment">
<t t-call="HiddenInputFile">
<t t-set="fileupload_id" t-value="widget.fileupload_id"/>
-- <t t-set="fileupload_action">/web/binary/upload_attachment</t>
++ <t t-set="fileupload_action" t-translation="off">/web/binary/upload_attachment</t>
<input type="hidden" name="model" t-att-value="widget.dataset and widget.dataset.model"/>
<input type="hidden" name="id" t-att-value="widget.model_id"/>
<input type="hidden" name="session_id" t-att-value="widget.session.session_id"/>
<t t-esc="attrs.string"/>
</button>
<ul t-name="SearchView.filters">
- <li t-foreach="widget.filters" t-as="filter"
- t-att-title="filter.attrs.string ? filter.attrs.help : undefined">
- <li t-foreach="widget.filters" t-as="filter" t-if="filter.visible()"
- t-att-title="filter.attrs.string ? filter.attrs.help : undefined">
++ <li t-foreach="widget.filters" t-as="filter" t-if="!filter.visible || filter.visible()"
++ t-att-title="filter.attrs.string ? filter.attrs.help : undefined"
++ t-att-data-index="filter_index">
<t t-esc="filter.attrs.string or filter.attrs.help or filter.attrs.name or 'Ω'"/>
</li>
</ul>
--- /dev/null
--- /dev/null
++openerp.testing.section('data.model.group_by', {
++ rpc: 'mock',
++ dependencies: ['web.data'],
++}, function (test) {
++ var group_result = [{
++ bar: 3, bar_count: 5, __context: {}, __domain: [['bar', '=', 3]],
++ }, {
++ bar: 5, bar_count: 3, __context: {}, __domain: [['bar', '=', 5]],
++ }, {
++ bar: 8, bar_count: 0, __context: {}, __domain: [['bar', '=', 8]],
++ }];
++ test('basic', {asserts: 7}, function (instance, $fix, mock) {
++ var m = new instance.web.Model('foo');
++ mock('foo:read_group', function (args, kwargs) {
++ deepEqual(kwargs.fields, ['bar'],
++ "should read grouping field");
++ deepEqual(kwargs.groupby, ['bar'],
++ "should have single grouping field");
++ return group_result;
++ });
++ mock('/web/dataset/search_read', function (args) {
++ deepEqual(args.params.domain, [['bar', '=', 3]],
++ "should have domain matching that of group_by result");
++ return {records: [
++ {bar: 3, id: 1},
++ {bar: 3, id: 2},
++ {bar: 3, id: 4},
++ {bar: 3, id: 8},
++ {bar: 3, id: 16}
++ ], length: 5};
++ });
++
++ return m.query().group_by('bar')
++ .then(function (groups) {
++ ok(groups, "should have data");
++ equal(groups.length, 3, "should have three results");
++ var first = groups[0];
++ ok(first.attributes.has_children, "should have children");
++ return first.query().all();
++ }).done(function (first) {
++ equal(first.length, 5, "should have 5 records")
++ });
++ });
++ test('noleaf', {asserts: 5}, function (instance, $fix, mock) {
++ var m = new instance.web.Model('foo', {group_by_no_leaf: true});
++ mock('foo:read_group', function (args, kwargs) {
++ deepEqual(kwargs.fields, ['bar'],
++ "should read grouping field");
++ deepEqual(kwargs.groupby, ['bar'],
++ "should have single grouping field");
++
++ return group_result;
++ });
++ return m.query().group_by('bar')
++ .then(function (groups) {
++ ok(groups, "should have data");
++ equal(groups.length, 3, "should have three results");
++ ok(!groups[0].attributes.has_children,
++ "should not have children because no_leaf");
++ })
++ });
++ test('nogroup', {rpc: false}, function (instance, $f, mock) {
++ var m = new instance.web.Model('foo');
++ strictEqual(m.query().group_by(), null, "should not group");
++ });
++ test('empty.noleaf', {asserts: 1}, function (instance, $f, mock) {
++ var m = new instance.web.Model('foo', {group_by_no_leaf: true});
++ mock('foo:read_group', function (args, kwargs) {
++ return [{__context: [], __domain: []}];
++ });
++ return m.query().group_by().done(function (groups) {
++ strictEqual(groups.length, 1,
++ "should generate a single fake-ish group");
++ });
++ });
++});
ok(!c, "no match should yield no completion");
});
});
+ test("M2O filtered", {asserts: 2}, function (instance, $s, mock) {
+ mock('dummy.model:name_search', function (args, kwargs) {
+ deepEqual(args, [], "should have no positional arguments");
+ deepEqual(kwargs, {
+ name: 'bob',
+ limit: 8,
+ args: [['foo', '=', 'bar']],
+ context: {flag: 1},
+ }, "should use filtering domain");
+ return [[42, "Match"]];
+ });
+ var view = {
+ inputs: [],
+ dataset: {get_context: function () { return {flag: 1}; }}
+ };
+ var f = new instance.web.search.ManyToOneField(
+ {attrs: {string: 'Dummy', domain: '[["foo", "=", "bar"]]'}},
+ {relation: 'dummy.model'}, view);
+ return f.complete("bob");
+ });
++ test('Integer: invalid', {asserts: 1}, function (instance) {
++ var view = {inputs: []};
++ var f = new instance.web.search.IntegerField(
++ {attrs: {string: "Dummy"}}, {}, view);
++ return f.complete("qux")
++ .done(function (completions) {
++ ok(!completions, "non-number => no completion");
++ });
++ });
++ test('Integer: non-zero', {asserts: 5}, function (instance) {
++ var view = {inputs: []};
++ var f = new instance.web.search.IntegerField(
++ {attrs: {string: "Dummy"}}, {}, view);
++ return f.complete("-2")
++ .done(function (completions) {
++ equal(completions.length, 1, "number fields provide 1 completion only");
++ var facet = new instance.web.search.Facet(completions[0].facet);
++ equal(facet.get('category'), f.attrs.string);
++ equal(facet.get('field'), f);
++ var value = facet.values.at(0);
++ equal(value.get('label'), "-2");
++ equal(value.get('value'), -2);
++ });
++ });
++ test('Integer: zero', {asserts: 3}, function (instance) {
++ var view = {inputs: []};
++ var f = new instance.web.search.IntegerField(
++ {attrs: {string: "Dummy"}}, {}, view);
++ return f.complete("0")
++ .done(function (completions) {
++ equal(completions.length, 1, "number fields provide 1 completion only");
++ var facet = new instance.web.search.Facet(completions[0].facet);
++ var value = facet.values.at(0);
++ equal(value.get('label'), "0");
++ equal(value.get('value'), 0);
++ });
++ });
++ test('Float: non-zero', {asserts: 5}, function (instance) {
++ var view = {inputs: []};
++ var f = new instance.web.search.FloatField(
++ {attrs: {string: "Dummy"}}, {}, view);
++ return f.complete("42.37")
++ .done(function (completions) {
++ equal(completions.length, 1, "float fields provide 1 completion only");
++ var facet = new instance.web.search.Facet(completions[0].facet);
++ equal(facet.get('category'), f.attrs.string);
++ equal(facet.get('field'), f);
++ var value = facet.values.at(0);
++ equal(value.get('label'), "42.37");
++ equal(value.get('value'), 42.37);
++ });
++ });
++
});
- openerp.testing.section('search-serialization', {
+ openerp.testing.section('search.serialization', {
dependencies: ['web.search'],
rpc: 'mock',
templates: true
});
// TODO: UI tests?
});
+ openerp.testing.section('search.invisible', {
+ dependencies: ['web.search'],
+ rpc: 'mock',
+ templates: true,
+ }, function (test) {
+ var registerTestField = function (instance, methods) {
+ instance.web.search.fields.add('test', 'instance.testing.TestWidget');
+ instance.testing = {
+ TestWidget: instance.web.search.Field.extend(methods),
+ };
+ };
+ var makeView = function (instance, mock, fields, arch, defaults) {
+ mock('ir.filters:get_filters', function () { return []; });
+ mock('test.model:fields_get', function () { return fields; });
+ mock('test.model:fields_view_get', function () {
+ return { type: 'search', fields: fields, arch: arch };
+ });
+ var ds = new instance.web.DataSet(null, 'test.model');
+ return new instance.web.SearchView(null, ds, false, defaults);
+ };
+ // Invisible fields should not auto-complete
+ test('invisible-field-no-autocomplete', {asserts: 1}, function (instance, $fix, mock) {
+ registerTestField(instance, {
+ complete: function () {
+ return $.when([{label: this.attrs.string}]);
+ },
+ });
+ var view = makeView(instance, mock, {
+ field0: {type: 'test', string: 'Field 0'},
+ field1: {type: 'test', string: 'Field 1'},
+ }, ['<search>',
+ '<field name="field0"/>',
+ '<field name="field1" modifiers="{"invisible": true}"/>',
- '</search>'].join());
++ '</search>'].join(''));
+ return view.appendTo($fix)
+ .then(function () {
+ var done = $.Deferred();
+ view.complete_global_search({term: 'test'}, function (comps) {
+ done.resolve(comps);
+ });
+ return done;
+ }).then(function (completions) {
+ deepEqual(completions, [{label: 'Field 0'}],
+ "should only complete the visible field");
+ });
+ });
+ // Invisible filters should not appear in the drawer
+ test('invisible-filter-no-drawer', {asserts: 4}, function (instance, $fix, mock) {
+ var view = makeView(instance, mock, {}, [
+ '<search>',
+ '<filter string="filter 0"/>',
+ '<filter string="filter 1" modifiers="{"invisible": true}"/>',
- '</search>'].join());
++ '</search>'].join(''));
+ return view.appendTo($fix)
+ .then(function () {
+ var $fs = $fix.find('.oe_searchview_filters ul');
+ strictEqual($fs.children().length,
+ 1,
+ "should only display one filter");
+ strictEqual(_.str.trim($fs.children().text()),
+ "filter 0",
+ "should only display filter 0");
+ var done = $.Deferred();
+ view.complete_global_search({term: 'filter'}, function (comps) {
+ done.resolve();
+ strictEqual(comps.length, 1, "should only complete visible filter");
+ strictEqual(comps[0].label, "Filter on: filter 0",
+ "should complete filter 0");
+ });
+ return done;
+ });
+ });
++ test('invisible-previous-sibling', {asserts: 3}, function (instance, $fix, mock) {
++ var view = makeView(instance, mock, {}, [
++ '<search>',
++ '<filter string="filter 0" context="{"test": 0}"/>',
++ '<filter string="filter 1" modifiers="{"invisible": true}" context="{"test": 1}"/>',
++ '<filter string="filter 2" modifiers="{"invisible": true}" context="{"test": 2}"/>',
++ '<filter string="filter 3" context="{"test": 3}"/>',
++ '</search>'].join(''));
++ return view.appendTo($fix)
++ .done(function () {
++ // Select filter 3
++ $fix.find('.oe_searchview_filters ul li:contains("filter 3")').click();
++ equal(view.query.length, 1, "should have selected a filter");
++ var facet = view.query.at(0);
++ strictEqual(facet.values.at(0).get('label'), "filter 3",
++ "should have correctly labelled the facet");
++ deepEqual(view.build_search_data().contexts, [{test: 3}],
++ "should have built correct context");
++ });
++ });
+ // Invisible filter groups should not appear in the drawer
+ // Group invisibility should be inherited by children
+ test('group-invisibility', {asserts: 6}, function (instance, $fix, mock) {
+ registerTestField(instance, {
+ complete: function () {
+ return $.when([{label: this.attrs.string}]);
+ },
+ });
+ var view = makeView(instance, mock, {
+ field0: {type: 'test', string: 'Field 0'},
+ field1: {type: 'test', string: 'Field 1'},
+ }, [
+ '<search>',
+ '<group string="Visibles">',
+ '<field name="field0"/>',
+ '<filter string="Filter 0"/>',
+ '</group>',
+ '<group string="Invisibles" modifiers="{"invisible": true}">',
+ '<field name="field1"/>',
+ '<filter string="Filter 1"/>',
+ '</group>',
+ '</search>'
+ ].join(''));
+ return view.appendTo($fix)
+ .then(function () {
+ strictEqual($fix.find('.oe_searchview_filters h3').length,
+ 1,
+ "should only display one group");
+ strictEqual($fix.find('.oe_searchview_filters h3').text(),
+ 'w Visibles',
+ "should only display the Visibles group (and its icon char)");
+
+ var $fs = $fix.find('.oe_searchview_filters ul');
+ strictEqual($fs.children().length, 1,
+ "should only have one filter in the drawer");
+ strictEqual(_.str.trim($fs.text()), "Filter 0",
+ "should have filter 0 as sole filter");
+
+ var done = $.Deferred();
+ view.complete_global_search({term: 'filter'}, function (compls) {
+ done.resolve();
+ strictEqual(compls.length, 2,
+ "should have 2 completions");
+ deepEqual(_.pluck(compls, 'label'),
+ ['Field 0', 'Filter on: Filter 0'],
+ "should complete on field 0 and filter 0");
+ });
+ return done;
+ });
+ });
+ // Default on invisible fields should still work, for fields and filters both
+ test('invisible-defaults', {asserts: 1}, function (instance, $fix, mock) {
+ var view = makeView(instance, mock, {
+ field: {type: 'char', string: "Field"},
+ field2: {type: 'char', string: "Field 2"},
+ }, [
+ '<search>',
+ '<field name="field2"/>',
+ '<filter name="filter2" string="Filter"',
+ ' domain="[[\'qwa\', \'=\', 42]]"/>',
+ '<group string="Invisibles" modifiers="{"invisible": true}">',
+ '<field name="field"/>',
+ '<filter name="filter" string="Filter"',
+ ' domain="[[\'whee\', \'=\', \'42\']]"/>',
+ '</group>',
+ '</search>'
+ ].join(''), {field: "foo", filter: true});
+
+ return view.appendTo($fix)
+ .then(function () {
+ deepEqual(view.build_search_data(), {
+ errors: [],
+ groupbys: [],
+ contexts: [],
+ domains: [
+ // Generated from field
+ [['field', 'ilike', 'foo']],
+ // generated from filter
+ "[['whee', '=', '42']]"
+ ],
+ }, "should yield invisible fields selected by defaults");
+ });
+ });
+ });
//To parse Events we have to convert date Format
var res_events = [],
sidebar_items = {};
++ var selection_label = {};
++ if(this.fields[this.color_field].selection) {
++ _(this.fields[this.color_field].selection).each(function(value){
++ selection_label[value[0]] = value[1];
++ });
++ }
for (var e = 0; e < events.length; e++) {
var evt = events[e];
if (!evt[this.date_start]) {
if (this.color_field) {
var filter = evt[this.color_field];
if (filter) {
++ if(this.fields[this.color_field].selection) {
++ filter = selection_label[filter];
++ }
var filter_value = (typeof filter === 'object') ? filter[0] : filter;
if (typeof(fn_filter) === 'function' && !fn_filter(filter_value)) {
continue;
},
get_event_data: function(event_obj) {
var data = {
-- name: event_obj.text
++ name: event_obj.text || scheduler.locale.labels.new_event
};
-- data[this.date_start] = instance.web.datetime_to_str(event_obj.start_date);
++ if (this.fields[this.date_start].type == 'date') {
++ data[this.date_start] = instance.web.date_to_str(event_obj.start_date)
++ }else {
++ data[this.date_start] = instance.web.datetime_to_str(event_obj.start_date)
++ }
if (this.date_stop) {
data[this.date_stop] = instance.web.datetime_to_str(event_obj.end_date);
}
import openerp
--class DiagramView(openerp.addons.web.controllers.main.View):
++class DiagramView(openerp.addons.web.http.Controller):
_cp_path = "/web_diagram/diagram"
@openerp.addons.web.http.jsonrequest
-@charset "utf-8";
.openerp .oe_kanban_view {
background: white;
-- height: inherit;
--}
++ height: inherit; }
+.openerp .oe_kanban_view .oe_kanban_column_higlight {
- background: #eeddf6 !important;
- }
++ background: #eeddf6 !important; }
+ .openerp .oe_kanban_view .oe_view_nocontent {
+ position: relative;
+ z-index: 1;
+ max-width: none;
- height: 100%;
-}
++ height: 100%; }
+ .openerp .oe_kanban_view .oe_view_nocontent .oe_view_nocontent_content {
+ margin-left: 90px;
+ margin-top: 5px;
- max-width: 700px;
-}
++ max-width: 700px; }
+ .openerp .oe_kanban_view .oe_view_nocontent .oe_view_nocontent_bg {
+ background: #eeeeee;
+ opacity: 0.7;
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
- z-index: -1;
-}
++ z-index: -1; }
.openerp .oe_kanban_view.oe_kanban_grouped .oe_kanban_dummy_cell {
background: url(/web/static/src/img/form_sheetbg.png);
-- width: 100%;
--}
++ width: 100%; }
+ .openerp .oe_kanban_view .oe_kanban_group_length {
+ text-align: center;
- display: none;
-}
++ display: none; }
+ .openerp .oe_kanban_view .oe_kanban_group_length .oe_tag {
+ position: relative;
+ top: 8px;
- font-weight: bold;
-}
++ font-weight: bold; }
++.openerp .oe_kanban_view .oe_kanban_header:hover .oe_kanban_group_length {
++ display: none; }
.openerp .oe_kanban_view .ui-sortable-placeholder {
border: 1px solid rgba(0, 0, 0, 0.1);
-- visibility: visible !important;
--}
++ visibility: visible !important; }
.openerp .oe_kanban_view .ui-sortable-helper {
-moz-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.3);
-webkit-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.3);
-ms-transform: rotate(3deg);
-webkit-transition: -webkit-transform 100ms linear;
-moz-transition: -moz-transform 100ms linear;
-- transition: transform 100ms linear;
--}
++ transition: transform 100ms linear; }
.openerp .oe_kanban_view .oe_kanban_left {
-- float: left;
--}
++ float: left; }
.openerp .oe_kanban_view .oe_kanban_right {
-- float: right;
--}
++ float: right; }
.openerp .oe_kanban_view .oe_kanban_clear {
-- clear: both;
--}
++ clear: both; }
.openerp .oe_kanban_view .oe_kanban_content {
-- word-wrap: break-word;
--}
++ word-wrap: break-word; }
.openerp .oe_kanban_view .oe_kanban_content .oe_star_on, .openerp .oe_kanban_view .oe_kanban_content .oe_star_off {
color: #cccccc;
text-shadow: 0 0 2px black;
vertical-align: top;
position: relative;
-- top: -5px;
--}
++ top: -5px; }
.openerp .oe_kanban_view .oe_kanban_content .oe_star_on:hover, .openerp .oe_kanban_view .oe_kanban_content .oe_star_off:hover {
-- text-decoration: none;
--}
++ text-decoration: none; }
.openerp .oe_kanban_view .oe_kanban_content .oe_star_on {
-- color: gold;
--}
++ color: gold; }
.openerp .oe_kanban_view .oe_kanban_content div:first-child {
-- margin-right: 16px;
--}
++ margin-right: 16px; }
.openerp .oe_kanban_view .oe_kanban_button_new {
color: white;
-- background: #dc5f59;
--}
++ background: #dc5f59; }
.openerp .oe_kanban_view .oe_kanban_groups {
-- height: inherit;
--}
++ height: inherit; }
.openerp .oe_kanban_view.oe_kanban_ungrouped .oe_kanban_groups {
-- width: 100%;
--}
++ width: 100%; }
.openerp .oe_kanban_view.oe_kanban_grouped_by_m2o .oe_kanban_group_title {
-- cursor: move;
--}
++ cursor: move; }
.openerp .oe_kanban_view .oe_kanban_header .oe_dropdown_kanban {
-- float: right;
--}
++ float: right; }
.openerp .oe_kanban_view .oe_kanban_header .oe_dropdown_kanban > span {
-- visibility: hidden;
--}
++ visibility: hidden; }
.openerp .oe_kanban_view .oe_kanban_header:hover .oe_dropdown_kanban > span {
-- visibility: visible;
--}
- .openerp .oe_kanban_view .oe_kanban_header:hover .oe_kanban_group_length {
- display: none;
- }
++ visibility: visible; }
.openerp .oe_kanban_view .oe_kanban_header .oe_dropdown_menu {
font-weight: normal;
-- font-size: 13px;
--}
++ font-size: 13px; }
.openerp .oe_kanban_view .oe_kanban_group_title {
position: relative;
font-size: 16px;
color: #333333;
text-shadow: 0 1px 0 white;
margin-right: 30px;
-- width: 200px;
--}
++ width: 200px; }
.openerp .oe_kanban_view .oe_kanban_group_title .oe_kanban_group_title_text {
margin-right: 4px;
white-space: nowrap;
overflow: hidden;
-- text-overflow: ellipsis;
--}
- .openerp .oe_kanban_view .oe_kanban_group_title .oe_kanban_group_length {
++ text-overflow: ellipsis; }
+ .openerp .oe_kanban_view .oe_fold_column .oe_kanban_group_length {
position: absolute;
top: -1px;
right: -14px;
- text-align: center;
float: right;
- }
- display: block;
-}
++ display: block; }
.openerp .oe_kanban_view.oe_kanban_grouped .oe_kanban_column, .openerp .oe_kanban_view.oe_kanban_grouped .oe_kanban_group_header {
width: 185px;
-- min-width: 185px;
--}
++ min-width: 185px; }
.openerp .oe_kanban_view.oe_kanban_grouped .oe_kanban_column.oe_kanban_group_folded, .openerp .oe_kanban_view.oe_kanban_grouped .oe_kanban_group_header.oe_kanban_group_folded {
width: auto;
-- min-width: 30px;
--}
++ min-width: 30px; }
.openerp .oe_kanban_view .oe_kanban_column, .openerp .oe_kanban_view .oe_kanban_group_header {
vertical-align: top;
-- padding: 5px 5px 5px 4px;
--}
++ padding: 5px 5px 5px 4px; }
.openerp .oe_kanban_view .oe_kanban_column ul, .openerp .oe_kanban_view .oe_kanban_column li, .openerp .oe_kanban_view .oe_kanban_group_header ul, .openerp .oe_kanban_view .oe_kanban_group_header li {
margin: 0;
padding: 0;
-- list-style-type: none;
--}
++ list-style-type: none; }
.openerp .oe_kanban_view .oe_kanban_group_header.oe_kanban_no_group {
-- padding: 0px;
--}
++ padding: 0px; }
.openerp .oe_kanban_view.oe_kanban_grouped .oe_kanban_column, .openerp .oe_kanban_view .oe_kanban_group_header {
background: #f0eeee;
border-left: 1px solid #f0f8f8;
-- border-right: 1px solid #b9b9b9;
--}
++ border-right: 1px solid #b9b9b9; }
.openerp .oe_kanban_view .oe_form .oe_kanban_column {
padding: 0px;
-- background: white;
--}
++ background: white; }
.openerp .oe_kanban_view .oe_kanban_column, .openerp .oe_kanban_view .oe_kanban_column_cards {
-- height: 100%;
--}
++ height: 100%; }
.openerp .oe_kanban_view .oe_kanban_aggregates {
padding: 0;
-- margin: 0px;
--}
- .openerp .oe_kanban_view .oe_kanban_column .oe_kanban_folded_column_cards {
- visibility: hidden;
- }
++ margin: 0px; }
.openerp .oe_kanban_view .oe_kanban_group_folded .oe_kanban_group_title, .openerp .oe_kanban_view .oe_kanban_group_folded.oe_kanban_column *, .openerp .oe_kanban_view .oe_kanban_group_folded .oe_kanban_aggregates, .openerp .oe_kanban_view .oe_kanban_group_folded .oe_kanban_add {
-- display: none;
--}
- .openerp .oe_kanban_view .oe_kanban_group_folded .oe_kanban_group_title_vertical {
- display: block;
- }
++ display: none; }
+ .openerp .oe_kanban_view .oe_kanban_group_folded .oe_kanban_group_title_vertical, .openerp .oe_kanban_view .oe_kanban_group_folded .oe_kanban_group_length {
- display: block;
-}
++ display: block; }
.openerp .oe_kanban_view .oe_kanban_group_folded .oe_dropdown_kanban {
-- left: -5px;
--}
++ left: -5px; }
+.openerp .oe_kanban_view .oe_kanban_group_folded .oe_kanban_folded_column_cards {
+ visibility: visible;
+ display: block !important;
- height: 100%;
- }
++ height: 100%; }
.openerp .oe_kanban_view .oe_kanban_group_title_undefined {
-- color: #666666;
--}
++ color: #666666; }
.openerp .oe_kanban_view .oe_kanban_group_title_vertical {
writing-mode: tb-rl;
-webkit-transform: rotate(90deg);
display: none;
position: relative;
opacity: 0.75;
-- top: 26px;
--}
++ top: 26px; }
.openerp .oe_kanban_view .oe_kanban_add, .openerp .oe_kanban_view .oe_kanban_header .oe_dropdown_toggle {
margin-left: 4px;
cursor: pointer;
-- position: relative;
--}
++ position: relative; }
.openerp .oe_kanban_view .oe_kanban_add {
top: -8px;
- }
- z-index: 2;
-}
++ z-index: 2; }
.openerp .oe_kanban_view .oe_kanban_header .oe_dropdown_toggle {
top: -2px;
- }
- .openerp .oe_kanban_view .oe_kanban_header .oe_dropdown_toggle .oe_kanban_group_length {
- margin: 7px 1px -15px 2px;
- font-weight: bold;
- }
- height: 14px;
-}
++ height: 14px; }
.openerp .oe_kanban_view .oe_kanban_card, .openerp .oe_kanban_view .oe_dropdown_toggle {
cursor: pointer;
-- display: inline-block;
--}
++ display: inline-block; }
.openerp .oe_kanban_view .oe_kanban_add {
-- float: right;
--}
++ float: right; }
.openerp .oe_kanban_view .oe_kanban_quick_create_buttons {
-- margin: 4px 0;
--}
++ margin: 4px 0; }
.openerp .oe_kanban_view .oe_kanban_no_group .oe_kanban_quick_create {
width: 185px;
-- padding: 10px;
--}
++ padding: 10px; }
+ .openerp .oe_kanban_view .oe_kanban_quick_create {
- z-index: 2;
-}
++ z-index: 2; }
.openerp .oe_kanban_view .oe_kanban_quick_create input {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
width: 100%;
-moz-box-shadow: none;
-webkit-box-shadow: none;
-- -box-shadow: none;
--}
++ -box-shadow: none; }
.openerp .oe_kanban_view .oe_kanban_quick_create input:focus {
border: 1px solid #a6a6fe;
-moz-box-shadow: 0px 0px 7px rgba(0, 133, 255, 0.3) inset;
-webkit-box-shadow: 0px 0px 7px rgba(0, 133, 255, 0.3) inset;
-- -box-shadow: 0px 0px 7px rgba(0, 133, 255, 0.3) inset;
--}
++ -box-shadow: 0px 0px 7px rgba(0, 133, 255, 0.3) inset; }
.openerp .oe_kanban_view .oe_kanban_vignette {
padding: 8px;
-- min-height: 100px;
--}
++ min-height: 100px; }
.openerp .oe_kanban_view .oe_kanban_image {
display: inline-block;
vertical-align: top;
border-radius: 3px;
-moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.4);
-webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.4);
-- -box-shadow: 0 1px 4px rgba(0, 0, 0, 0.4);
--}
++ -box-shadow: 0 1px 4px rgba(0, 0, 0, 0.4); }
.openerp .oe_kanban_view .oe_kanban_details {
display: inline-block;
vertical-align: top;
width: 240px;
font-size: 13px;
padding: 0 5px;
-- color: #4c4c4c;
--}
++ color: #4c4c4c; }
.openerp .oe_kanban_view .oe_kanban_details h4 {
-- margin: 0 0 4px 0;
--}
++ margin: 0 0 4px 0; }
.openerp .oe_kanban_view .oe_kanban_details .oe_tag {
display: inline-block;
-- margin: 0 2px 2px 0;
--}
++ margin: 0 2px 2px 0; }
.openerp .oe_kanban_view .oe_kanban_record {
position: relative;
display: block;
margin: 0;
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
-- border-radius: 4px;
--}
++ border-radius: 4px; }
.openerp .oe_kanban_view .oe_kanban_record:last-child {
-- margin-bottom: 0;
--}
++ margin-bottom: 0; }
.openerp .oe_kanban_view .oe_kanban_record .oe_kanban_title {
font-weight: bold;
-- margin: 2px 4px;
--}
++ margin: 2px 4px; }
+ .openerp .oe_kanban_view .oe_kanban_record .oe_kanban_alias {
- margin: 0px 0 8px 0;
-}
++ margin: 0px 0 8px 0; }
+ .openerp .oe_kanban_view .oe_kanban_record .oe_kanban_alias .oe_e {
+ font-size: 30px;
+ line-height: 6px;
+ vertical-align: top;
+ margin-right: 3px;
+ color: white;
+ text-shadow: 0px 0px 2px black;
- float: left;
-}
++ float: left; }
.openerp .oe_kanban_view.oe_kanban_grouped .oe_kanban_record {
-- margin-bottom: 4px;
--}
++ margin-bottom: 4px; }
.openerp .oe_kanban_view .oe_kanban_avatar_smallbox {
height: 40px;
width: 40px;
border-radius: 3px;
-moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
-- -box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
--}
++ -box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2); }
.openerp .oe_kanban_view .oe_kanban_box {
background: white;
border: 2px solid #cccccc;
border-radius: 4px;
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
-- margin-bottom: 5px;
--}
++ margin-bottom: 5px; }
.openerp .oe_kanban_view .oe_kanban_box_header {
-- border-bottom: 1px solid #cccccc;
--}
++ border-bottom: 1px solid #cccccc; }
.openerp .oe_kanban_view .oe_kanban_title {
font-size: 95%;
font-weight: bold;
-- padding: 0 4px 0 4px;
--}
++ padding: 0 4px 0 4px; }
.openerp .oe_kanban_view .oe_kanban_small {
font-size: 80%;
-- font-weight: normal;
--}
++ font-weight: normal; }
.openerp .oe_kanban_view .oe_kanban_show_more {
clear: both;
-- text-align: center;
--}
++ text-align: center; }
.openerp .oe_kanban_view.oe_kanban_grouped .oe_kanban_show_more .oe_button {
-- width: 100%;
--}
++ width: 100%; }
.openerp .oe_kanban_view.oe_kanban_ungrouped .oe_kanban_column .oe_kanban_record {
display: inline-block;
padding: 2px;
vertical-align: top;
box-sizing: border-box;
-moz-box-sizing: border-box;
-- -webkit-box-sizing: border-box;
--}
++ -webkit-box-sizing: border-box; }
.openerp .oe_kanban_view .oe_kanban_action_button {
height: 22px;
-- margin: 0;
--}
++ margin: 0; }
.openerp .oe_kanban_view .oe_kanban_action_a {
-- text-decoration: none;
--}
++ text-decoration: none; }
.openerp .oe_kanban_view .oe_kanban_action_a:hover {
-- text-decoration: none;
--}
++ text-decoration: none; }
.openerp .oe_kanban_view .oe_kanban_table {
width: 100%;
border: none;
border-collapse: collapse;
margin: 0;
-- padding: 0;
--}
++ padding: 0; }
.openerp .oe_kanban_view .oe_kanban_table tr td {
-- padding: 0;
--}
++ padding: 0; }
.openerp .oe_kanban_view .oe_kanban_table tr td.oe_kanban_title {
-- padding: 2px;
--}
++ padding: 2px; }
.openerp .oe_kanban_view .oe_kanban_box_content {
padding: 4px;
-- font-size: 90%;
--}
++ font-size: 90%; }
.openerp .oe_kanban_view .oe_kanban_button {
border: 1px solid #8ec1da;
background-color: #ddeef6;
text-shadow: 0 1px white;
padding: 0 4px;
font-size: 85%;
-- margin: 1px;
--}
++ margin: 1px; }
.openerp .oe_kanban_view a.oe_kanban_button:hover, .openerp .oe_kanban_view .openerp button.oe_kanban_button:hover {
-- background-color: #eeddf6;
--}
++ background-color: #eeddf6; }
.openerp .oe_kanban_view .oe_kanban_buttons_set {
border-top: 1px dotted;
white-space: nowrap;
padding-top: 2px;
position: relative;
-- clear: both;
--}
++ clear: both; }
.openerp .oe_kanban_view .oe_kanban_buttons_set a {
-- padding: 2px;
--}
++ padding: 2px; }
.openerp .oe_kanban_view .oe_kanban_box_show_onclick {
-- display: none;
--}
++ display: none; }
.openerp .oe_kanban_view .oe_kanban_draghandle {
-- cursor: move;
--}
++ cursor: move; }
.openerp .oe_kanban_view .oe_kanban_color_border {
-- border-color: #cccccc;
--}
++ border-color: #cccccc; }
.openerp .oe_kanban_view .oe_kanban_color_border {
-- border-color: #cccccc;
--}
++ border-color: #cccccc; }
.openerp .oe_kanban_view .oe_kanban_tooltip ul, .openerp .oe_kanban_view ul.oe_kanban_tooltip {
padding: 0 0 4px 0;
margin: 5px 0 0 15px;
-- list-style: circle;
--}
++ list-style: circle; }
.openerp .oe_kanban_view .oe_kanban_highlight {
border-radius: 2px;
-moz-border-radius: 2px;
margin: 1px 4px;
white-space: nowrap;
display: inline-block;
-- line-height: 1em;
--}
++ line-height: 1em; }
.openerp .oe_kanban_view .oe_kanban_card, .openerp .oe_kanban_view .oe_kanban_quick_create {
margin-bottom: 4px;
position: relative;
-webkit-transition: -webkit-transform, -webkit-box-shadow, border 200ms linear;
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
-- border-radius: 4px;
--}
++ border-radius: 4px; }
.openerp .oe_kanban_view .oe_kanban_card:not(.ui-sortable-helper):hover, .openerp .oe_kanban_view .oe_kanban_quick_create:not(.ui-sortable-helper):hover {
border: 1px solid #7c7bad;
-moz-box-shadow: 0 0 4px #7c7bad;
-webkit-box-shadow: 0 0 4px #7c7bad;
-- -box-shadow: 0 0 4px #7c7bad;
--}
++ -box-shadow: 0 0 4px #7c7bad; }
.openerp .oe_kanban_view .oe_kanban_card:not(.ui-sortable-helper):hover .oe_dropdown_kanban > span, .openerp .oe_kanban_view .oe_kanban_quick_create:not(.ui-sortable-helper):hover .oe_dropdown_kanban > span {
-- visibility: visible;
--}
++ visibility: visible; }
.openerp .oe_kanban_view .oe_kanban_card h3, .openerp .oe_kanban_view .oe_kanban_quick_create h3 {
margin: 0 16px 0 0;
color: #4c4c4c;
-- text-decoration: none;
--}
++ text-decoration: none; }
.openerp .oe_kanban_view .oe_kanban_card h3:hover, .openerp .oe_kanban_view .oe_kanban_quick_create h3:hover {
-- text-decoration: none;
--}
++ text-decoration: none; }
.openerp .oe_kanban_view .oe_kanban_card .oe_dropdown_kanban .oe_kanban_project_times li, .openerp .oe_kanban_view .oe_kanban_quick_create .oe_dropdown_kanban .oe_kanban_project_times li {
-- float: left;
--}
++ float: left; }
.openerp .oe_kanban_view .oe_kanban_star {
float: left;
position: inline-block;
-- margin: 0 4px 0 0;
--}
++ margin: 0 4px 0 0; }
.openerp .oe_kanban_view .oe_kanban_avatar {
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
border-radius: 3px;
-moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
-- -box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
--}
++ -box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2); }
.openerp .oe_kanban_view .oe_kanban_footer_left {
-- margin-top: 2px;
--}
++ margin-top: 2px; }
.openerp .oe_kanban_view .oe_kanban_footer_left > span {
margin-top: 2px;
display: inline-block;
line-height: 16px;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
-- border-radius: 3px;
--}
++ border-radius: 3px; }
.openerp .oe_kanban_view .oe_kanban_footer_left > span .oe_e {
line-height: 12px;
-- font-size: 22px;
--}
++ font-size: 22px; }
.openerp .oe_kanban_view .oe_kanban_footer_left .oe_tags {
-- margin-right: 0;
--}
++ margin-right: 0; }
.openerp .oe_kanban_view .oe_kanban_footer_left .oe_tags .oe_tag {
display: inline-block;
padding: 0 2px;
-- line-height: 14px;
--}
++ line-height: 14px; }
.openerp .oe_kanban_view .oe_kanban_footer_left .oe_kanban_mail_new {
line-height: 18px;
background-color: #8a89ba;
color: white;
font-weight: bold;
position: relative;
-- top: -1px;
--}
++ top: -1px; }
.openerp .oe_kanban_view .oe_kanban_bottom_right {
float: right;
position: relative;
-- top: 2px;
--}
++ top: 2px; }
.openerp .oe_kanban_view .oe_kanban_status {
position: relative;
top: 4px;
background-image: -webkit-radial-gradient(circle, #eeeeee 0%, #cccccc 40%, #bbbbbb 100%);
background-image: -moz-radial-gradient(#eeeeee 0%, #cccccc 40%, #bbbbbb 100%);
background-image: -ms-radial-gradient(#eeeeee 0%, #cccccc 40%, #bbbbbb 100%);
-- background-image: radial-gradient(#eeeeee 0%, #cccccc 40%, #bbbbbb 100%);
--}
++ background-image: radial-gradient(#eeeeee 0%, #cccccc 40%, #bbbbbb 100%); }
.openerp .oe_kanban_view .oe_kanban_status_green {
background: green;
background-position: center center;
background-image: -webkit-radial-gradient(circle, #55dd55 0%, #44aa44 40%, #339933 100%);
background-image: -moz-radial-gradient(#55dd55 0%, #44aa44 40%, #339933 100%);
background-image: -ms-radial-gradient(#55dd55 0%, #44aa44 40%, #339933 100%);
-- background-image: radial-gradient(#55dd55 0%, #44aa44 40%, #339933 100%);
--}
++ background-image: radial-gradient(#55dd55 0%, #44aa44 40%, #339933 100%); }
.openerp .oe_kanban_view .oe_kanban_status_red {
background: red;
background-position: center center;
background-image: -webkit-radial-gradient(circle, #ee7777 0%, #cc3333 40%, #bb0808 100%);
background-image: -moz-radial-gradient(#ee7777 0%, #cc3333 40%, #bb0808 100%);
background-image: -ms-radial-gradient(#ee7777 0%, #cc3333 40%, #bb0808 100%);
-- background-image: radial-gradient(#ee7777 0%, #cc3333 40%, #bb0808 100%);
--}
++ background-image: radial-gradient(#ee7777 0%, #cc3333 40%, #bb0808 100%); }
.openerp .oe_kanban_view .oe_kanban_text_red {
color: #a61300;
font-weight: bold;
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
-- border-radius: 4px;
--}
++ border-radius: 4px; }
.openerp .oe_kanban_view .oe_kanban_ellipsis {
overflow: hidden;
text-overflow: ellipsis;
-- white-space: nowrap;
--}
++ white-space: nowrap; }
.openerp .oe_kanban_view .oe_dropdown_kanban {
float: right;
cursor: pointer;
-- margin-top: -6px;
--}
++ margin-top: -6px; }
.openerp .oe_kanban_view .oe_dropdown_kanban:hover {
-- text-decoration: none;
--}
++ text-decoration: none; }
.openerp .oe_kanban_view .oe_dropdown_kanban .oe_dropdown_menu {
left: 0;
top: 28px;
min-width: 160px;
-- padding: 2px;
--}
++ padding: 2px; }
.openerp .oe_kanban_view .oe_dropdown_kanban .oe_dropdown_menu > li {
-- padding: 3px;
--}
++ padding: 3px; }
.openerp .oe_kanban_view .oe_dropdown_kanban.oe_opened > span {
-- visibility: visible;
--}
++ visibility: visible; }
.openerp .oe_kanban_view .oe_dropdown_kanban > span {
-- visibility: hidden;
--}
++ visibility: hidden; }
.openerp .oe_kanban_view .oe_kanban_colorpicker {
-- white-space: nowrap;
--}
++ white-space: nowrap; }
.openerp .oe_kanban_view .oe_kanban_colorpicker li {
float: left;
margin: 0;
-- padding: 0;
--}
++ padding: 0; }
.openerp .oe_kanban_view .oe_kanban_colorpicker li a {
display: inline-block;
width: 16px;
height: 16px;
-- border: 1px solid white;
--}
++ border: 1px solid white; }
.openerp .oe_kanban_view .oe_kanban_colorpicker li a:hover {
-- border: 1px solid gray !important;
--}
++ border: 1px solid gray !important; }
.openerp .oe_kanban_view .oe_kanban_colorpicker li:first-child a {
-- border: 1px solid #cccccc;
--}
++ border: 1px solid #cccccc; }
.openerp .oe_kanban_view .oe_kanban_color_0 {
background-color: white;
-- color: #5a5a5a;
--}
++ color: #5a5a5a; }
.openerp .oe_kanban_view .oe_kanban_color_1 {
background-color: #cccccc;
-- color: #424242;
--}
++ color: #424242; }
.openerp .oe_kanban_view .oe_kanban_color_2 {
background-color: #ffc7c7;
-- color: #7a3737;
--}
++ color: #7a3737; }
.openerp .oe_kanban_view .oe_kanban_color_3 {
background-color: #fff1c7;
-- color: #756832;
--}
++ color: #756832; }
.openerp .oe_kanban_view .oe_kanban_color_4 {
background-color: #e3ffc7;
-- color: #5d6937;
--}
++ color: #5d6937; }
.openerp .oe_kanban_view .oe_kanban_color_5 {
background-color: #c7ffd5;
-- color: #1a7759;
--}
++ color: #1a7759; }
.openerp .oe_kanban_view .oe_kanban_color_6 {
background-color: #c7ffff;
-- color: #1a5d83;
--}
++ color: #1a5d83; }
.openerp .oe_kanban_view .oe_kanban_color_7 {
background-color: #c7d5ff;
-- color: #3b3e75;
--}
++ color: #3b3e75; }
.openerp .oe_kanban_view .oe_kanban_color_8 {
background-color: #e3c7ff;
-- color: #4c3668;
--}
++ color: #4c3668; }
.openerp .oe_kanban_view .oe_kanban_color_9 {
background-color: #ffc7f1;
-- color: #6d2c70;
--}
++ color: #6d2c70; }
.openerp .oe_form .oe_kanban_view .oe_kanban_column, .openerp .oe_form .oe_kanban_view .oe_kanban_group_header {
padding: 0px;
-- background: white;
--}
++ background: white; }
.openerp .oe_popup_form .oe_kanban_buttons .oe_highlight {
color: #404040;
-- background: none;
--}
++ background: none; }
.openerp .oe_popup_form .oe_kanban_buttons button.oe_highlight {
background-color: #efefef;
background-image: -webkit-gradient(linear, left top, left bottom, from(#efefef), to(#d8d8d8));
background-image: linear-gradient(to bottom, #efefef, #d8d8d8);
-moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(255, 255, 255, 0.8) inset;
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(255, 255, 255, 0.8) inset;
-- -box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(255, 255, 255, 0.8) inset;
--}
++ -box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(255, 255, 255, 0.8) inset; }
.openerp .oe_popup_form .oe_kanban_buttons button.oe_highlight:active {
background-color: #e3e3e3;
background-image: -webkit-gradient(linear, left top, left bottom, from(#e3e3e3), to(#f6f6f6));
background-image: linear-gradient(to bottom, #e3e3e3, #f6f6f6);
-moz-box-shadow: none;
-webkit-box-shadow: none;
-- -box-shadow: none;
--}
++ -box-shadow: none; }
.openerp .oe_popup_form .oe_kanban_buttons button.oe_highlight:hover {
background-color: #f6f6f6;
background-image: -webkit-gradient(linear, left top, left bottom, from(#f6f6f6), to(#e3e3e3));
background-image: linear-gradient(to bottom, #f6f6f6, #e3e3e3);
-moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(255, 255, 255, 0.8) inset;
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(255, 255, 255, 0.8) inset;
-- -box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(255, 255, 255, 0.8) inset;
--}
++ -box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(255, 255, 255, 0.8) inset; }
.openerp_ie .oe_kanban_view .oe_kanban_group_header .oe_kanban_group_title_vertical {
-- display: none !important;
--}
++ display: none !important; }
.openerp_ie .oe_kanban_view .oe_kanban_group_header.oe_kanban_group_folded .oe_kanban_group_title_vertical {
-- display: inline-block !important;
--}
++ display: inline-block !important; }
.openerp_ie .oe_kanban_view .oe_kanban_group_title_vertical {
-ms-writing-mode: lr-tb !important;
background: #f0eeee;
-- top: -5px !important;
--}
++ top: -5px !important; }
.openerp_ie .oe_kanban_view.oe_kanban_grouped .oe_kanban_group_header {
-- height: 1%;
--}
++ height: 1%; }
@media print {
.openerp .oe_kanban_groups button {
-- visibility: hidden;
-- }
++ visibility: hidden; }
.openerp .oe_kanban_groups a[data-type=object], .openerp .oe_kanban_groups a[data-type=delete] {
-- visibility: hidden;
-- }
++ visibility: hidden; }
.openerp .oe_kanban_view .oe_kanban_group_title {
-- text-shadow: none !important;
-- }
--}
++ text-shadow: none !important; } }
//background: url(data:image/pngbase64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAYAAACp8Z5+AAAAKElEQVQIHWP8DwTv379nAAFBQUEGhnfv3oHEwADEZgJLIRGMIClkLQCr3x2Htp/lLwAAAABJRU5ErkJggg==)
background: white
height: inherit
+ .oe_kanban_column_higlight
+ background: #eeddf6 !important
- &.oe_kanban_grouped .oe_kanban_dummy_cell
- background: url(/web/static/src/img/form_sheetbg.png)
- width: 100%
+ .oe_view_nocontent
+ position: relative
+ z-index: 1
+ max-width: none
+ height: 100%
+ .oe_view_nocontent_content
+ margin-left: 90px
+ margin-top: 5px
+ max-width: 700px
+ .oe_view_nocontent_bg
+ background: #eee
+ opacity: 0.7
+ position: absolute
+ top: 0
+ bottom: 0
+ left: 0
+ right: 0
+ z-index: -1
+ &.oe_kanban_grouped
+ .oe_kanban_dummy_cell
+ background: url(/web/static/src/img/form_sheetbg.png)
+ width: 100%
+ .oe_kanban_group_length
+ text-align: center
+ display: none
+ .oe_tag
+ position: relative
+ top: +8px
+ font-weight: bold
++ .oe_kanban_header:hover .oe_kanban_group_length
++ display: none
.ui-sortable-placeholder
border: 1px solid rgba(0,0,0,0.1)
visibility: visible !important
.oe_kanban_column, .oe_kanban_column_cards
height: 100%
++
.oe_kanban_aggregates
padding: 0
margin: 0px
.oe_kanban_project_times
li
float: left
--
++
.oe_kanban_star
float: left
position: inline-block
}
evt.currentTarget.selectedIndex = 0;
}else{
-- return this._super.apply(this,arguments);
++ return this._super.apply(this,arguments);
}
}
});
return main_object;
},
parse_xml: function(arch, view_id) {
++ //First element of att_list must be element tagname.
main_object = {
'level': 0,
'id': this.xml_element_id +=1,
-- 'att_list': [],
++ 'att_list': ["view"],
'name': _.str.sprintf("<view view_id = %s>", view_id),
'child_id': []
};
var field_dataset = new instance.web.DataSetSearch(this, this.model, null, null);
parent_tr = self.get_object_by_id(parseInt($(parent_tr).attr('id').replace(/[^0-9]+/g, '')), this.one_object['main_object'], [])[0].att_list[0];
_.each([tr, parent_tr],function(element) {
-- var value = _.has(_CHILDREN, element) ? element : _.str.include(html_tag, element)?"html_tag":false;
++ var value = _.has(_CHILDREN, element) ? element : _.str.include(html_tag, element)?"html_tag":false;
property_to_check.push(value);
});
field_dataset.call( 'fields_get', []).done(function(result) {
var fields = _.keys(result);
fields.push(" "),fields.sort();
-- self.on_add_node(property_to_check, fields);
++ self.on_add_node(property_to_check, fields, self.inject_position(parent_tr,tr));
});
},
++ inject_position : function(parent_tag,current_tag){
++ if(parent_tag == "view")
++ return ['Inside'];
++ if(current_tag == "field")
++ return ['After','Before'];
++ return ['After','Before','Inside'];
++ },
do_node_edit: function(side) {
var self = this;
var result = self.get_object_by_id(this.one_object.clicked_tr_id, this.one_object['main_object'], []);
var children = _.filter(xml_arch.childNodes[0].childNodes, function (child) {
return child.nodeType == 1;
});
-- arch.arch = _.detect(children, function(xml_child) {
++ var inherited_view = _.detect(children, function(xml_child) {
var temp_obj = self.create_View_Node(xml_child),
insert = _.intersection(_.flatten(temp_obj.att_list),_.uniq(check_list));
if (insert.length == _.uniq(check_list).length ) {return xml_child;}
});
-- xml_arch = QWeb.load_xml(arch.arch);
++ xml_arch = QWeb.load_xml(instance.web.xml_to_str(inherited_view));
}
return self.do_save_xml(xml_arch.documentElement, obj[0].child_id[0],obj[0].child_id, move_direct, update_values,arch);
},
});
return def.promise();
},
-- on_add_node: function(properties, fields){
++ on_add_node: function(properties, fields, position){
var self = this;
var render_list = [{'name': 'node_type','selection': _.keys(_CHILDREN).sort(), 'value': 'field', 'string': 'Node Type','type': 'selection'},
{'name': 'field_value','selection': fields, 'value': false, 'string': '','type': 'selection'},
-- {'name': 'position','selection': ['After','Before','Inside'], 'value': false, 'string': 'Position','type': 'selection'}];
++ {'name': 'position','selection': position, 'value': false, 'string': 'Position','type': 'selection'}];
this.add_widget = [];
this.add_node_dialog = new instance.web.Dialog(this,{
title: _t("Properties"),
//e.g.:xyz 'td' : ['field']
};
// Generic html_tag list and can be added html tag in future. It's support above _CHILDREN dict's *html_tag* by default.
--// For specific child node one has to define tag above and specify children tag in list. Like above xyz example.
++// For specific child node one has to define tag above and specify children tag in list. Like above xyz example.
var html_tag = ['div','h1','h2','h3','h4','h5','h6','td','tr'];
var _ICONS = ['','STOCK_ABOUT', 'STOCK_ADD', 'STOCK_APPLY', 'STOCK_BOLD',