[IMP] New many2manytags field

Many2manytag widget is specialized by calendar module so it had to be
common for community/enterprise
This commit is contained in:
qsm-odoo
2015-06-19 09:46:38 +02:00
parent bd3bf97dce
commit 3abe93715a
6 changed files with 101 additions and 173 deletions
+3 -24
View File
@@ -221,31 +221,10 @@ WebClient.include({
});
var Many2ManyAttendee = FieldMany2ManyTags.extend({
tag_template: "many2manyattendee",
initialize_texttext: function() {
return _.extend(this._super(),{
html : {
tag: QWeb.render('m2mattendee_tag')
}
});
},
map_tag: function(value){
return _.map(value, function(el) {return {name: el[1], id:el[0], state: el[2]};});
},
tag_template: "Many2ManyAttendeeTag",
get_render_data: function(ids){
var self = this;
var dataset = new data.DataSetStatic(this, this.field.relation, self.build_context());
return dataset.call('get_attendee_detail',[ids, self.getParent().datarecord.id || false]);
},
render_tag: function(data){
this._super(data);
var self = this;
if (! self.get("effective_readonly")) {
var tag_element = self.tags.tagElements();
_.each(data,function(value, key){
$(tag_element[key]).find(".custom-edit").addClass(data[key][2]);
});
}
var dataset = new data.DataSetStatic(this, this.field.relation, this.build_context());
return dataset.call('get_attendee_detail',[ids, this.getParent().datarecord.id || false]);
}
});
@@ -1,13 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<template>
<t t-name="many2manyattendee">
<t t-set="i" t-value="0"/>
<t t-foreach="elements" t-as="el">
<span class="oe_tag no-wrap" t-att-data-index="i">
<a t-attf-class="oe_invitation #{el[2]}"/>
<t t-esc="el[1]"/>
</span>
<t t-set="i" t-value="i + 1"/>
<t t-name="Many2ManyAttendeeTag" t-extend="FieldMany2ManyTag">
<t t-jquery="span:first" t-operation="prepend">
<span t-attf-class="o_calendar_invitation #{el[2]}"/>
</t>
</t>
<t t-name='notify_title'>
@@ -21,16 +16,7 @@
<button class='link2event '>Details</button>
<button class='link2recall '>Snooze</button>
</t>
<t t-name='m2mattendee_tag'>
<div class="text-tag">
<div class="text-button">
<a class="oe_invitation custom-edit"/>
<span class="text-label"/>
<a class="text-remove"/>
</div>
</div>
</t>
<t t-name="invitation_view">
<div class='invitation_block well' style='width:50%; margin:auto; margin-top : 30px;'>
<div class="oe_right" style="margin-left:0px"><b><t t-esc="invitation['current_attendee'].cn"/> (<t t-esc="invitation['current_attendee'].email"/>)</b></div>
@@ -1236,125 +1236,61 @@ var One2ManyViewManager = ViewManager.extend({
});
var FieldMany2ManyTags = AbstractManyField.extend(common.CompletionFieldMixin, common.ReinitializeFieldMixin, {
template: "FieldMany2ManyTags",
className: "oe_form_field o_form_field_many2manytags",
tag_template: "FieldMany2ManyTag",
init: function() {
this._super.apply(this, arguments);
events: {
'click .o_delete': function(e) {
this.remove_id($(e.target).parent().data('id'));
}
},
init: function(field_manager, node) {
this._super(field_manager, node);
common.CompletionFieldMixin.init.call(this);
this.set({"value": []});
this._display_orderer = new utils.DropMisordered();
this._drop_shown = false;
},
initialize_texttext: function(){
var self = this;
return {
plugins : 'tags arrow autocomplete',
autocomplete: {
render: function(suggestion) {
return $('<span class="text-label"/>').
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 {
self.ignore_blur = true;
data.action();
}
this.trigger('setSuggestions', {result : []});
},
},
tags: {
isTagAllowed: function(tag) {
return !!tag.name;
},
removeTag: function(tag) {
var id = tag.data("id");
self.set({"value": _.without(self.get("value"), id)});
},
renderTag: function(stuff) {
return $.fn.textext.TextExtTags.prototype.renderTag.
call(this, stuff).data("id", stuff.id);
},
},
itemManager: {
itemToString: function(item) {
return item.name;
},
},
core: {
onSetInputData: function(e, data) {
if (data === '') {
this._plugins.autocomplete._suggestions = null;
}
this.input().val(data);
},
},
},
};
},
initialize_content: function() {
if (this.get("effective_readonly"))
return;
var self = this;
self.ignore_blur = false;
self.$text = this.$("textarea");
self.$text.textext(self.initialize_texttext()).bind('getSuggestions', function(e, data) {
var _this = this;
var str = !!data ? data.query || '' : '';
self.get_search_result(str).done(function(result) {
self.search_result = result;
$(_this).trigger('setSuggestions', {result : _.map(result, function(el, i) {
return _.extend(el, {index:i});
})});
});
}).bind('hideDropdown', function() {
self._drop_shown = false;
}).bind('showDropdown', function() {
self._drop_shown = true;
});
self.tags = self.$text.textext()[0].tags();
self.$text
.focusin(function () {
self.trigger('focused');
self.ignore_blur = false;
})
.focusout(function() {
self.$text.trigger("setInputData", "");
if (!self.ignore_blur) {
self.trigger('blurred');
}
}).keydown(function(e) {
if (e.which === $.ui.keyCode.TAB && self._drop_shown) {
self.$text.textext()[0].autocomplete().selectFromDropdown();
if(!this.get("effective_readonly")) {
this.many2one = new FieldMany2One(this.field_manager, this.node);
this.many2one.options.no_open = true;
this.many2one.on('changed_value', this, function() {
var newValue = this.many2one.get('value');
if(newValue) {
this.add_id(newValue);
var self = this;
setTimeout(function() {
self.many2one.$input.val('');
}, 0);
}
});
this.many2one.prependTo(this.$el);
var self = this;
this.many2one.$('input').on('keydown', function(e) {
if(!$(e.target).val() && e.which === 8) {
var $badges = self.$('.badge');
if($badges.length) {
self.remove_id($badges.last().data('id'));
}
}
});
}
},
get_search_blacklist: function() {
return this.get("value");
},
map_tag: function(data){
return _.map(data, function(el) {return {name: el[1], id:el[0]};});
destroy_content: function() {
if(this.many2one) {
this.many2one.destroy();
this.many2one = undefined;
}
},
get_render_data: function(ids){
return this.dataset.name_get(ids);
},
render_tag: function(data) {
var self = this;
if (! self.get("effective_readonly")) {
self.tags.containerElement().children().remove();
self.$('textarea').css("padding-left", "3px");
self.tags.addTags(self.map_tag(data));
} else {
self.$el.html(QWeb.render(self.tag_template, {elements: data}));
}
this.$('.badge').remove();
this.$el.prepend(QWeb.render(this.tag_template, {elements: data, readonly: this.get('effective_readonly')}));
},
render_value: function() {
var self = this;
@@ -1369,7 +1305,7 @@ var FieldMany2ManyTags = AbstractManyField.extend(common.CompletionFieldMixin, c
data = _.map(values, function(el) { return indexed[el]; });
self.render_tag(data);
};
if (! values || values.length > 0) {
if (!values || values.length > 0) {
return this._display_orderer.add(self.get_render_data(values)).done(handle_names);
} else {
handle_names([]);
@@ -1378,21 +1314,22 @@ var FieldMany2ManyTags = AbstractManyField.extend(common.CompletionFieldMixin, c
add_id: function(id) {
this.set({'value': _.uniq(this.get('value').concat([id]))});
},
remove_id: function(id) {
this.set({'value': _.without(this.get("value"), id)});
},
focus: function () {
var input = this.$text && this.$text[0];
return input ? input.focus() : false;
if(!this.get("effective_readonly")) {
return this.many2one.focus();
}
return false;
},
set_dimensions: function (height, width) {
this._super(height, width);
this.$("textarea").css({
width: width,
minHeight: height
});
},
_search_create_popup: function() {
this.ignore_blur = true;
return common.CompletionFieldMixin._search_create_popup.apply(this, arguments);
},
this._super(height, width);
var $input = this.$('input');
if (!this.get("effective_readonly") && $input) {
$input.css('height', height);
}
}
});
/**
@@ -224,6 +224,38 @@
}
}
.o_form_field_many2manytags {
.o-flex-display();
.o-flex-flow(row, wrap);
.o-align-items(flex-start);
.badge {
.o-flex(0, 0, auto);
margin: 0 3px 3px 0;
.o_delete {
cursor: pointer;
}
}
padding: 0;
> .oe_form_field_many2one {
padding: 0;
}
}
&.oe_form_editable .o_form_field_many2manytags {
border: 1px solid #CCC;
border-radius: 3px;
> .oe_form_field {
.o-flex(1, 0, 100px);
input {
border: none;
}
}
}
.o_address_format {
width: 100%;
+2 -9
View File
@@ -1262,19 +1262,12 @@
<t t-name="Many2OneButton.cell"
><img t-attf-src="#{prefix}/web/static/src/img/icons/#{widget.icon}.png" t-att-alt="widget.string" width="16" height="16"/>
</t>
<t t-name="FieldMany2ManyTags">
<div class="oe_form_field oe_tags" t-att-style="widget.node.attrs.style">
<t t-if="! widget.get('effective_readonly')">
<textarea rows="1" style="width: 100%"
t-att-placeholder="widget.node.attrs.placeholder"></textarea>
</t>
</div>
</t>
<t t-name="FieldMany2ManyTag">
<t t-set="i" t-value="0"/>
<t t-foreach="elements" t-as="el">
<span class="oe_tag" t-att-data-index="i">
<span class="badge" t-att-data-index="i" t-att-data-id="el[0]">
<t t-esc="el[1]"/>
<span t-if="!readonly" class="fa fa-times o_delete"/>
</span>
<t t-set="i" t-value="i + 1"/>
</t>
+5 -4
View File
@@ -72,10 +72,6 @@
<link rel="stylesheet" href="/web/static/lib/select2/select2.css"/>
<script type="text/javascript" src="/web/static/lib/select2/select2.js"></script>
<link rel="stylesheet" href='/website/static/src/less/import_bootstrap.less'/>
<link rel="stylesheet" href="/web/static/src/less/enterprise_compatibility.less"/>
<link rel="stylesheet" href="/web/static/src/less/utils.less"/>
<link rel="stylesheet" href="/web/static/src/less/modal.less"/>
<script src="/web/static/lib/bootstrap/js/affix.js"></script>
<script src="/web/static/lib/bootstrap/js/alert.js"></script>
<script src="/web/static/lib/bootstrap/js/button.js"></script>
@@ -115,6 +111,11 @@
<link rel="stylesheet" href="/web/static/src/css/data_export.css"/>
<link rel="stylesheet" href="/base/static/src/css/modules.css"/>
<link rel="stylesheet" href='/website/static/src/less/import_bootstrap.less'/>
<link rel="stylesheet" href="/web/static/src/less/enterprise_compatibility.less"/>
<link rel="stylesheet" href="/web/static/src/less/utils.less"/>
<link rel="stylesheet" href="/web/static/src/less/modal.less"/>
<script type="text/javascript" src="/web/static/lib/py.js/lib/py.js"></script>
<!-- Special case: core.js declares $.browser needed by ba-bbq -->