diff --git a/addons/web/static/src/css/base.css b/addons/web/static/src/css/base.css index 01f5d21511f..89b8cc1a38f 100644 --- a/addons/web/static/src/css/base.css +++ b/addons/web/static/src/css/base.css @@ -1633,7 +1633,7 @@ -webkit-border-radius: 3px; border-radius: 3px; background: white; - min-width: 90px; + min-width: 70px; color: #1f1f1f; } .openerp .oe_form input[readonly], @@ -1672,8 +1672,6 @@ .openerp .oe_form .oe_form_field_url button img { vertical-align: top; } -.openerp .oe_form .oe_form_field_translatable, -.openerp .oe_form .oe_form_field_many2one, .openerp .oe_form .oe_form_field_date, .openerp .oe_form .oe_form_field_datetime { white-space: nowrap; @@ -1790,8 +1788,9 @@ } .openerp .oe_horizontal_separator { font-weight: bold; - font-size: 16px; - margin: 4px 0; + font-size: 20px; + margin: 20px 0px 10px 0px; + color: #aaaabb; } .openerp .oe_horizontal_separator:empty { height: 5px; @@ -1868,7 +1867,7 @@ -webkit-border-radius: 3px; border-radius: 3px; background: white; - min-width: 90px; + min-width: 50px; } .openerp .oe_form .oe_form_field_progressbar.ui-progressbar span { position: absolute; @@ -1982,8 +1981,10 @@ .openerp .oe-listview-content > tbody > tr { border-top: 1px solid #dddddd; } -.openerp .oe-listview-content > tbody > tr > td, .openerp .oe-listview-content > tbody > tr > th { +.openerp .oe-listview-content > tbody > tr > td.oe-field-cell { padding: 3px 6px; +} +.openerp .oe-listview-content > tbody > tr > td, .openerp .oe-listview-content > tbody > tr > th { line-height: 18px; } .openerp .oe-listview-content > tbody > tr > td > button, .openerp .oe-listview-content > tbody > tr > th > button { diff --git a/addons/web/static/src/css/base.sass b/addons/web/static/src/css/base.sass index 95571ee7caf..e013009f9b1 100644 --- a/addons/web/static/src/css/base.sass +++ b/addons/web/static/src/css/base.sass @@ -1329,13 +1329,13 @@ $colour4: #8a89ba -webkit-border-radius: 3px border-radius: 3px background: white - min-width: 90px + min-width: 70px color: #1f1f1f input[readonly], select[readonly], textarea[readonly], input[disabled], - select[disabled], + select[disabled] background: #E5E5E5 !important color: #666 textarea[disabled] @@ -1359,8 +1359,6 @@ $colour4: #8a89ba .oe_form_field_email button img, .oe_form_field_url button img vertical-align: top - .oe_form_field_translatable, - .oe_form_field_many2one, .oe_form_field_date, .oe_form_field_datetime white-space: nowrap @@ -1471,8 +1469,9 @@ $colour4: #8a89ba border-bottom: 1px solid black .oe_horizontal_separator font-weight: bold - font-size: 16px - margin: 4px 0 + font-size: 20px + margin: 20px 0px 10px 0px + color: #aab .oe_horizontal_separator:empty height: 5px .oe_vertical_separator @@ -1538,7 +1537,7 @@ $colour4: #8a89ba -webkit-border-radius: 3px border-radius: 3px background: white - min-width: 90px + min-width: 50px span position: absolute @@ -1642,8 +1641,9 @@ $colour4: #8a89ba background: white > tr border-top: 1px solid #ddd - > td, > th + > td.oe-field-cell padding: 3px 6px + > td, > th line-height: 18px > button border: none diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js index ed11a63fde3..6d310743cae 100644 --- a/addons/web/static/src/js/view_form.js +++ b/addons/web/static/src/js/view_form.js @@ -673,7 +673,7 @@ instance.web.FormView = instance.web.View.extend(_.extend({}, instance.web.form. var msg = ""; @@ -937,7 +937,7 @@ instance.web.form.FormRenderingEngine = instance.web.form.FormRenderingEngineInt } var obj = self.fields_registry.get_any([$elem.attr('widget'), self.fvg.fields[name].type]); if (!obj) { - throw new Error("Widget type '"+ key + "' is not implemented"); + throw new Error("Widget type '"+ $elem.attr('widget') + "' is not implemented"); } var w = new (obj)(self.view, instance.web.xml_to_json($elem[0])); var $label = self.labels[$elem.attr("name")]; @@ -2951,6 +2951,12 @@ instance.web.form.One2ManyViewManager = instance.web.ViewManager.extend({ var pop = new instance.web.form.FormOpenPopup(self.o2m.view); pop.show_element(self.o2m.field.relation, id, self.o2m.build_context(), { title: _t("Open: ") + self.name, + create_function: function(data) { + return self.o2m.dataset.create(data).then(function(r) { + self.o2m.dataset.set_ids(self.o2m.dataset.ids.concat([r.result])); + self.o2m.dataset.on_change(); + }); + }, write_function: function(id, data, options) { return self.o2m.dataset.write(id, data, {}).then(function() { self.o2m.reload_current_view(); @@ -2965,6 +2971,9 @@ instance.web.form.One2ManyViewManager = instance.web.ViewManager.extend({ form_view_options: {'not_interactible_on_create':true}, readonly: self.o2m.get("effective_readonly") }); + pop.on_select_elements.add_last(function() { + self.o2m.reload_current_view(); + }); }, }); @@ -3148,7 +3157,7 @@ instance.web.form.FieldMany2ManyTags = instance.web.form.AbstractField.extend(_. }); }).bind('hideDropdown', function() { self._drop_shown = false; - }).bind('hideDropdown', function() { + }).bind('showDropdown', function() { self._drop_shown = true; }); self.tags = self.$text.textext()[0].tags(); @@ -3337,6 +3346,208 @@ instance.web.form.Many2ManyListView = instance.web.ListView.extend(/** @lends in } }); +instance.web.form.FieldMany2ManyKanban = instance.web.form.AbstractField.extend(_.extend({}, instance.web.form.CompletionFieldMixin, { + disable_utility_classes: true, + init: function(field_manager, node) { + this._super(field_manager, node); + instance.web.form.CompletionFieldMixin.init.call(this); + m2m_kanban_lazy_init(); + this.is_loaded = $.Deferred(); + this.initial_is_loaded = this.is_loaded; + this.is_setted = $.Deferred(); + }, + start: function() { + this._super.apply(this, arguments); + + var self = this; + + this.dataset = new instance.web.form.Many2ManyDataSet(this, this.field.relation); + this.dataset.m2m = this; + this.dataset.on_unlink.add_last(function(ids) { + self.dataset_changed(); + }); + + this.is_setted.then(function() { + self.load_view(); + }); + this.is_loaded.then(function() { + self.on("change:effective_readonly", self, function() { + self.is_loaded = self.is_loaded.pipe(function() { + self.kanban_view.destroy(); + return $.when(self.load_view()).then(function() { + self.reload_content(); + }); + }); + }); + }) + }, + set_value: function(value_) { + value_ = value_ || []; + if (value_.length >= 1 && value_[0] instanceof Array) { + value_ = value_[0][2]; + } + this._super(value_); + this.dataset.set_ids(value_); + var self = this; + self.reload_content(); + this.is_setted.resolve(); + }, + load_view: function() { + var self = this; + this.kanban_view = new instance.web.form.Many2ManyKanbanView(this, this.dataset, false, { + 'create_text': _t("Add"), + 'creatable': self.get("effective_readonly") ? false : true, + 'quick_creatable': self.get("effective_readonly") ? false : true, + }); + var embedded = (this.field.views || {}).kanban; + if (embedded) { + this.kanban_view.set_embedded_view(embedded); + } + this.kanban_view.m2m = this; + var loaded = $.Deferred(); + this.kanban_view.on_loaded.add_last(function() { + self.initial_is_loaded.resolve(); + loaded.resolve(); + }); + this.kanban_view.do_switch_view.add_last(_.bind(this.open_popup, this)); + $.async_when().then(function () { + self.kanban_view.appendTo(self.$element); + }); + return loaded; + }, + reload_content: function() { + var self = this; + this.is_loaded = this.is_loaded.pipe(function() { + return self.kanban_view.do_search(self.build_domain(), self.dataset.get_context(), []); + }); + }, + dataset_changed: function() { + this.set({'value': [commands.replace_with(this.dataset.ids)]}); + }, + open_popup: function(type, unused) { + if (type !== "form") + return; + var self = this; + if (this.dataset.index === null) { + var pop = new instance.web.form.SelectCreatePopup(this); + pop.select_element( + this.field.relation, + { + title: _t("Add: ") + this.name + }, + new instance.web.CompoundDomain(this.build_domain(), ["!", ["id", "in", this.dataset.ids]]), + this.build_context() + ); + pop.on_select_elements.add(function(element_ids) { + _.each(element_ids, function(one_id) { + if(! _.detect(self.dataset.ids, function(x) {return x == one_id;})) { + self.dataset.set_ids([].concat(self.dataset.ids, [one_id])); + self.dataset_changed(); + self.reload_content(); + } + }); + }); + } else { + var id = self.dataset.ids[self.dataset.index]; + var pop = new instance.web.form.FormOpenPopup(self.view); + pop.show_element(self.field.relation, id, self.build_context(), { + title: _t("Open: ") + self.name, + write_function: function(id, data, options) { + return self.dataset.write(id, data, {}).then(function() { + self.reload_content(); + }); + }, + alternative_form_view: self.field.views ? self.field.views["form"] : undefined, + parent_view: self.view, + child_name: self.name, + readonly: self.get("effective_readonly") + }); + } + }, + add_id: function(id) { + this.quick_create.add_id(id); + }, +})); + +function m2m_kanban_lazy_init() { +if (instance.web.form.Many2ManyKanbanView) + return; +instance.web.form.Many2ManyKanbanView = instance.web_kanban.KanbanView.extend({ + quick_create_class: 'instance.web.form.Many2ManyQuickCreate', + _is_quick_create_enabled: function() { + return this._super() && ! this.group_by; + }, +}); +instance.web.form.Many2ManyQuickCreate = instance.web.Widget.extend({ + template: 'Many2ManyKanban.quick_create', + + /** + * close_btn: If true, the widget will display a "Close" button able to trigger + * a "close" event. + */ + init: function(parent, dataset, context, buttons) { + this._super(parent); + this.m2m = this.getParent().view.m2m; + this.m2m.quick_create = this; + this._dataset = dataset; + this._buttons = buttons || false; + this._context = context || {}; + }, + start: function () { + var self = this; + self.$text = this.$element.find('input').css("width", "200px"); + self.$text.textext({ + plugins : 'arrow autocomplete', + autocomplete: { + render: function(suggestion) { + return $(''). + data('index', suggestion['index']).html(suggestion['label']); + } + }, + ext: { + autocomplete: { + selectFromDropdown: function() { + $(this).trigger('hideDropdown'); + var index = Number(this.selectedSuggestionElement().children().children().data('index')); + var data = self.search_result[index]; + if (data.id) { + self.add_id(data.id); + } else { + data.action(); + } + }, + }, + itemManager: { + itemToString: function(item) { + return item.name; + }, + }, + }, + }).bind('getSuggestions', function(e, data) { + var _this = this; + var str = !!data ? data.query || '' : ''; + self.m2m.get_search_result(str).then(function(result) { + self.search_result = result; + $(_this).trigger('setSuggestions', {result : _.map(result, function(el, i) { + return _.extend(el, {index:i}); + })}); + }); + }); + self.$text.focusout(function() { + self.$text.val(""); + }); + }, + focus: function() { + this.$text.focus(); + }, + add_id: function(id) { + var self = this; + self.$text.val(""); + self.trigger('added', id); + }, +}); +} + /** * Class with everything which is common between FormOpenPopup and SelectCreatePopup. */ @@ -4006,7 +4217,8 @@ instance.web.form.widgets = new instance.web.Registry({ 'selection' : 'instance.web.form.FieldSelection', 'many2one' : 'instance.web.form.FieldMany2One', 'many2many' : 'instance.web.form.FieldMany2Many', - 'many2manytags' : 'instance.web.form.FieldMany2ManyTags', + 'many2many_tags' : 'instance.web.form.FieldMany2ManyTags', + 'many2many_kanban' : 'instance.web.form.FieldMany2ManyKanban', 'one2many' : 'instance.web.form.FieldOne2Many', 'one2many_list' : 'instance.web.form.FieldOne2Many', 'reference' : 'instance.web.form.FieldReference', diff --git a/addons/web/static/src/xml/base.xml b/addons/web/static/src/xml/base.xml index 04f45258854..d07b8a7ee86 100644 --- a/addons/web/static/src/xml/base.xml +++ b/addons/web/static/src/xml/base.xml @@ -1806,5 +1806,8 @@
+
+ +
diff --git a/addons/web_kanban/static/src/css/kanban.css b/addons/web_kanban/static/src/css/kanban.css index 3512398bffa..dd376ef44e5 100644 --- a/addons/web_kanban/static/src/css/kanban.css +++ b/addons/web_kanban/static/src/css/kanban.css @@ -96,7 +96,7 @@ background: url(/web_kanban/static/src/img/plus-icon.png) no-repeat; } .openerp .oe_kanban_view .oe_kanban_quick_create { - overflow: hidden; + overflow: visible; } .openerp .oe_kanban_view .oe_kanban_no_group .oe_kanban_quick_create { width: 200px; diff --git a/addons/web_kanban/static/src/js/kanban.js b/addons/web_kanban/static/src/js/kanban.js index 60ff0891525..4a4e385cd1b 100644 --- a/addons/web_kanban/static/src/js/kanban.js +++ b/addons/web_kanban/static/src/js/kanban.js @@ -10,10 +10,11 @@ instance.web_kanban.KanbanView = instance.web.View.extend({ display_name: _lt('Kanban'), default_nr_columns: 3, view_type: "kanban", + quick_create_class: "instance.web_kanban.QuickCreate", number_of_color_schemes: 10, init: function (parent, dataset, view_id, options) { this._super(parent, dataset, view_id, options); - _.defaults(this.options, {"quick_creatable": true, "creatable": true}); + _.defaults(this.options, {"quick_creatable": true, "creatable": true, "create_text": undefined}); this.fields_view = {}; this.fields_keys = []; this.group_by = null; @@ -37,7 +38,7 @@ instance.web_kanban.KanbanView = instance.web.View.extend({ }, start: function() { var self = this; - this._super.apply(this, arguments); + var def = this._super.apply(this, arguments); // Bind kanban cards dropdown menus $('html').on('click.kanban', function() { self.trigger('hide_menus'); @@ -45,6 +46,7 @@ instance.web_kanban.KanbanView = instance.web.View.extend({ this.on('hide_menus', this, function() { self.$element.find('.oe_kanban_menu').hide(); }); + return def; }, destroy: function() { this._super.apply(this, arguments); @@ -337,6 +339,10 @@ instance.web_kanban.KanbanView = instance.web.View.extend({ } }); +function get_class(name) { + return new instance.web.Registry({'tmp' : name}).get_object("tmp"); +} + instance.web_kanban.KanbanGroup = instance.web.OldWidget.extend({ template: 'KanbanView.group_header', init: function (parent, records, group, dataset) { @@ -390,7 +396,7 @@ instance.web_kanban.KanbanGroup = instance.web.OldWidget.extend({ def = this._super(); if (! self.view.group_by) { self.$element.addClass("oe_kanban_no_group"); - self.quick = new instance.web_kanban.QuickCreate(this, self.dataset, {}, false) + self.quick = new (get_class(self.view.quick_create_class))(this, self.dataset, {}, false) .on('added', self, self.proxy('quick_created')); self.quick.replace($(".oe_kanban_no_group_qc_placeholder")); } @@ -405,13 +411,13 @@ instance.web_kanban.KanbanGroup = instance.web.OldWidget.extend({ if (self.quick) { return; } var ctx = {}; ctx['default_' + self.view.group_by] = self.value; - self.quick = new instance.web_kanban.QuickCreate(this, self.dataset, ctx, true) + self.quick = new (get_class(self.view.quick_create_class))(this, self.dataset, ctx, true) .on('added', self, self.proxy('quick_created')) .on('close', self, function() { this.quick.destroy(); delete this.quick; }); - self.quick.appendTo(self.$element.find('.oe_kanban_group_header')); + self.quick.appendTo(self.$element.find('.oe_kanban_header')); self.quick.focus(); }); this.$records.find('.oe_kanban_show_more').click(this.do_show_more); @@ -492,7 +498,7 @@ instance.web_kanban.KanbanGroup = instance.web.OldWidget.extend({ * @param {(Id, String)} record name_get format for the newly created record */ quick_created: function (record) { - var id = record[0], self = this; + var id = record, self = this; this.dataset.read_ids([id], this.view.fields_keys) .then(function (records) { self.view.dataset.ids.push(id); @@ -782,7 +788,7 @@ instance.web_kanban.QuickCreate = instance.web.Widget.extend({ this._dataset.get_context(), this._context)]) .pipe(function(record) { self.$input.val(""); - self.trigger('added', record); + self.trigger('added', record[0]); }, function(error, event) { event.preventDefault(); return self.slow_create(); @@ -803,7 +809,7 @@ instance.web_kanban.QuickCreate = instance.web.Widget.extend({ ); pop.on_select_elements.add(function(element_ids) { self.$input.val(""); - self.trigger('added', element_ids); + self.trigger('added', element_ids[0]); }); } }); diff --git a/addons/web_kanban/static/src/xml/web_kanban.xml b/addons/web_kanban/static/src/xml/web_kanban.xml index 2fef4737acc..cabe9cb52fb 100644 --- a/addons/web_kanban/static/src/xml/web_kanban.xml +++ b/addons/web_kanban/static/src/xml/web_kanban.xml @@ -13,7 +13,9 @@
- +