[Merge]Merge lp:openerp-web
bzr revid: vja@tinyerp.com-20130301104802-h03oi6khbhjv0pvs
This commit is contained in:
@@ -13,6 +13,7 @@ import os
|
||||
import re
|
||||
import simplejson
|
||||
import time
|
||||
import urllib
|
||||
import urllib2
|
||||
import zlib
|
||||
from xml.etree import ElementTree
|
||||
@@ -293,9 +294,9 @@ def manifest_list(req, extension, mods=None, db=None):
|
||||
if not req.debug:
|
||||
path = '/web/webclient/' + extension
|
||||
if mods is not None:
|
||||
path += '?mods=' + mods
|
||||
path += '?' + urllib.urlencode({'mods': mods})
|
||||
elif db:
|
||||
path += '?db=' + db
|
||||
path += '?' + urllib.urlencode({'db': db})
|
||||
return [path]
|
||||
files = manifest_glob(req, extension, addons=mods, db=db)
|
||||
i_am_diabetic = req.httprequest.environ["QUERY_STRING"].count("no_sugar") >= 1 or \
|
||||
@@ -1310,7 +1311,7 @@ class Binary(openerpweb.Controller):
|
||||
'id': attachment_id
|
||||
}
|
||||
except Exception:
|
||||
args = {'error':e.faultCode }
|
||||
args = {'error': "Something horrible happened"}
|
||||
return out % (simplejson.dumps(callback), simplejson.dumps(args))
|
||||
|
||||
@openerpweb.httprequest
|
||||
|
||||
@@ -32,12 +32,12 @@ NOMODULE_TEMPLATE = Template(u"""<!DOCTYPE html>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
""")
|
||||
""", default_filters=['h'])
|
||||
NOTFOUND = Template(u"""
|
||||
<p>Unable to find the module [${module}], please check that the module
|
||||
name is correct and the module is on OpenERP's path.</p>
|
||||
<a href="/web/tests"><< Back to tests</a>
|
||||
""")
|
||||
""", default_filters=['h'])
|
||||
TESTING = Template(u"""<!DOCTYPE html>
|
||||
<html style="height: 100%">
|
||||
<%def name="to_path(module, p)">/${module}/${p}</%def>
|
||||
@@ -51,9 +51,9 @@ TESTING = Template(u"""<!DOCTYPE html>
|
||||
<script src="/web/static/lib/qunit/qunit.js"></script>
|
||||
|
||||
<script type="text/javascript">
|
||||
var oe_db_info = ${db_info};
|
||||
var oe_db_info = ${db_info | n};
|
||||
// List of modules, each module is preceded by its dependencies
|
||||
var oe_all_dependencies = ${dependencies};
|
||||
var oe_all_dependencies = ${dependencies | n};
|
||||
QUnit.config.testTimeout = 5 * 60 * 1000;
|
||||
</script>
|
||||
</head>
|
||||
@@ -83,7 +83,7 @@ TESTING = Template(u"""<!DOCTYPE html>
|
||||
% endif
|
||||
% endfor
|
||||
</html>
|
||||
""")
|
||||
""", default_filters=['h'])
|
||||
|
||||
class TestRunnerController(http.Controller):
|
||||
_cp_path = '/web/tests'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@charset "UTF-8";
|
||||
@charset "utf-8";
|
||||
@font-face {
|
||||
font-family: "mnmliconsRegular";
|
||||
src: url("/web/static/src/font/mnmliconsv21-webfont.eot") format("eot");
|
||||
@@ -1263,7 +1263,7 @@
|
||||
color: white;
|
||||
padding: 2px 4px;
|
||||
margin: 1px 6px 0 0;
|
||||
border: 1px solid lightgrey;
|
||||
border: 1px solid lightGray;
|
||||
text-shadow: 0 1px 1px rgba(0, 0, 0, 0.2);
|
||||
-moz-border-radius: 4px;
|
||||
-webkit-border-radius: 4px;
|
||||
@@ -1295,7 +1295,7 @@
|
||||
transform: scale(1.1);
|
||||
}
|
||||
.openerp .oe_secondary_submenu .oe_active {
|
||||
border-top: 1px solid lightgrey;
|
||||
border-top: 1px solid lightGray;
|
||||
border-bottom: 1px solid #dedede;
|
||||
text-shadow: 0 1px 1px rgba(0, 0, 0, 0.2);
|
||||
-moz-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.2), inset 0 -1px 3px rgba(40, 40, 40, 0.2);
|
||||
@@ -1415,7 +1415,13 @@
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
}
|
||||
.openerp .oe_view_manager {
|
||||
display: table;
|
||||
height: inherit;
|
||||
width: 100%;
|
||||
}
|
||||
.openerp .oe_view_manager .oe_view_manager_body {
|
||||
display: table-row;
|
||||
height: inherit;
|
||||
}
|
||||
.openerp .oe_view_manager .oe_view_manager_view_kanban {
|
||||
@@ -2251,7 +2257,7 @@
|
||||
}
|
||||
.openerp .oe_form .oe_form_label_help[for] span, .openerp .oe_form .oe_form_label[for] span {
|
||||
font-size: 80%;
|
||||
color: darkgreen;
|
||||
color: darkGreen;
|
||||
vertical-align: top;
|
||||
position: relative;
|
||||
top: -4px;
|
||||
@@ -2323,6 +2329,7 @@
|
||||
width: 100%;
|
||||
display: inline-block;
|
||||
padding: 2px 2px 2px 0px;
|
||||
vertical-align: top;
|
||||
}
|
||||
.openerp .oe_form .oe_form_field input {
|
||||
margin: 0px;
|
||||
@@ -2366,7 +2373,6 @@
|
||||
white-space: nowrap;
|
||||
}
|
||||
.openerp .oe_form .oe_form_field_boolean {
|
||||
padding-top: 4px;
|
||||
width: auto;
|
||||
}
|
||||
.openerp .oe_form .oe_datepicker_container {
|
||||
@@ -3088,8 +3094,25 @@
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
@-moz-document url-prefix() {
|
||||
.openerp .oe_view_manager .oe_view_manager_switch li {
|
||||
line-height: 21px;
|
||||
}
|
||||
.openerp .oe_searchview .oe_searchview_search {
|
||||
top: -1px;
|
||||
}
|
||||
.openerp .oe_form_field_many2one .oe_m2o_cm_button {
|
||||
line-height: 18px;
|
||||
}
|
||||
.openerp .oe_secondary_submenu {
|
||||
line-height: 14px;
|
||||
}
|
||||
.openerp .oe_webclient .oe_star_on, .openerp .oe_webclient .oe_star_off {
|
||||
top: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
.kitten-mode-activated {
|
||||
background-image: url(http://placekitten.com/g/1365/769);
|
||||
background-size: cover;
|
||||
background-attachment: fixed;
|
||||
}
|
||||
@@ -3318,6 +3341,7 @@ div.ui-widget-overlay {
|
||||
overflow: hidden !important;
|
||||
}
|
||||
}
|
||||
|
||||
.blockUI.blockOverlay {
|
||||
background-color: black;
|
||||
opacity: 0.6;
|
||||
|
||||
@@ -1137,7 +1137,11 @@ $sheet-padding: 16px
|
||||
// }}}
|
||||
// ViewManager common {{{
|
||||
.oe_view_manager
|
||||
display: table
|
||||
height: inherit
|
||||
width: 100%
|
||||
.oe_view_manager_body
|
||||
display: table-row
|
||||
height: inherit
|
||||
.oe_view_manager_view_kanban
|
||||
height: inherit
|
||||
@@ -1845,6 +1849,7 @@ $sheet-padding: 16px
|
||||
width: 100%
|
||||
display: inline-block
|
||||
padding: 2px 2px 2px 0px
|
||||
vertical-align: top
|
||||
input
|
||||
margin: 0px
|
||||
input[type="text"], input[type="password"], input[type="file"], select
|
||||
@@ -1872,7 +1877,6 @@ $sheet-padding: 16px
|
||||
.oe_form_field_datetime
|
||||
white-space: nowrap
|
||||
.oe_form_field_boolean
|
||||
padding-top: 4px
|
||||
width: auto
|
||||
.oe_datepicker_container
|
||||
display: none
|
||||
@@ -2434,9 +2438,22 @@ $sheet-padding: 16px
|
||||
float: right
|
||||
color: #333
|
||||
// }}}
|
||||
@-moz-document url-prefix()
|
||||
.openerp
|
||||
.oe_view_manager .oe_view_manager_switch li
|
||||
line-height: 21px
|
||||
.oe_searchview .oe_searchview_search
|
||||
top: -1px
|
||||
.oe_form_field_many2one .oe_m2o_cm_button
|
||||
line-height: 18px
|
||||
.oe_secondary_submenu
|
||||
line-height: 14px
|
||||
.oe_webclient
|
||||
.oe_star_on, .oe_star_off
|
||||
top: 0px
|
||||
|
||||
// Kitten Mode {{{
|
||||
.kitten-mode-activated
|
||||
background-image: url(http://placekitten.com/g/1365/769)
|
||||
background-size: cover
|
||||
background-attachment: fixed
|
||||
>*
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 28 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 783 B |
@@ -1084,7 +1084,7 @@ instance.web.UserMenu = instance.web.Widget.extend({
|
||||
if (!self.session.uid)
|
||||
return;
|
||||
var func = new instance.web.Model("res.users").get_func("read");
|
||||
return func(self.session.uid, ["name", "company_id"]).then(function(res) {
|
||||
return self.alive(func(self.session.uid, ["name", "company_id"])).then(function(res) {
|
||||
var topbar_name = res.name;
|
||||
if(instance.session.debug)
|
||||
topbar_name = _.str.sprintf("%s (%s)", topbar_name, instance.session.db);
|
||||
@@ -1100,6 +1100,9 @@ instance.web.UserMenu = instance.web.Widget.extend({
|
||||
};
|
||||
this.update_promise = this.update_promise.then(fct, fct);
|
||||
},
|
||||
on_menu_help: function() {
|
||||
window.open('http://help.openerp.com', '_blank');
|
||||
},
|
||||
on_menu_logout: function() {
|
||||
this.trigger('user_logout');
|
||||
},
|
||||
@@ -1213,6 +1216,7 @@ instance.web.WebClient = instance.web.Client.extend({
|
||||
return $.when(this._super()).then(function() {
|
||||
if (jQuery.param !== undefined && jQuery.deparam(jQuery.param.querystring()).kitten !== undefined) {
|
||||
$("body").addClass("kitten-mode-activated");
|
||||
$("body").css("background-image", "url(" + instance.session.origin + "/web/static/src/img/back-enable.jpg" + ")");
|
||||
if ($.blockUI) {
|
||||
$.blockUI.defaults.message = '<img src="http://www.amigrave.com/kitten.gif">';
|
||||
}
|
||||
@@ -1299,7 +1303,7 @@ instance.web.WebClient = instance.web.Client.extend({
|
||||
},
|
||||
logo_edit: function(ev) {
|
||||
var self = this;
|
||||
new instance.web.Model("res.users").get_func("read")(this.session.uid, ["company_id"]).then(function(res) {
|
||||
new self.alive(instance.web.Model("res.users").get_func("read")(this.session.uid, ["company_id"])).then(function(res) {
|
||||
self.rpc("/web/action/load", { action_id: "base.action_res_company_form" }).done(function(result) {
|
||||
result.res_id = res['company_id'][0];
|
||||
result.target = "new";
|
||||
@@ -1320,7 +1324,7 @@ instance.web.WebClient = instance.web.Client.extend({
|
||||
},
|
||||
check_timezone: function() {
|
||||
var self = this;
|
||||
return new instance.web.Model('res.users').call('read', [[this.session.uid], ['tz_offset']]).then(function(result) {
|
||||
return self.alive(new instance.web.Model('res.users').call('read', [[this.session.uid], ['tz_offset']])).then(function(result) {
|
||||
var user_offset = result[0]['tz_offset'];
|
||||
var offset = -(new Date().getTimezoneOffset());
|
||||
// _.str.sprintf()'s zero front padding is buggy with signed decimals, so doing it manually
|
||||
@@ -1396,8 +1400,9 @@ instance.web.WebClient = instance.web.Client.extend({
|
||||
},
|
||||
on_hashchange: function(event) {
|
||||
var self = this;
|
||||
var state = event.getState(true);
|
||||
if (!_.isEqual(this._current_state, state)) {
|
||||
var stringstate = event.getState(false);
|
||||
if (!_.isEqual(this._current_state, stringstate)) {
|
||||
var state = event.getState(true);
|
||||
if(!state.action && state.menu_id) {
|
||||
self.menu.has_been_loaded.done(function() {
|
||||
self.menu.do_reload().done(function() {
|
||||
@@ -1409,13 +1414,13 @@ instance.web.WebClient = instance.web.Client.extend({
|
||||
this.action_manager.do_load_state(state, !!this._current_state);
|
||||
}
|
||||
}
|
||||
this._current_state = state;
|
||||
this._current_state = stringstate;
|
||||
},
|
||||
do_push_state: function(state) {
|
||||
this.set_title(state.title);
|
||||
delete state.title;
|
||||
var url = '#' + $.param(state);
|
||||
this._current_state = _.clone(state);
|
||||
this._current_state = $.deparam($.param(state), false); // stringify all values
|
||||
$.bbq.pushState(url);
|
||||
this.trigger('state_pushed', state);
|
||||
},
|
||||
@@ -1425,9 +1430,10 @@ instance.web.WebClient = instance.web.Client.extend({
|
||||
.then(function (result) {
|
||||
return self.action_mutex.exec(function() {
|
||||
if (options.needaction) {
|
||||
result.context = new instance.web.CompoundContext(
|
||||
result.context,
|
||||
{search_default_message_unread: true});
|
||||
result.context = new instance.web.CompoundContext(result.context, {
|
||||
search_default_message_unread: true,
|
||||
search_disable_custom_filters: true,
|
||||
});
|
||||
}
|
||||
var completed = $.Deferred();
|
||||
$.when(self.action_manager.do_action(result, {
|
||||
|
||||
@@ -228,6 +228,38 @@ instance.web.ParentedMixin = {
|
||||
isDestroyed : function() {
|
||||
return this.__parentedDestroyed;
|
||||
},
|
||||
/**
|
||||
Utility method to only execute asynchronous actions if the current
|
||||
object has not been destroyed.
|
||||
|
||||
@param {Promise} promise The promise representing the asynchronous action.
|
||||
@param {bool} reject Defaults to false. If true, the returned promise will be
|
||||
rejected with no arguments if the current object is destroyed. If false,
|
||||
the returned promise will never be resolved nor rejected.
|
||||
@returns {Promise} A promise that will mirror the given promise if everything goes
|
||||
fine but will either be rejected with no arguments or never resolved if the
|
||||
current object is destroyed.
|
||||
*/
|
||||
alive: function(promise, reject) {
|
||||
var def = $.Deferred();
|
||||
var self = this;
|
||||
promise.done(function() {
|
||||
if (! self.isDestroyed()) {
|
||||
if (! reject)
|
||||
def.resolve.apply(def, arguments);
|
||||
else
|
||||
def.reject();
|
||||
}
|
||||
}).fail(function() {
|
||||
if (! self.isDestroyed()) {
|
||||
if (! reject)
|
||||
def.reject.apply(def, arguments);
|
||||
else
|
||||
def.reject();
|
||||
}
|
||||
});
|
||||
return def.promise();
|
||||
},
|
||||
/**
|
||||
* Inform the object it should destroy itself, releasing any
|
||||
* resource it could have reserved.
|
||||
@@ -495,16 +527,7 @@ instance.web.Controller = instance.web.Class.extend(instance.web.PropertiesMixin
|
||||
return false;
|
||||
},
|
||||
rpc: function(url, data, options) {
|
||||
var def = $.Deferred();
|
||||
var self = this;
|
||||
instance.session.rpc(url, data, options).done(function() {
|
||||
if (!self.isDestroyed())
|
||||
def.resolve.apply(def, arguments);
|
||||
}).fail(function() {
|
||||
if (!self.isDestroyed())
|
||||
def.reject.apply(def, arguments);
|
||||
});
|
||||
return def.promise();
|
||||
return this.alive(instance.session.rpc(url, data, options));
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -690,7 +690,7 @@ instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.Sea
|
||||
return filter.user_id && filter.is_default;
|
||||
});
|
||||
if (personal_filter) {
|
||||
this.custom_filters.enable_filter(personal_filter, true);
|
||||
this.custom_filters.toggle_filter(personal_filter, true);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -698,7 +698,7 @@ instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.Sea
|
||||
return !filter.user_id && filter.is_default;
|
||||
});
|
||||
if (global_filter) {
|
||||
this.custom_filters.enable_filter(global_filter, true);
|
||||
this.custom_filters.toggle_filter(global_filter, true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1466,12 +1466,15 @@ instance.web.search.ManyToOneField = instance.web.search.CharField.extend({
|
||||
},
|
||||
complete: function (needle) {
|
||||
var self = this;
|
||||
// TODO: context
|
||||
// FIXME: "concurrent" searches (multiple requests, mis-ordered responses)
|
||||
var context = instance.web.pyeval.eval(
|
||||
'contexts', [this.view.dataset.get_context()]);
|
||||
return this.model.call('name_search', [], {
|
||||
name: needle,
|
||||
args: instance.web.pyeval.eval(
|
||||
'domains', this.attrs.domain ? [this.attrs.domain] : [], context),
|
||||
limit: 8,
|
||||
context: {}
|
||||
context: context
|
||||
}).then(function (results) {
|
||||
if (_.isEmpty(results)) { return null; }
|
||||
return [{label: self.attrs.string}].concat(
|
||||
@@ -1541,6 +1544,9 @@ instance.web.search.CustomFilters = instance.web.search.Input.extend({
|
||||
})
|
||||
.on('reset', this.proxy('clear_selection'));
|
||||
this.$el.on('submit', 'form', this.proxy('save_current'));
|
||||
this.$el.on('click', 'input[type=checkbox]', function() {
|
||||
$(this).siblings('input[type=checkbox]').prop('checked', false);
|
||||
});
|
||||
this.$el.on('click', 'h4', function () {
|
||||
self.$el.toggleClass('oe_opened');
|
||||
});
|
||||
@@ -1591,6 +1597,7 @@ instance.web.search.CustomFilters = instance.web.search.Input.extend({
|
||||
get_groupby: function () { return [filter.context]; },
|
||||
get_domain: function () { return filter.domain; }
|
||||
},
|
||||
_id: filter['id'],
|
||||
is_custom_filter: true,
|
||||
values: [{label: filter.name, value: null}]
|
||||
};
|
||||
@@ -1632,10 +1639,18 @@ instance.web.search.CustomFilters = instance.web.search.Input.extend({
|
||||
}
|
||||
|
||||
$filter.unbind('click').click(function () {
|
||||
self.enable_filter(filter);
|
||||
self.toggle_filter(filter);
|
||||
});
|
||||
},
|
||||
enable_filter: function (filter, preventSearch) {
|
||||
toggle_filter: function (filter, preventSearch) {
|
||||
var current = this.view.query.find(function (facet) {
|
||||
return facet.get('_id') === filter.id;
|
||||
});
|
||||
if (current) {
|
||||
this.view.query.remove(current);
|
||||
this.$filters[this.key_for(filter)].removeClass('oe_selected');
|
||||
return;
|
||||
}
|
||||
this.view.query.reset([this.facet_for(filter)], {
|
||||
preventSearch: preventSearch || false});
|
||||
this.$filters[this.key_for(filter)].addClass('oe_selected');
|
||||
@@ -1800,6 +1815,7 @@ instance.web.search.ExtendedSearchProposition = instance.web.Widget.extend(/** @
|
||||
template: 'SearchView.extended_search.proposition',
|
||||
events: {
|
||||
'change .searchview_extended_prop_field': 'changed',
|
||||
'change .searchview_extended_prop_op': 'operator_changed',
|
||||
'click .searchview_extended_delete_prop': function (e) {
|
||||
e.stopPropagation();
|
||||
this.getParent().remove_proposition(this);
|
||||
@@ -1831,6 +1847,17 @@ instance.web.search.ExtendedSearchProposition = instance.web.Widget.extend(/** @
|
||||
this.select_field(_.detect(this.fields, function(x) {return x.name == nval;}));
|
||||
}
|
||||
},
|
||||
operator_changed: function (e) {
|
||||
var $value = this.$('.searchview_extended_prop_value');
|
||||
switch ($(e.target).val()) {
|
||||
case '∃':
|
||||
case '∄':
|
||||
$value.hide();
|
||||
break;
|
||||
default:
|
||||
$value.show();
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Selects the provided field object
|
||||
*
|
||||
@@ -1859,7 +1886,7 @@ instance.web.search.ExtendedSearchProposition = instance.web.Widget.extend(/** @
|
||||
.text(String(operator.text))
|
||||
.appendTo(self.$('.searchview_extended_prop_op'));
|
||||
});
|
||||
var $value_loc = this.$('.searchview_extended_prop_value').empty();
|
||||
var $value_loc = this.$('.searchview_extended_prop_value').show().empty();
|
||||
this.value.appendTo($value_loc);
|
||||
|
||||
},
|
||||
@@ -1867,19 +1894,12 @@ instance.web.search.ExtendedSearchProposition = instance.web.Widget.extend(/** @
|
||||
if ( this.attrs.selected == null)
|
||||
return null;
|
||||
var field = this.attrs.selected;
|
||||
var op = this.$('.searchview_extended_prop_op')[0];
|
||||
var operator = op.options[op.selectedIndex];
|
||||
var op_select = this.$('.searchview_extended_prop_op')[0];
|
||||
var operator = op_select.options[op_select.selectedIndex];
|
||||
|
||||
return {
|
||||
label: _.str.sprintf(_t('%(field)s %(operator)s "%(value)s"'), {
|
||||
field: field.string,
|
||||
// According to spec, HTMLOptionElement#label should return
|
||||
// HTMLOptionElement#text when not defined/empty, but it does
|
||||
// not in older Webkit (between Safari 5.1.5 and Chrome 17) and
|
||||
// Gecko (pre Firefox 7) browsers, so we need a manual fallback
|
||||
// for those
|
||||
operator: operator.label || operator.text,
|
||||
value: this.value}),
|
||||
value: [field.name, operator.value, this.value.get_value()]
|
||||
label: this.value.get_label(field, operator),
|
||||
value: this.value.get_domain(field, operator),
|
||||
};
|
||||
}
|
||||
});
|
||||
@@ -1889,6 +1909,37 @@ instance.web.search.ExtendedSearchProposition.Field = instance.web.Widget.extend
|
||||
this._super(parent);
|
||||
this.field = field;
|
||||
},
|
||||
get_label: function (field, operator) {
|
||||
var format;
|
||||
switch (operator.value) {
|
||||
case '∃': case '∄': format = _t('%(field)s %(operator)s'); break;
|
||||
default: format = _t('%(field)s %(operator)s "%(value)s"'); break;
|
||||
}
|
||||
return this.format_label(format, field, operator);
|
||||
},
|
||||
format_label: function (format, field, operator) {
|
||||
return _.str.sprintf(format, {
|
||||
field: field.string,
|
||||
// According to spec, HTMLOptionElement#label should return
|
||||
// HTMLOptionElement#text when not defined/empty, but it does
|
||||
// not in older Webkit (between Safari 5.1.5 and Chrome 17) and
|
||||
// Gecko (pre Firefox 7) browsers, so we need a manual fallback
|
||||
// for those
|
||||
operator: operator.label || operator.text,
|
||||
value: this
|
||||
});
|
||||
},
|
||||
get_domain: function (field, operator) {
|
||||
switch (operator.value) {
|
||||
case '∃': return this.make_domain(field.name, '!=', false);
|
||||
case '∄': return this.make_domain(field.name, '=', false);
|
||||
default: return this.make_domain(
|
||||
field.name, operator.value, this.get_value());
|
||||
}
|
||||
},
|
||||
make_domain: function (field, operator, value) {
|
||||
return [field, operator, value];
|
||||
},
|
||||
/**
|
||||
* Returns a human-readable version of the value, in case the "logical"
|
||||
* and the "semantic" values of a field differ (as for selection fields,
|
||||
@@ -1908,7 +1959,9 @@ instance.web.search.ExtendedSearchProposition.Char = instance.web.search.Extende
|
||||
{value: "ilike", text: _lt("contains")},
|
||||
{value: "not ilike", text: _lt("doesn't contain")},
|
||||
{value: "=", text: _lt("is equal to")},
|
||||
{value: "!=", text: _lt("is not equal to")}
|
||||
{value: "!=", text: _lt("is not equal to")},
|
||||
{value: "∃", text: _lt("is set")},
|
||||
{value: "∄", text: _lt("is not set")}
|
||||
],
|
||||
get_value: function() {
|
||||
return this.$el.val();
|
||||
@@ -1922,7 +1975,9 @@ instance.web.search.ExtendedSearchProposition.DateTime = instance.web.search.Ext
|
||||
{value: ">", text: _lt("greater than")},
|
||||
{value: "<", text: _lt("less than")},
|
||||
{value: ">=", text: _lt("greater or equal than")},
|
||||
{value: "<=", text: _lt("less or equal than")}
|
||||
{value: "<=", text: _lt("less or equal than")},
|
||||
{value: "∃", text: _lt("is set")},
|
||||
{value: "∄", text: _lt("is not set")}
|
||||
],
|
||||
/**
|
||||
* Date widgets live in view_form which is not yet loaded when this is
|
||||
@@ -1956,7 +2011,9 @@ instance.web.search.ExtendedSearchProposition.Integer = instance.web.search.Exte
|
||||
{value: ">", text: _lt("greater than")},
|
||||
{value: "<", text: _lt("less than")},
|
||||
{value: ">=", text: _lt("greater or equal than")},
|
||||
{value: "<=", text: _lt("less or equal than")}
|
||||
{value: "<=", text: _lt("less or equal than")},
|
||||
{value: "∃", text: _lt("is set")},
|
||||
{value: "∄", text: _lt("is not set")}
|
||||
],
|
||||
toString: function () {
|
||||
return this.$el.val();
|
||||
@@ -1981,7 +2038,9 @@ instance.web.search.ExtendedSearchProposition.Float = instance.web.search.Extend
|
||||
{value: ">", text: _lt("greater than")},
|
||||
{value: "<", text: _lt("less than")},
|
||||
{value: ">=", text: _lt("greater or equal than")},
|
||||
{value: "<=", text: _lt("less or equal than")}
|
||||
{value: "<=", text: _lt("less or equal than")},
|
||||
{value: "∃", text: _lt("is set")},
|
||||
{value: "∄", text: _lt("is not set")}
|
||||
],
|
||||
toString: function () {
|
||||
return this.$el.val();
|
||||
@@ -1999,7 +2058,9 @@ instance.web.search.ExtendedSearchProposition.Selection = instance.web.search.Ex
|
||||
template: 'SearchView.extended_search.proposition.selection',
|
||||
operators: [
|
||||
{value: "=", text: _lt("is")},
|
||||
{value: "!=", text: _lt("is not")}
|
||||
{value: "!=", text: _lt("is not")},
|
||||
{value: "∃", text: _lt("is set")},
|
||||
{value: "∄", text: _lt("is not set")}
|
||||
],
|
||||
toString: function () {
|
||||
var select = this.$el[0];
|
||||
@@ -2016,7 +2077,10 @@ instance.web.search.ExtendedSearchProposition.Boolean = instance.web.search.Exte
|
||||
{value: "=", text: _lt("is true")},
|
||||
{value: "!=", text: _lt("is false")}
|
||||
],
|
||||
toString: function () { return ''; },
|
||||
get_label: function (field, operator) {
|
||||
return this.format_label(
|
||||
_t('%(field)s %(operator)s'), field, operator);
|
||||
},
|
||||
get_value: function() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -247,13 +247,11 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
|
||||
|
||||
do_load_state: function(state, warm) {
|
||||
if (state.id && this.datarecord.id != state.id) {
|
||||
if (!this.dataset.get_id_index(state.id)) {
|
||||
if (this.dataset.get_id_index(state.id) === null) {
|
||||
this.dataset.ids.push(state.id);
|
||||
}
|
||||
this.dataset.select_id(state.id);
|
||||
if (warm) {
|
||||
this.do_show();
|
||||
}
|
||||
this.do_show({ reload: warm });
|
||||
}
|
||||
},
|
||||
/**
|
||||
@@ -511,9 +509,13 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
|
||||
var on_change = widget.node.attrs.on_change;
|
||||
if (on_change) {
|
||||
var change_spec = self.parse_on_change(on_change, widget);
|
||||
var id = [self.datarecord.id == null ? [] : [self.datarecord.id]];
|
||||
def = new instance.web.Model(self.dataset.model).call(
|
||||
change_spec.method, id.concat(change_spec.args));
|
||||
var ids = [];
|
||||
if (self.datarecord.id && !instance.web.BufferedDataSet.virtual_id_regex.test(self.datarecord.id)) {
|
||||
// In case of a o2m virtual id, we should pass an empty ids list
|
||||
ids.push(self.datarecord.id);
|
||||
}
|
||||
def = self.alive(new instance.web.Model(self.dataset.model).call(
|
||||
change_spec.method, [ids].concat(change_spec.args)));
|
||||
} else {
|
||||
def = $.when({});
|
||||
}
|
||||
@@ -531,9 +533,9 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
|
||||
var condition = fieldname + '=' + value_;
|
||||
|
||||
if (value_) {
|
||||
return new instance.web.Model('ir.values').call(
|
||||
return self.alive(new instance.web.Model('ir.values').call(
|
||||
'get_defaults', [self.model, condition]
|
||||
).then(function (results) {
|
||||
)).then(function (results) {
|
||||
if (!results.length) {
|
||||
return response;
|
||||
}
|
||||
@@ -1191,6 +1193,10 @@ instance.web.form.FormRenderingEngine = instance.web.form.FormRenderingEngineInt
|
||||
$('button', doc).each(function() {
|
||||
$(this).attr('data-button-type', $(this).attr('type')).attr('type', 'button');
|
||||
});
|
||||
// IE's html parser is also a css parser. How convenient...
|
||||
$('board', doc).each(function() {
|
||||
$(this).attr('layout', $(this).attr('style'));
|
||||
});
|
||||
return $('<div class="oe_form"/>').append(instance.web.xml_to_str(doc));
|
||||
},
|
||||
render_to: function($target) {
|
||||
@@ -2327,7 +2333,7 @@ instance.web.form.FieldUrl = instance.web.form.FieldChar.extend({
|
||||
this._super();
|
||||
} else {
|
||||
var tmp = this.get('value');
|
||||
var s = /(\w+):(.+)/.exec(tmp);
|
||||
var s = /(\w+):(.+)|^\.{0,2}\//.exec(tmp);
|
||||
if (!s) {
|
||||
tmp = "http://" + this.get('value');
|
||||
}
|
||||
@@ -2376,6 +2382,7 @@ instance.web.DateTimeWidget = instance.web.Widget.extend({
|
||||
type_of_date: "datetime",
|
||||
events: {
|
||||
'change .oe_datepicker_master': 'change_datetime',
|
||||
'dragstart img.oe_datepicker_trigger': function () { return false; },
|
||||
},
|
||||
init: function(parent) {
|
||||
this._super(parent);
|
||||
@@ -2395,6 +2402,11 @@ instance.web.DateTimeWidget = instance.web.Widget.extend({
|
||||
showButtonPanel: true,
|
||||
firstDay: Date.CultureInfo.firstDayOfWeek
|
||||
});
|
||||
// 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();
|
||||
@@ -2970,7 +2982,9 @@ instance.web.form.FieldMany2One = instance.web.form.AbstractField.extend(instanc
|
||||
case $.ui.keyCode.DOWN:
|
||||
e.stopPropagation();
|
||||
}
|
||||
}
|
||||
},
|
||||
'dragstart .oe_m2o_drop_down_button img': function () { return false; },
|
||||
'dragstart .oe_m2o_cm_button': function () { return false; }
|
||||
},
|
||||
init: function(field_manager, node) {
|
||||
this._super(field_manager, node);
|
||||
@@ -3060,9 +3074,9 @@ instance.web.form.FieldMany2One = instance.web.form.AbstractField.extend(instanc
|
||||
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.focus();
|
||||
self.$input.autocomplete("close");
|
||||
} else {
|
||||
if (self.get("value") && ! self.floating) {
|
||||
self.$input.autocomplete("search", "");
|
||||
@@ -3071,6 +3085,15 @@ instance.web.form.FieldMany2One = instance.web.form.AbstractField.extend(instanc
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Autocomplete close on dialog content scroll
|
||||
var close_autocomplete = _.debounce(function() {
|
||||
if (self.$input.autocomplete("widget").is(":visible")) {
|
||||
self.$input.autocomplete("close");
|
||||
}
|
||||
}, 50);
|
||||
this.$input.closest(".ui-dialog .ui-dialog-content").on('scroll', this, close_autocomplete);
|
||||
|
||||
self.ed_def = $.Deferred();
|
||||
self.uned_def = $.Deferred();
|
||||
var ed_delay = 200;
|
||||
@@ -4107,6 +4130,13 @@ instance.web.form.FieldMany2ManyTags = instance.web.form.AbstractField.extend(in
|
||||
focus: function () {
|
||||
this.$text[0].focus();
|
||||
},
|
||||
set_dimensions: function (height, width) {
|
||||
this._super(height, width);
|
||||
this.$("textarea").css({
|
||||
width: width,
|
||||
minHeight: height
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
@@ -4463,6 +4493,7 @@ instance.web.form.AbstractFormPopup = instance.web.Widget.extend({
|
||||
* options:
|
||||
* -readonly: only applicable when not in creation mode, default to false
|
||||
* - alternative_form_view
|
||||
* - view_id
|
||||
* - write_function
|
||||
* - read_function
|
||||
* - create_function
|
||||
@@ -4529,7 +4560,7 @@ instance.web.form.AbstractFormPopup = instance.web.Widget.extend({
|
||||
_.extend(options, {
|
||||
$buttons: this.$buttonpane,
|
||||
});
|
||||
this.view_form = new instance.web.FormView(this, this.dataset, false, options);
|
||||
this.view_form = new instance.web.FormView(this, this.dataset, this.options.view_id || false, options);
|
||||
if (this.options.alternative_form_view) {
|
||||
this.view_form.set_embedded_view(this.options.alternative_form_view);
|
||||
}
|
||||
@@ -4558,6 +4589,7 @@ instance.web.form.AbstractFormPopup = instance.web.Widget.extend({
|
||||
});
|
||||
var $cbutton = self.$buttonpane.find(".oe_abstractformpopup-form-close");
|
||||
$cbutton.click(function() {
|
||||
self.view_form.trigger('on_button_cancel');
|
||||
self.check_exit();
|
||||
});
|
||||
self.view_form.do_show();
|
||||
@@ -5236,8 +5268,20 @@ instance.web.form.FieldStatus = instance.web.form.AbstractField.extend({
|
||||
this.options.clickable = this.options.clickable || (this.node.attrs || {}).clickable || false;
|
||||
this.options.visible = this.options.visible || (this.node.attrs || {}).statusbar_visible || false;
|
||||
this.set({value: false});
|
||||
this.selection = [];
|
||||
this.set("selection", []);
|
||||
this.selection_dm = new instance.web.DropMisordered();
|
||||
},
|
||||
start: function() {
|
||||
this.field_manager.on("view_content_has_changed", this, this.calc_domain);
|
||||
this.calc_domain();
|
||||
this.on("change:value", this, this.get_selection);
|
||||
this.on("change:evaluated_selection_domain", this, this.get_selection);
|
||||
this.get_selection();
|
||||
this.on("change:selection", this, function() {
|
||||
this.selection = this.get("selection");
|
||||
this.render_value();
|
||||
});
|
||||
if (this.options.clickable) {
|
||||
this.$el.on('click','li',this.on_click_stage);
|
||||
}
|
||||
@@ -5254,15 +5298,20 @@ instance.web.form.FieldStatus = instance.web.form.AbstractField.extend({
|
||||
},
|
||||
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);
|
||||
var colors = JSON.parse((self.node.attrs || {}).statusbar_colors || "{}");
|
||||
var color = colors[self.get('value')];
|
||||
if (color) {
|
||||
self.$("oe_active").css("color", color);
|
||||
}
|
||||
},
|
||||
calc_domain: function() {
|
||||
var d = instance.web.pyeval.eval('domain', this.build_domain());
|
||||
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], ...]
|
||||
@@ -5271,32 +5320,37 @@ instance.web.form.FieldStatus = instance.web.form.AbstractField.extend({
|
||||
*/
|
||||
get_selection: function() {
|
||||
var self = this;
|
||||
self.selection = [];
|
||||
if (this.field.type == "many2one") {
|
||||
var domain = [];
|
||||
if(!_.isEmpty(this.field.domain) || !_.isEmpty(this.node.attrs.domain)) {
|
||||
var d = instance.web.pyeval.eval('domain', self.build_domain());
|
||||
domain = ['|', ['id', '=', self.get('value')]].concat(d);
|
||||
}
|
||||
var ds = new instance.web.DataSetSearch(this, this.field.relation, self.build_context(), domain);
|
||||
return ds.read_slice(['name'], {}).then(function (records) {
|
||||
for(var i = 0; i < records.length; i++) {
|
||||
self.selection.push([records[i].id, records[i].name]);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// For field type selection filter values according to
|
||||
// statusbar_visible attribute of the field. For example:
|
||||
// statusbar_visible="draft,open".
|
||||
var selection = this.field.selection;
|
||||
for(var i=0; i < selection.length; i++) {
|
||||
var key = selection[i][0];
|
||||
if(key == this.get('value') || !this.options.visible || this.options.visible.indexOf(key) != -1) {
|
||||
this.selection.push(selection[i]);
|
||||
var selection = [];
|
||||
|
||||
var calculation = _.bind(function() {
|
||||
if (this.field.type == "many2one") {
|
||||
var domain = [];
|
||||
var ds = new instance.web.DataSetSearch(this, this.field.relation,
|
||||
self.build_context(), this.get("evaluated_selection_domain"));
|
||||
return ds.read_slice(['name'], {}).then(function (records) {
|
||||
for(var i = 0; i < records.length; i++) {
|
||||
selection.push([records[i].id, records[i].name]);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// For field type selection filter values according to
|
||||
// statusbar_visible attribute of the field. For example:
|
||||
// statusbar_visible="draft,open".
|
||||
var select = this.field.selection;
|
||||
for(var i=0; i < select.length; i++) {
|
||||
var key = select[i][0];
|
||||
if(key == this.get('value') || !this.options.visible || this.options.visible.indexOf(key) != -1) {
|
||||
selection.push(select[i]);
|
||||
}
|
||||
}
|
||||
return $.when();
|
||||
}
|
||||
return $.when();
|
||||
}
|
||||
}, this);
|
||||
this.selection_dm.add(calculation()).then(function () {
|
||||
if (! _.isEqual(selection, self.get("selection"))) {
|
||||
self.set("selection", selection);
|
||||
}
|
||||
});
|
||||
},
|
||||
on_click_stage: function (ev) {
|
||||
var self = this;
|
||||
@@ -5340,8 +5394,8 @@ instance.web.form.FieldMonetary = instance.web.form.FieldFloat.extend({
|
||||
this.set({"currency_info": null});
|
||||
return;
|
||||
}
|
||||
return this.ci_dm.add(new instance.web.Model("res.currency").query(["symbol", "position"])
|
||||
.filter([["id", "=", self.get("currency")]]).first()).then(function(res) {
|
||||
return this.ci_dm.add(self.alive(new instance.web.Model("res.currency").query(["symbol", "position"])
|
||||
.filter([["id", "=", self.get("currency")]]).first())).then(function(res) {
|
||||
self.set({"currency_info": res});
|
||||
});
|
||||
},
|
||||
|
||||
@@ -1186,7 +1186,7 @@ instance.web.ListView.List = instance.web.Class.extend( /** @lends instance.web.
|
||||
}
|
||||
});
|
||||
instance.web.ListView.Groups = instance.web.Class.extend( /** @lends instance.web.ListView.Groups# */{
|
||||
passtrough_events: 'action deleted row_link',
|
||||
passthrough_events: 'action deleted row_link',
|
||||
/**
|
||||
* Grouped display for the ListView. Handles basic DOM events and interacts
|
||||
* with the :js:class:`~DataGroup` bound to it.
|
||||
@@ -1406,7 +1406,7 @@ instance.web.ListView.Groups = instance.web.Class.extend( /** @lends instance.we
|
||||
// can have selections spanning multiple links
|
||||
var selection = self.get_selection();
|
||||
$this.trigger(e, [selection.ids, selection.records]);
|
||||
}).bind(this.passtrough_events, function (e) {
|
||||
}).bind(this.passthrough_events, function (e) {
|
||||
// additional positional parameters are provided to trigger as an
|
||||
// Array, following the event type or event object, but are
|
||||
// provided to the .bind event handler as *args.
|
||||
@@ -2212,7 +2212,7 @@ instance.web.list.Binary = instance.web.list.Column.extend({
|
||||
if (value && value.substr(0, 10).indexOf(' ') == -1) {
|
||||
download_url = "data:application/octet-stream;base64," + value;
|
||||
} else {
|
||||
download_url = this.session.url('/web/binary/saveas', {model: options.model, field: this.id, id: options.id});
|
||||
download_url = instance.session.url('/web/binary/saveas', {model: options.model, field: this.id, id: options.id});
|
||||
if (this.filename) {
|
||||
download_url += '&filename_field=' + this.filename;
|
||||
}
|
||||
|
||||
@@ -132,6 +132,15 @@ openerp.web.list_editable = function (instance) {
|
||||
var self = this;
|
||||
// tree/@editable takes priority on everything else if present.
|
||||
var result = this._super(data, grouped);
|
||||
|
||||
// In case current editor was started previously, also has to run
|
||||
// when toggling from editable to non-editable in case form widgets
|
||||
// have setup global behaviors expecting themselves to exist
|
||||
// somehow.
|
||||
this.editor.destroy();
|
||||
// Editor is not restartable due to formview not being restartable
|
||||
this.editor = this.make_editor();
|
||||
|
||||
if (this.editable()) {
|
||||
this.$el.addClass('oe_list_editable');
|
||||
// FIXME: any hook available to ensure this is only done once?
|
||||
@@ -143,10 +152,6 @@ openerp.web.list_editable = function (instance) {
|
||||
e.preventDefault();
|
||||
self.cancel_edition();
|
||||
});
|
||||
this.editor.destroy();
|
||||
// Editor is not restartable due to formview not being
|
||||
// restartable
|
||||
this.editor = this.make_editor();
|
||||
var editor_ready = this.editor.prependTo(this.$el)
|
||||
.done(this.proxy('setup_events'));
|
||||
|
||||
@@ -795,7 +800,7 @@ openerp.web.list_editable = function (instance) {
|
||||
});
|
||||
|
||||
instance.web.ListView.Groups.include(/** @lends instance.web.ListView.Groups# */{
|
||||
passtrough_events: instance.web.ListView.Groups.prototype.passtrough_events + " edit saved",
|
||||
passthrough_events: instance.web.ListView.Groups.prototype.passthrough_events + " edit saved",
|
||||
get_row_for: function (record) {
|
||||
return _(this.children).chain()
|
||||
.invoke('get_row_for', record)
|
||||
|
||||
@@ -190,6 +190,18 @@ instance.web.ActionManager = instance.web.Widget.extend({
|
||||
});
|
||||
state = _.extend(params || {}, state);
|
||||
}
|
||||
if (this.inner_action.context) {
|
||||
var active_id = this.inner_action.context.active_id;
|
||||
if (active_id) {
|
||||
state["active_id"] = active_id;
|
||||
}
|
||||
var active_ids = this.inner_action.context.active_ids;
|
||||
if (active_ids && !(active_ids.length === 1 && active_ids[0] === active_id)) {
|
||||
// We don't push active_ids if it's a single element array containing the active_id
|
||||
// This makes the url shorter in most cases.
|
||||
state["active_ids"] = this.inner_action.context.active_ids.join(',');
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!this.dialog) {
|
||||
this.getParent().do_push_state(state);
|
||||
@@ -212,8 +224,22 @@ instance.web.ActionManager = instance.web.Widget.extend({
|
||||
} else {
|
||||
var run_action = (!this.inner_widget || !this.inner_widget.action) || this.inner_widget.action.id !== state.action;
|
||||
if (run_action) {
|
||||
var add_context = {};
|
||||
if (state.active_id) {
|
||||
add_context.active_id = state.active_id;
|
||||
}
|
||||
if (state.active_ids) {
|
||||
// The jQuery BBQ plugin does some parsing on values that are valid integers.
|
||||
// It means that if there's only one item, it will do parseInt() on it,
|
||||
// otherwise it will keep the comma seperated list as string.
|
||||
add_context.active_ids = state.active_ids.toString().split(',').map(function(id) {
|
||||
return parseInt(id, 10) || id;
|
||||
});
|
||||
} else if (state.active_id) {
|
||||
add_context.active_ids = [state.active_id];
|
||||
}
|
||||
this.null_action();
|
||||
action_loaded = this.do_action(state.action);
|
||||
action_loaded = this.do_action(state.action, { additional_context: add_context });
|
||||
$.when(action_loaded || null).done(function() {
|
||||
instance.webclient.menu.has_been_loaded.done(function() {
|
||||
if (self.inner_action && self.inner_action.id) {
|
||||
@@ -249,12 +275,25 @@ instance.web.ActionManager = instance.web.Widget.extend({
|
||||
}
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Execute an OpenERP action
|
||||
*
|
||||
* @param {Number|String|Object} Can be either an action id, a client action or an action descriptor.
|
||||
* @param {Object} [options]
|
||||
* @param {Boolean} [options.clear_breadcrumbs=false] Clear the breadcrumbs history list
|
||||
* @param {Function} [options.on_reverse_breadcrumb] Callback to be executed whenever an anterior breadcrumb item is clicked on.
|
||||
* @param {Function} [options.on_close] Callback to be executed when the dialog is closed (only relevant for target=new actions)
|
||||
* @param {Function} [options.action_menu_id] Manually set the menu id on the fly.
|
||||
* @param {Object} [options.additional_context] Additional context to be merged with the action's context.
|
||||
* @return {jQuery.Deferred} Action loaded
|
||||
*/
|
||||
do_action: function(action, options) {
|
||||
options = _.defaults(options || {}, {
|
||||
clear_breadcrumbs: false,
|
||||
on_reverse_breadcrumb: function() {},
|
||||
on_close: function() {},
|
||||
action_menu_id: null,
|
||||
additional_context: {},
|
||||
});
|
||||
if (action === false) {
|
||||
action = { type: 'ir.actions.act_window_close' };
|
||||
@@ -269,9 +308,13 @@ instance.web.ActionManager = instance.web.Widget.extend({
|
||||
}
|
||||
|
||||
// Ensure context & domain are evaluated and can be manipulated/used
|
||||
if (action.context) {
|
||||
action.context = instance.web.pyeval.eval(
|
||||
'context', action.context);
|
||||
var ncontext = new instance.web.CompoundContext(options.additional_context, action.context || {});
|
||||
action.context = instance.web.pyeval.eval('context', ncontext);
|
||||
if (action.context.active_id || action.context.active_ids) {
|
||||
// Here we assume that when an `active_id` or `active_ids` is used
|
||||
// in the context, we are in a `related` action, so we disable the
|
||||
// searchview's default custom filters.
|
||||
action.context.search_disable_custom_filters = true;
|
||||
}
|
||||
if (action.domain) {
|
||||
action.domain = instance.web.pyeval.eval(
|
||||
@@ -539,7 +582,7 @@ instance.web.ViewManager = instance.web.Widget.extend({
|
||||
_.each(_.keys(self.views), function(view_name) {
|
||||
var controller = self.views[view_name].controller;
|
||||
if (controller) {
|
||||
var container = self.$el.find(".oe_view_manager_view_" + view_name + ":first");
|
||||
var container = self.$el.find("> .oe_view_manager_body > .oe_view_manager_view_" + view_name);
|
||||
if (view_name === view_type) {
|
||||
container.show();
|
||||
controller.do_show(view_options || {});
|
||||
@@ -582,7 +625,7 @@ instance.web.ViewManager = instance.web.Widget.extend({
|
||||
controller.on('switch_mode', self, this.switch_mode);
|
||||
controller.on('previous_view', self, this.prev_view);
|
||||
|
||||
var container = this.$el.find(".oe_view_manager_view_" + view_type);
|
||||
var container = this.$el.find("> .oe_view_manager_body > .oe_view_manager_view_" + view_type);
|
||||
var view_promise = controller.appendTo(container);
|
||||
this.views[view_type].controller = controller;
|
||||
this.views[view_type].deferred.resolve(view_type);
|
||||
@@ -597,6 +640,12 @@ instance.web.ViewManager = instance.web.Widget.extend({
|
||||
self.trigger("controller_inited",view_type,controller);
|
||||
});
|
||||
},
|
||||
/**
|
||||
* @returns {Number|Boolean} the view id of the given type, false if not found
|
||||
*/
|
||||
get_view_id: function(view_type) {
|
||||
return this.views[view_type] && this.views[view_type].view_id || false;
|
||||
},
|
||||
set_title: function(title) {
|
||||
this.$el.find('.oe_view_title_text:first').text(title);
|
||||
},
|
||||
@@ -953,10 +1002,11 @@ instance.web.ViewManagerAction = instance.web.ViewManager.extend({
|
||||
});
|
||||
},
|
||||
do_create_view: function(view_type) {
|
||||
var r = this._super.apply(this, arguments);
|
||||
var view = this.views[view_type].controller;
|
||||
view.set({ 'title': this.action.name });
|
||||
return r;
|
||||
var self = this;
|
||||
return this._super.apply(this, arguments).then(function() {
|
||||
var view = self.views[view_type].controller;
|
||||
view.set({ 'title': self.action.name });
|
||||
});
|
||||
},
|
||||
get_action_manager: function() {
|
||||
var cur = this;
|
||||
@@ -1270,11 +1320,6 @@ instance.web.View = instance.web.Widget.extend({
|
||||
active_ids: [record_id],
|
||||
active_model: dataset.model
|
||||
});
|
||||
if (("" + action.context).match(/\bactive_id\b/)) {
|
||||
// Special case: when the context is evaluted using
|
||||
// the active_id, we want to disable the custom filters.
|
||||
ncontext.add({ search_disable_custom_filters: true });
|
||||
}
|
||||
}
|
||||
ncontext.add(action.context || {});
|
||||
action.context = ncontext;
|
||||
@@ -1502,13 +1547,22 @@ instance.web.json_node_to_xml = function(node, human_readable, indent) {
|
||||
}
|
||||
};
|
||||
instance.web.xml_to_str = function(node) {
|
||||
var str = "";
|
||||
if (window.XMLSerializer) {
|
||||
return (new XMLSerializer()).serializeToString(node);
|
||||
str = (new XMLSerializer()).serializeToString(node);
|
||||
} else if (window.ActiveXObject) {
|
||||
return node.xml;
|
||||
str = node.xml;
|
||||
} else {
|
||||
throw new Error(_t("Could not serialize XML"));
|
||||
}
|
||||
// Browsers won't deal with self closing tags except br, hr, input, ...
|
||||
// http://stackoverflow.com/questions/97522/what-are-all-the-valid-self-closing-elements-in-xhtml-as-implemented-by-the-maj
|
||||
//
|
||||
// The following regex is a bit naive but it's ok for the xmlserializer output
|
||||
str = str.replace(/<([a-z]+)([^<>]*)\s*\/\s*>/g, function(match, tag, attrs) {
|
||||
return "<" + tag + attrs + "></" + tag + ">";
|
||||
});
|
||||
return str;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -119,7 +119,7 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label for="db_name">New database name:</label></td>
|
||||
<td><input type="text" name="db_name" class="required" matches="^[a-zA-Z][a-zA-Z0-9_-]+$" autofocus="true"/></td>
|
||||
<td><input type="text" name="db_name" class="required" matches="^[a-zA-Z0-9][a-zA-Z0-9_-]+$" autofocus="true"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label for="demo_data">Load Demonstration data:</label></td>
|
||||
@@ -403,8 +403,9 @@
|
||||
<img class="oe_topbar_avatar" t-att-data-default-src="_s + '/web/static/src/img/user_menu_avatar.png'"/>
|
||||
<span class="oe_topbar_name"/>
|
||||
<ul class="oe_dropdown_menu">
|
||||
<li><a href="#" data-menu="about">About OpenERP</a></li>
|
||||
<li><a href="#" data-menu="settings">Preferences</a></li>
|
||||
<li><a href="#" data-menu="about">About OpenERP</a></li>
|
||||
<li><a href="#" data-menu="help">Help</a></li>
|
||||
<li><a href="#" data-menu="logout">Log out</a></li>
|
||||
</ul>
|
||||
</span>
|
||||
@@ -1299,7 +1300,7 @@
|
||||
<span class='oe_attach_label'>File</span>
|
||||
<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.view.model"/>
|
||||
<input type="hidden" name="id" value="0"/>
|
||||
<input type="hidden" name="session_id" t-att-value="widget.session.session_id"/>
|
||||
|
||||
@@ -318,6 +318,28 @@ openerp.testing.section('defaults', {
|
||||
"facet value should match provided default's selection");
|
||||
});
|
||||
});
|
||||
test("M2O default: value array", {asserts: 2}, function (instance, $s, mock) {
|
||||
var view = {inputs: []}, id = 5;
|
||||
var f = new instance.web.search.ManyToOneField(
|
||||
{attrs: {name: 'dummy', string: 'Dummy'}},
|
||||
{relation: 'dummy.model.name'},
|
||||
view);
|
||||
mock('dummy.model.name:name_get', function (args) {
|
||||
equal(args[0], id);
|
||||
return [[id, "DumDumDum"]];
|
||||
});
|
||||
return f.facet_for_defaults({dummy: [id]})
|
||||
.done(function (facet) {
|
||||
var model = facet;
|
||||
if (!(model instanceof instance.web.search.Facet)) {
|
||||
model = new instance.web.search.Facet(facet);
|
||||
}
|
||||
deepEqual(
|
||||
model.values.toJSON(),
|
||||
[{label: "DumDumDum", value: id}],
|
||||
"should support default as a singleton");
|
||||
});
|
||||
});
|
||||
test("M2O default: value", {asserts: 1}, function (instance, $s, mock) {
|
||||
var view = {inputs: []}, id = 4;
|
||||
var f = new instance.web.search.ManyToOneField(
|
||||
@@ -330,6 +352,15 @@ openerp.testing.section('defaults', {
|
||||
ok(!facet, "an invalid m2o default should yield a non-facet");
|
||||
});
|
||||
});
|
||||
test("M2O default: values", {rpc: false}, function (instance) {
|
||||
var view = {inputs: []};
|
||||
var f = new instance.web.search.ManyToOneField(
|
||||
{attrs: {name: 'dummy', string: 'Dummy'}},
|
||||
{relation: 'dummy.model.name'},
|
||||
view);
|
||||
raises(function () { f.facet_for_defaults({dummy: [6, 7]}) },
|
||||
"should not accept multiple default values");
|
||||
})
|
||||
});
|
||||
openerp.testing.section('completions', {
|
||||
dependencies: ['web.search'],
|
||||
@@ -526,7 +557,7 @@ openerp.testing.section('completions', {
|
||||
return [[42, "choice 1"], [43, "choice @"]];
|
||||
});
|
||||
|
||||
var view = {inputs: []};
|
||||
var view = {inputs: [], dataset: {get_context: function () {}}};
|
||||
var f = new instance.web.search.ManyToOneField(
|
||||
{attrs: {string: 'Dummy'}}, {relation: 'dummy.model'}, view);
|
||||
return f.complete("bob")
|
||||
@@ -555,7 +586,7 @@ openerp.testing.section('completions', {
|
||||
strictEqual(kwargs.name, 'bob');
|
||||
return [];
|
||||
});
|
||||
var view = {inputs: []};
|
||||
var view = {inputs: [], dataset: {get_context: function () {}}};
|
||||
var f = new instance.web.search.ManyToOneField(
|
||||
{attrs: {string: 'Dummy'}}, {relation: 'dummy.model'}, view);
|
||||
return f.complete("bob")
|
||||
@@ -563,6 +594,26 @@ openerp.testing.section('completions', {
|
||||
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");
|
||||
});
|
||||
});
|
||||
openerp.testing.section('search-serialization', {
|
||||
dependencies: ['web.search'],
|
||||
@@ -1038,6 +1089,44 @@ openerp.testing.section('saved_filters', {
|
||||
"should not be checked anymore");
|
||||
});
|
||||
});
|
||||
test('toggling', {asserts: 2}, function (instance, $fix, mock) {
|
||||
var view = makeSearchView(instance);
|
||||
mock('ir.filters:get_filters', function () {
|
||||
return [{name: 'filter name', user_id: 42, id: 1}];
|
||||
});
|
||||
|
||||
return view.appendTo($fix)
|
||||
.done(function () {
|
||||
var $row = $fix.find('.oe_searchview_custom li:first').click();
|
||||
equal(view.query.length, 1, "should have one facet");
|
||||
$row.click();
|
||||
equal(view.query.length, 0, "should have removed facet");
|
||||
});
|
||||
});
|
||||
test('replacement', {asserts: 4}, function (instance, $fix, mock) {
|
||||
var view = makeSearchView(instance);
|
||||
mock('ir.filters:get_filters', function () {
|
||||
return [
|
||||
{name: 'f', user_id: 42, id: 1, context: {'private': 1}},
|
||||
{name: 'f', user_id: false, id: 2, context: {'private': 0}}
|
||||
];
|
||||
});
|
||||
return view.appendTo($fix)
|
||||
.done(function () {
|
||||
$fix.find('.oe_searchview_custom li:eq(0)').click();
|
||||
equal(view.query.length, 1, "should have one facet");
|
||||
deepEqual(
|
||||
view.query.at(0).get('field').get_context(),
|
||||
{'private': 1},
|
||||
"should have selected first filter");
|
||||
$fix.find('.oe_searchview_custom li:eq(1)').click();
|
||||
equal(view.query.length, 1, "should have one facet");
|
||||
deepEqual(
|
||||
view.query.at(0).get('field').get_context(),
|
||||
{'private': 0},
|
||||
"should have selected second filter");
|
||||
});
|
||||
});
|
||||
});
|
||||
openerp.testing.section('advanced', {
|
||||
dependencies: ['web.search'],
|
||||
|
||||
@@ -0,0 +1,217 @@
|
||||
# Korean translation for openerp-web
|
||||
# Copyright (c) 2013 Rosetta Contributors and Canonical Ltd 2013
|
||||
# This file is distributed under the same license as the openerp-web package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2013.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: openerp-web\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2012-12-21 17:06+0000\n"
|
||||
"PO-Revision-Date: 2013-02-26 07:04+0000\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: Korean <ko@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2013-02-27 04:53+0000\n"
|
||||
"X-Generator: Launchpad (build 16506)\n"
|
||||
|
||||
#. module: web_calendar
|
||||
#. openerp-web
|
||||
#: code:addons/web_calendar/static/src/js/calendar.js:153
|
||||
#, python-format
|
||||
msgid "New event"
|
||||
msgstr "신규 이벤트"
|
||||
|
||||
#. module: web_calendar
|
||||
#. openerp-web
|
||||
#: code:addons/web_calendar/static/src/js/calendar.js:156
|
||||
#, python-format
|
||||
msgid "Details"
|
||||
msgstr "상세 내용"
|
||||
|
||||
#. module: web_calendar
|
||||
#. openerp-web
|
||||
#: code:addons/web_calendar/static/src/js/calendar.js:154
|
||||
#, python-format
|
||||
msgid "Save"
|
||||
msgstr "저장"
|
||||
|
||||
#. module: web_calendar
|
||||
#. openerp-web
|
||||
#: code:addons/web_calendar/static/src/js/calendar.js:101
|
||||
#, python-format
|
||||
msgid "Calendar view has a 'date_delay' type != float"
|
||||
msgstr "달력 화면에 'date_delay'유형의 != 플로트가 있습니다"
|
||||
|
||||
#. module: web_calendar
|
||||
#. openerp-web
|
||||
#: code:addons/web_calendar/static/src/js/calendar.js:149
|
||||
#, python-format
|
||||
msgid "Today"
|
||||
msgstr "오늘"
|
||||
|
||||
#. module: web_calendar
|
||||
#. openerp-web
|
||||
#: code:addons/web_calendar/static/src/js/calendar.js:151
|
||||
#, python-format
|
||||
msgid "Week"
|
||||
msgstr "주"
|
||||
|
||||
#. module: web_calendar
|
||||
#. openerp-web
|
||||
#: code:addons/web_calendar/static/src/js/calendar.js:163
|
||||
#, python-format
|
||||
msgid "Full day"
|
||||
msgstr "하루 종일"
|
||||
|
||||
#. module: web_calendar
|
||||
#. openerp-web
|
||||
#: code:addons/web_calendar/static/src/js/calendar.js:161
|
||||
#: code:addons/web_calendar/static/src/js/calendar.js:174
|
||||
#, python-format
|
||||
msgid "Description"
|
||||
msgstr "설명"
|
||||
|
||||
#. module: web_calendar
|
||||
#. openerp-web
|
||||
#: code:addons/web_calendar/static/src/js/calendar.js:160
|
||||
#, python-format
|
||||
msgid "Event will be deleted permanently, are you sure?"
|
||||
msgstr "이벤트가 영구 삭제될 것입니다. 확실하십니까?"
|
||||
|
||||
#. module: web_calendar
|
||||
#. openerp-web
|
||||
#: code:addons/web_calendar/static/src/xml/web_calendar.xml:8
|
||||
#: code:addons/web_calendar/static/src/xml/web_calendar.xml:9
|
||||
#, python-format
|
||||
msgid " "
|
||||
msgstr " "
|
||||
|
||||
#. module: web_calendar
|
||||
#. openerp-web
|
||||
#: code:addons/web_calendar/static/src/js/calendar.js:173
|
||||
#, python-format
|
||||
msgid "Date"
|
||||
msgstr "날짜"
|
||||
|
||||
#. module: web_calendar
|
||||
#. openerp-web
|
||||
#: code:addons/web_calendar/static/src/js/calendar.js:470
|
||||
#, python-format
|
||||
msgid "Edit: "
|
||||
msgstr "편집: "
|
||||
|
||||
#. module: web_calendar
|
||||
#. openerp-web
|
||||
#: code:addons/web_calendar/static/src/js/calendar.js:150
|
||||
#, python-format
|
||||
msgid "Day"
|
||||
msgstr "일"
|
||||
|
||||
#. module: web_calendar
|
||||
#. openerp-web
|
||||
#: code:addons/web_calendar/static/src/js/calendar.js:157
|
||||
#, python-format
|
||||
msgid "Edit"
|
||||
msgstr "편집"
|
||||
|
||||
#. module: web_calendar
|
||||
#. openerp-web
|
||||
#: code:addons/web_calendar/static/src/js/calendar.js:169
|
||||
#, python-format
|
||||
msgid "Enabled"
|
||||
msgstr "활성화 됨"
|
||||
|
||||
#. module: web_calendar
|
||||
#. openerp-web
|
||||
#: code:addons/web_calendar/static/src/js/calendar.js:166
|
||||
#, python-format
|
||||
msgid "Do you want to edit the whole set of repeated events?"
|
||||
msgstr "반복 이벤트의 전체 세트를 편집하시겠습니까?"
|
||||
|
||||
#. module: web_calendar
|
||||
#. openerp-web
|
||||
#: code:addons/web_calendar/static/src/js/calendar.js:82
|
||||
#, python-format
|
||||
msgid "Filter"
|
||||
msgstr "필터"
|
||||
|
||||
#. module: web_calendar
|
||||
#. openerp-web
|
||||
#: code:addons/web_calendar/static/src/js/calendar.js:167
|
||||
#, python-format
|
||||
msgid "Repeat event"
|
||||
msgstr "이벤트 반복"
|
||||
|
||||
#. module: web_calendar
|
||||
#. openerp-web
|
||||
#: code:addons/web_calendar/static/src/js/calendar.js:172
|
||||
#: code:addons/web_calendar/static/src/js/calendar.js:180
|
||||
#, python-format
|
||||
msgid "Agenda"
|
||||
msgstr "의제"
|
||||
|
||||
#. module: web_calendar
|
||||
#. openerp-web
|
||||
#: code:addons/web_calendar/static/src/js/calendar.js:162
|
||||
#, python-format
|
||||
msgid "Time period"
|
||||
msgstr "시한"
|
||||
|
||||
#. module: web_calendar
|
||||
#. openerp-web
|
||||
#: code:addons/web_calendar/static/src/js/calendar.js:158
|
||||
#, python-format
|
||||
msgid "Delete"
|
||||
msgstr "삭제"
|
||||
|
||||
#. module: web_calendar
|
||||
#. openerp-web
|
||||
#: code:addons/web_calendar/static/src/js/calendar.js:152
|
||||
#, python-format
|
||||
msgid "Month"
|
||||
msgstr "월"
|
||||
|
||||
#. module: web_calendar
|
||||
#. openerp-web
|
||||
#: code:addons/web_calendar/static/src/js/calendar.js:168
|
||||
#, python-format
|
||||
msgid "Disabled"
|
||||
msgstr "비활성화 됨"
|
||||
|
||||
#. module: web_calendar
|
||||
#. openerp-web
|
||||
#: code:addons/web_calendar/static/src/js/calendar.js:435
|
||||
#, python-format
|
||||
msgid "Create: "
|
||||
msgstr "생성: "
|
||||
|
||||
#. module: web_calendar
|
||||
#. openerp-web
|
||||
#: code:addons/web_calendar/static/src/js/calendar.js:177
|
||||
#, python-format
|
||||
msgid "Year"
|
||||
msgstr "년도"
|
||||
|
||||
#. module: web_calendar
|
||||
#. openerp-web
|
||||
#: code:addons/web_calendar/static/src/js/calendar.js:155
|
||||
#, python-format
|
||||
msgid "Cancel"
|
||||
msgstr "취소"
|
||||
|
||||
#. module: web_calendar
|
||||
#. openerp-web
|
||||
#: code:addons/web_calendar/static/src/js/calendar.js:28
|
||||
#, python-format
|
||||
msgid "Calendar"
|
||||
msgstr "달력"
|
||||
|
||||
#. module: web_calendar
|
||||
#. openerp-web
|
||||
#: code:addons/web_calendar/static/src/js/calendar.js:93
|
||||
#, python-format
|
||||
msgid "Calendar view has not defined 'date_start' attribute."
|
||||
msgstr "달력 화면이 'date_start' 속성을 정의하지 않았습니다."
|
||||
@@ -18,7 +18,7 @@
|
||||
.openerp .oe_calendar .dhx_cal_select_menu .dhx_menu_icon.icon_edit {
|
||||
display: none;
|
||||
}
|
||||
.openerp .oe_calendar .dhx_cal_navline {
|
||||
.openerp .oe_calendar .dhx_cal_navline, .openerp .oe_calendar .dhx_cal_header {
|
||||
z-index: auto;
|
||||
}
|
||||
.openerp .oe_calendar.oe_cal_month .dhx_cal_data table tr td:last-child div.dhx_month_body {
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
// Dhtmlx Scheduler css overrides
|
||||
.dhx_cal_select_menu .dhx_menu_icon.icon_edit
|
||||
display: none
|
||||
.dhx_cal_navline
|
||||
.dhx_cal_navline, .dhx_cal_header
|
||||
// dhtmlx sets the index to 3 (in glossy theme)
|
||||
// I didn't found the reason yet but it overlaps the
|
||||
// dropdown menus and I want to avoid a z-index war.
|
||||
|
||||
@@ -414,6 +414,20 @@ instance.web_calendar.CalendarView = instance.web.View.extend({
|
||||
self.slow_create(event_id, event_obj);
|
||||
});
|
||||
},
|
||||
get_form_popup_infos: function() {
|
||||
var parent = this.getParent();
|
||||
var infos = {
|
||||
view_id: false,
|
||||
title: this.name,
|
||||
};
|
||||
if (parent instanceof instance.web.ViewManager) {
|
||||
infos.view_id = parent.get_view_id('form');
|
||||
if (parent instanceof instance.web.ViewManagerAction && parent.action && parent.action.name) {
|
||||
infos.title = parent.action.name;
|
||||
}
|
||||
}
|
||||
return infos;
|
||||
},
|
||||
slow_create: function(event_id, event_obj) {
|
||||
var self = this;
|
||||
if (this.current_mode() === 'month') {
|
||||
@@ -431,9 +445,11 @@ instance.web_calendar.CalendarView = instance.web.View.extend({
|
||||
});
|
||||
var something_saved = false;
|
||||
var pop = new instance.web.form.FormOpenPopup(this);
|
||||
var pop_infos = this.get_form_popup_infos();
|
||||
pop.show_element(this.dataset.model, null, this.dataset.get_context(defaults), {
|
||||
title: _t("Create: ") + ' ' + this.name,
|
||||
title: _.str.sprintf(_t("Create: %s"), pop_infos.title),
|
||||
disable_multiple_selection: true,
|
||||
view_id: pop_infos.view_id,
|
||||
});
|
||||
pop.on('closed', self, function() {
|
||||
if (!something_saved) {
|
||||
@@ -465,9 +481,11 @@ instance.web_calendar.CalendarView = instance.web.View.extend({
|
||||
});
|
||||
} else {
|
||||
var pop = new instance.web.form.FormOpenPopup(this);
|
||||
var pop_infos = this.get_form_popup_infos();
|
||||
var id_from_dataset = this.dataset.ids[index]; // dhtmlx scheduler loses id's type
|
||||
pop.show_element(this.dataset.model, id_from_dataset, this.dataset.get_context(), {
|
||||
title: _t("Edit: ") + this.name
|
||||
title: _.str.sprintf(_t("Edit: %s"), pop_infos.title),
|
||||
view_id: pop_infos.view_id,
|
||||
});
|
||||
pop.on('write_completed', self, function(){
|
||||
self.reload_event(id_from_dataset);
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
# Korean translation for openerp-web
|
||||
# Copyright (c) 2013 Rosetta Contributors and Canonical Ltd 2013
|
||||
# This file is distributed under the same license as the openerp-web package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2013.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: openerp-web\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2012-12-21 17:06+0000\n"
|
||||
"PO-Revision-Date: 2013-02-26 07:09+0000\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: Korean <ko@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2013-02-27 04:53+0000\n"
|
||||
"X-Generator: Launchpad (build 16506)\n"
|
||||
|
||||
#. module: web_diagram
|
||||
#. openerp-web
|
||||
#: code:addons/web_diagram/static/src/js/diagram.js:252
|
||||
#: code:addons/web_diagram/static/src/js/diagram.js:317
|
||||
#, python-format
|
||||
msgid "Open: "
|
||||
msgstr "열기: "
|
||||
|
||||
#. module: web_diagram
|
||||
#. openerp-web
|
||||
#: code:addons/web_diagram/static/src/js/diagram.js:215
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Deleting this node cannot be undone.\n"
|
||||
"It will also delete all connected transitions.\n"
|
||||
"\n"
|
||||
"Are you sure ?"
|
||||
msgstr ""
|
||||
"해당 노드를 삭제하는 작업은 복구할 수 없습니다.\n"
|
||||
"또한 모든 연결된 전환을 삭제할 것입니다.\n"
|
||||
"\n"
|
||||
"확실하십니까?"
|
||||
|
||||
#. module: web_diagram
|
||||
#. openerp-web
|
||||
#: code:addons/web_diagram/static/src/xml/base_diagram.xml:13
|
||||
#, python-format
|
||||
msgid "New Node"
|
||||
msgstr "신규 노드"
|
||||
|
||||
#. module: web_diagram
|
||||
#. openerp-web
|
||||
#: code:addons/web_diagram/static/src/js/diagram.js:310
|
||||
#: code:addons/web_diagram/static/src/js/diagram.js:329
|
||||
#, python-format
|
||||
msgid "Transition"
|
||||
msgstr "전환"
|
||||
|
||||
#. module: web_diagram
|
||||
#. openerp-web
|
||||
#: code:addons/web_diagram/static/src/js/diagram.js:11
|
||||
#, python-format
|
||||
msgid "Diagram"
|
||||
msgstr "도표"
|
||||
|
||||
#. module: web_diagram
|
||||
#. openerp-web
|
||||
#: code:addons/web_diagram/static/src/js/diagram.js:244
|
||||
#: code:addons/web_diagram/static/src/js/diagram.js:278
|
||||
#, python-format
|
||||
msgid "Activity"
|
||||
msgstr "활동"
|
||||
|
||||
#. module: web_diagram
|
||||
#. openerp-web
|
||||
#: code:addons/web_diagram/static/src/js/diagram.js:420
|
||||
#, python-format
|
||||
msgid "%d / %d"
|
||||
msgstr "%d / %d"
|
||||
|
||||
#. module: web_diagram
|
||||
#. openerp-web
|
||||
#: code:addons/web_diagram/static/src/js/diagram.js:283
|
||||
#: code:addons/web_diagram/static/src/js/diagram.js:335
|
||||
#, python-format
|
||||
msgid "Create:"
|
||||
msgstr "생성:"
|
||||
|
||||
#. module: web_diagram
|
||||
#. openerp-web
|
||||
#: code:addons/web_diagram/static/src/js/diagram.js:185
|
||||
#, python-format
|
||||
msgid "Are you sure?"
|
||||
msgstr "확실하십니까?"
|
||||
|
||||
#. module: web_diagram
|
||||
#. openerp-web
|
||||
#: code:addons/web_diagram/static/src/js/diagram.js:233
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Deleting this transition cannot be undone.\n"
|
||||
"\n"
|
||||
"Are you sure ?"
|
||||
msgstr ""
|
||||
"해당 전환을 삭제하는 작업은 복구할 수 없습니다.\n"
|
||||
"\n"
|
||||
"확실하십니까 ?"
|
||||
@@ -0,0 +1,32 @@
|
||||
# Korean translation for openerp-web
|
||||
# Copyright (c) 2013 Rosetta Contributors and Canonical Ltd 2013
|
||||
# This file is distributed under the same license as the openerp-web package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2013.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: openerp-web\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2012-12-21 17:06+0000\n"
|
||||
"PO-Revision-Date: 2013-02-26 06:02+0000\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: Korean <ko@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2013-02-27 04:53+0000\n"
|
||||
"X-Generator: Launchpad (build 16506)\n"
|
||||
|
||||
#. module: web_gantt
|
||||
#. openerp-web
|
||||
#: code:addons/web_gantt/static/src/xml/web_gantt.xml:10
|
||||
#, python-format
|
||||
msgid "Create"
|
||||
msgstr "생성"
|
||||
|
||||
#. module: web_gantt
|
||||
#. openerp-web
|
||||
#: code:addons/web_gantt/static/src/js/gantt.js:11
|
||||
#, python-format
|
||||
msgid "Gantt"
|
||||
msgstr "간트"
|
||||
@@ -24,8 +24,8 @@ instance.web_gantt.GanttView = instance.web.View.extend({
|
||||
var self = this;
|
||||
this.fields_view = fields_view_get;
|
||||
this.$el.addClass(this.fields_view.arch.attrs['class']);
|
||||
return new instance.web.Model(this.dataset.model)
|
||||
.call('fields_get').then(function (fields) {
|
||||
return self.alive(new instance.web.Model(this.dataset.model)
|
||||
.call('fields_get')).then(function (fields) {
|
||||
self.fields = fields;
|
||||
self.has_been_loaded.resolve();
|
||||
});
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
# Korean translation for openerp-web
|
||||
# Copyright (c) 2013 Rosetta Contributors and Canonical Ltd 2013
|
||||
# This file is distributed under the same license as the openerp-web package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2013.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: openerp-web\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2012-12-21 17:06+0000\n"
|
||||
"PO-Revision-Date: 2013-02-26 06:04+0000\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: Korean <ko@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2013-02-27 04:53+0000\n"
|
||||
"X-Generator: Launchpad (build 16506)\n"
|
||||
|
||||
#. module: web_graph
|
||||
#. openerp-web
|
||||
#: code:addons/web_graph/static/src/xml/web_graph.xml:12
|
||||
#, python-format
|
||||
msgid "Bars"
|
||||
msgstr "막대"
|
||||
|
||||
#. module: web_graph
|
||||
#. openerp-web
|
||||
#: code:addons/web_graph/static/src/xml/web_graph.xml:33
|
||||
#, python-format
|
||||
msgid "Show Data"
|
||||
msgstr "데이터 보기"
|
||||
|
||||
#. module: web_graph
|
||||
#. openerp-web
|
||||
#: code:addons/web_graph/static/src/js/graph.js:22
|
||||
#, python-format
|
||||
msgid "Graph"
|
||||
msgstr "그래프"
|
||||
|
||||
#. module: web_graph
|
||||
#. openerp-web
|
||||
#: code:addons/web_graph/static/src/xml/web_graph.xml:25
|
||||
#, python-format
|
||||
msgid "Inside"
|
||||
msgstr "내부"
|
||||
|
||||
#. module: web_graph
|
||||
#. openerp-web
|
||||
#: code:addons/web_graph/static/src/xml/web_graph.xml:3
|
||||
#, python-format
|
||||
msgid "í"
|
||||
msgstr "í"
|
||||
|
||||
#. module: web_graph
|
||||
#. openerp-web
|
||||
#: code:addons/web_graph/static/src/xml/web_graph.xml:11
|
||||
#, python-format
|
||||
msgid "Pie"
|
||||
msgstr "파이"
|
||||
|
||||
#. module: web_graph
|
||||
#. openerp-web
|
||||
#: code:addons/web_graph/static/src/xml/web_graph.xml:28
|
||||
#, python-format
|
||||
msgid "Actions"
|
||||
msgstr "액션"
|
||||
|
||||
#. module: web_graph
|
||||
#. openerp-web
|
||||
#: code:addons/web_graph/static/src/xml/web_graph.xml:7
|
||||
#, python-format
|
||||
msgid "Graph Mode"
|
||||
msgstr "그래프 모드"
|
||||
|
||||
#. module: web_graph
|
||||
#. openerp-web
|
||||
#: code:addons/web_graph/static/src/xml/web_graph.xml:18
|
||||
#, python-format
|
||||
msgid "Radar"
|
||||
msgstr "레이더"
|
||||
|
||||
#. module: web_graph
|
||||
#. openerp-web
|
||||
#: code:addons/web_graph/static/src/xml/web_graph.xml:34
|
||||
#, python-format
|
||||
msgid "Download as PNG"
|
||||
msgstr "PNG 형식으로 다운로드"
|
||||
|
||||
#. module: web_graph
|
||||
#. openerp-web
|
||||
#: code:addons/web_graph/static/src/xml/web_graph.xml:26
|
||||
#, python-format
|
||||
msgid "Top"
|
||||
msgstr "상단"
|
||||
|
||||
#. module: web_graph
|
||||
#. openerp-web
|
||||
#: code:addons/web_graph/static/src/xml/web_graph.xml:24
|
||||
#, python-format
|
||||
msgid "Hidden"
|
||||
msgstr "숨겨짐"
|
||||
|
||||
#. module: web_graph
|
||||
#. openerp-web
|
||||
#: code:addons/web_graph/static/src/xml/web_graph.xml:3
|
||||
#, python-format
|
||||
msgid "Graph Options"
|
||||
msgstr "그래프 옵션"
|
||||
|
||||
#. module: web_graph
|
||||
#. openerp-web
|
||||
#: code:addons/web_graph/static/src/xml/web_graph.xml:14
|
||||
#, python-format
|
||||
msgid "Lines"
|
||||
msgstr "선"
|
||||
|
||||
#. module: web_graph
|
||||
#. openerp-web
|
||||
#: code:addons/web_graph/static/src/xml/web_graph.xml:20
|
||||
#, python-format
|
||||
msgid "Legend"
|
||||
msgstr "범례"
|
||||
|
||||
#. module: web_graph
|
||||
#. openerp-web
|
||||
#: code:addons/web_graph/static/src/xml/web_graph.xml:32
|
||||
#, python-format
|
||||
msgid "Switch Axis"
|
||||
msgstr "축 전환"
|
||||
|
||||
#. module: web_graph
|
||||
#. openerp-web
|
||||
#: code:addons/web_graph/static/src/xml/web_graph.xml:15
|
||||
#, python-format
|
||||
msgid "Areas"
|
||||
msgstr "영역"
|
||||
@@ -246,7 +246,7 @@ instance.web_graph.GraphView = instance.web.View.extend({
|
||||
var result = [];
|
||||
var ticks = {};
|
||||
|
||||
return obj.call("fields_view_get", [view_id, 'graph']).then(function(tmp) {
|
||||
return this.alive(obj.call("fields_view_get", [view_id, 'graph']).then(function(tmp) {
|
||||
view_get = tmp;
|
||||
fields = view_get['fields'];
|
||||
var toload = _.select(group_by, function(x) { return fields[x] === undefined });
|
||||
@@ -368,7 +368,7 @@ instance.web_graph.GraphView = instance.web.View.extend({
|
||||
'ticks': _.map(ticks, function(el, key) { return [el, key] })
|
||||
};
|
||||
return res;
|
||||
});
|
||||
}));
|
||||
},
|
||||
|
||||
// Render the graph and update menu styles
|
||||
|
||||
@@ -0,0 +1,160 @@
|
||||
# Korean translation for openerp-web
|
||||
# Copyright (c) 2013 Rosetta Contributors and Canonical Ltd 2013
|
||||
# This file is distributed under the same license as the openerp-web package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2013.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: openerp-web\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2012-12-21 17:06+0000\n"
|
||||
"PO-Revision-Date: 2013-02-26 05:59+0000\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: Korean <ko@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2013-02-27 04:53+0000\n"
|
||||
"X-Generator: Launchpad (build 16506)\n"
|
||||
|
||||
#. module: web_kanban
|
||||
#. openerp-web
|
||||
#: code:addons/web_kanban/static/src/js/kanban.js:704
|
||||
#, python-format
|
||||
msgid "Edit column"
|
||||
msgstr "열 편집"
|
||||
|
||||
#. module: web_kanban
|
||||
#. openerp-web
|
||||
#: code:addons/web_kanban/static/src/js/kanban.js:418
|
||||
#, python-format
|
||||
msgid "An error has occured while moving the record to this group."
|
||||
msgstr "기록을 해당 그룹으로 옮기는 동안 오류가 발생했습니다."
|
||||
|
||||
#. module: web_kanban
|
||||
#. openerp-web
|
||||
#: code:addons/web_kanban/static/src/js/kanban.js:10
|
||||
#, python-format
|
||||
msgid "Kanban"
|
||||
msgstr "간판"
|
||||
|
||||
#. module: web_kanban
|
||||
#. openerp-web
|
||||
#: code:addons/web_kanban/static/src/js/kanban.js:557
|
||||
#, python-format
|
||||
msgid "Undefined"
|
||||
msgstr "정의되지 않음"
|
||||
|
||||
#. module: web_kanban
|
||||
#. openerp-web
|
||||
#: code:addons/web_kanban/static/src/js/kanban.js:723
|
||||
#, python-format
|
||||
msgid "Are you sure to remove this column ?"
|
||||
msgstr "정말로 해당 열을 제거하시겠습니다?"
|
||||
|
||||
#. module: web_kanban
|
||||
#. openerp-web
|
||||
#: code:addons/web_kanban/static/src/xml/web_kanban.xml:42
|
||||
#, python-format
|
||||
msgid "Edit"
|
||||
msgstr "편집"
|
||||
|
||||
#. module: web_kanban
|
||||
#. openerp-web
|
||||
#: code:addons/web_kanban/static/src/js/kanban.js:190
|
||||
#, python-format
|
||||
msgid "Add column"
|
||||
msgstr "열 추가"
|
||||
|
||||
#. module: web_kanban
|
||||
#. openerp-web
|
||||
#: code:addons/web_kanban/static/src/js/kanban.js:1100
|
||||
#, python-format
|
||||
msgid "Create: "
|
||||
msgstr "다음 생성: "
|
||||
|
||||
#. module: web_kanban
|
||||
#. openerp-web
|
||||
#: code:addons/web_kanban/static/src/xml/web_kanban.xml:24
|
||||
#, python-format
|
||||
msgid "Add a new column"
|
||||
msgstr "열 추가"
|
||||
|
||||
#. module: web_kanban
|
||||
#. openerp-web
|
||||
#: code:addons/web_kanban/static/src/js/kanban.js:694
|
||||
#: code:addons/web_kanban/static/src/xml/web_kanban.xml:40
|
||||
#, python-format
|
||||
msgid "Fold"
|
||||
msgstr "접기"
|
||||
|
||||
#. module: web_kanban
|
||||
#. openerp-web
|
||||
#: code:addons/web_kanban/static/src/xml/web_kanban.xml:91
|
||||
#, python-format
|
||||
msgid "Add"
|
||||
msgstr "추가"
|
||||
|
||||
#. module: web_kanban
|
||||
#. openerp-web
|
||||
#: code:addons/web_kanban/static/src/xml/web_kanban.xml:35
|
||||
#, python-format
|
||||
msgid "Quick create"
|
||||
msgstr "빠른 추가"
|
||||
|
||||
#. module: web_kanban
|
||||
#. openerp-web
|
||||
#: code:addons/web_kanban/static/src/js/kanban.js:936
|
||||
#, python-format
|
||||
msgid "Are you sure you want to delete this record ?"
|
||||
msgstr "정말로 다음 기록을 삭제하시겠습니까 ?"
|
||||
|
||||
#. module: web_kanban
|
||||
#. openerp-web
|
||||
#: code:addons/web_kanban/static/src/js/kanban.js:694
|
||||
#, python-format
|
||||
msgid "Unfold"
|
||||
msgstr "펼치기"
|
||||
|
||||
#. module: web_kanban
|
||||
#. openerp-web
|
||||
#: code:addons/web_kanban/static/src/xml/web_kanban.xml:73
|
||||
#, python-format
|
||||
msgid "Show more... ("
|
||||
msgstr "더 보기... ("
|
||||
|
||||
#. module: web_kanban
|
||||
#. openerp-web
|
||||
#: code:addons/web_kanban/static/src/xml/web_kanban.xml:92
|
||||
#, python-format
|
||||
msgid "Cancel"
|
||||
msgstr "취소"
|
||||
|
||||
#. module: web_kanban
|
||||
#. openerp-web
|
||||
#: code:addons/web_kanban/static/src/xml/web_kanban.xml:73
|
||||
#, python-format
|
||||
msgid "remaining)"
|
||||
msgstr "남음)"
|
||||
|
||||
#. module: web_kanban
|
||||
#. openerp-web
|
||||
#: code:addons/web_kanban/static/src/xml/web_kanban.xml:22
|
||||
#: code:addons/web_kanban/static/src/xml/web_kanban.xml:91
|
||||
#, python-format
|
||||
msgid "or"
|
||||
msgstr "또는"
|
||||
|
||||
#. module: web_kanban
|
||||
#. openerp-web
|
||||
#: code:addons/web_kanban/static/src/xml/web_kanban.xml:51
|
||||
#, python-format
|
||||
msgid "99+"
|
||||
msgstr "99+"
|
||||
|
||||
#. module: web_kanban
|
||||
#. openerp-web
|
||||
#: code:addons/web_kanban/static/src/xml/web_kanban.xml:43
|
||||
#, python-format
|
||||
msgid "Delete"
|
||||
msgstr "삭제"
|
||||
@@ -92,12 +92,21 @@
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.openerp .oe_kanban_view .oe_kanban_group_title .oe_kanban_group_length {
|
||||
.openerp .oe_kanban_view .oe_kanban_group_length {
|
||||
text-align: center;
|
||||
display: none;
|
||||
}
|
||||
.openerp .oe_kanban_view .oe_kanban_group_length .oe_tag {
|
||||
position: relative;
|
||||
top: +8px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.openerp .oe_kanban_view .oe_fold_column .oe_kanban_group_length {
|
||||
position: absolute;
|
||||
top: -1px;
|
||||
right: -14px;
|
||||
text-align: center;
|
||||
float: right;
|
||||
display: block;
|
||||
}
|
||||
.openerp .oe_kanban_view .oe_kanban_header:hover .oe_kanban_group_length {
|
||||
display: none;
|
||||
@@ -141,7 +150,8 @@
|
||||
.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 {
|
||||
.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;
|
||||
}
|
||||
.openerp .oe_kanban_view .oe_kanban_group_folded .oe_dropdown_kanban {
|
||||
@@ -163,7 +173,7 @@
|
||||
display: none;
|
||||
position: relative;
|
||||
opacity: 0.75;
|
||||
top: 20px;
|
||||
top: 26px;
|
||||
}
|
||||
.openerp .oe_kanban_view .oe_kanban_add, .openerp .oe_kanban_view .oe_kanban_header .oe_dropdown_toggle {
|
||||
margin-left: 4px;
|
||||
@@ -175,6 +185,7 @@
|
||||
}
|
||||
.openerp .oe_kanban_view .oe_kanban_header .oe_dropdown_toggle {
|
||||
top: -2px;
|
||||
height: 14px;
|
||||
}
|
||||
.openerp .oe_kanban_view .oe_kanban_card, .openerp .oe_kanban_view .oe_dropdown_toggle {
|
||||
cursor: pointer;
|
||||
|
||||
@@ -54,6 +54,13 @@
|
||||
&.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
|
||||
.ui-sortable-placeholder
|
||||
border: 1px solid rgba(0,0,0,0.1)
|
||||
visibility: visible !important
|
||||
@@ -118,11 +125,12 @@
|
||||
white-space: nowrap
|
||||
overflow: hidden
|
||||
text-overflow: ellipsis
|
||||
.oe_fold_column
|
||||
.oe_kanban_group_length
|
||||
position: absolute
|
||||
top: -1px
|
||||
right: -14px
|
||||
text-align: center
|
||||
display: block
|
||||
float: right
|
||||
&.oe_kanban_grouped
|
||||
.oe_kanban_column, .oe_kanban_group_header
|
||||
@@ -159,7 +167,7 @@
|
||||
.oe_kanban_group_folded
|
||||
.oe_kanban_group_title, &.oe_kanban_column *, .oe_kanban_aggregates, .oe_kanban_add
|
||||
display: none
|
||||
.oe_kanban_group_title_vertical
|
||||
.oe_kanban_group_title_vertical, .oe_kanban_group_length
|
||||
display: block
|
||||
.oe_dropdown_kanban
|
||||
left: -5px
|
||||
@@ -178,7 +186,7 @@
|
||||
display: none
|
||||
position: relative
|
||||
opacity: 0.75
|
||||
top: 20px
|
||||
top: 26px
|
||||
// }}}
|
||||
// KanbanQuickCreate {{{
|
||||
.oe_kanban_add, .oe_kanban_header .oe_dropdown_toggle
|
||||
@@ -189,6 +197,7 @@
|
||||
top: -8px
|
||||
.oe_kanban_header .oe_dropdown_toggle
|
||||
top: -2px
|
||||
height: 14px;
|
||||
.oe_kanban_card, .oe_dropdown_toggle
|
||||
cursor: pointer
|
||||
display: inline-block
|
||||
|
||||
@@ -134,7 +134,9 @@ instance.web_kanban.KanbanView = instance.web.View.extend({
|
||||
switch (node.tag) {
|
||||
case 'field':
|
||||
if (this.fields_view.fields[node.attrs.name].type === 'many2many') {
|
||||
this.many2manys.push(node.attrs.name);
|
||||
if (_.indexOf(this.many2manys, node.attrs.name) < 0) {
|
||||
this.many2manys.push(node.attrs.name);
|
||||
}
|
||||
node.tag = 'div';
|
||||
node.attrs['class'] = (node.attrs['class'] || '') + ' oe_form_field oe_tags';
|
||||
} else {
|
||||
@@ -227,14 +229,15 @@ instance.web_kanban.KanbanView = instance.web.View.extend({
|
||||
this.search_domain = domain;
|
||||
this.search_context = context;
|
||||
this.search_group_by = group_by;
|
||||
$.when(this.has_been_loaded).done(function() {
|
||||
return $.when(this.has_been_loaded).then(function() {
|
||||
self.group_by = group_by.length ? group_by[0] : self.fields_view.arch.attrs.default_group_by;
|
||||
self.group_by_field = self.fields_view.fields[self.group_by] || {};
|
||||
self.grouped_by_m2o = (self.group_by_field.type === 'many2one');
|
||||
self.$buttons.find('.oe_alternative').toggle(self.grouped_by_m2o);
|
||||
self.$el.toggleClass('oe_kanban_grouped_by_m2o', self.grouped_by_m2o);
|
||||
var grouping = new instance.web.Model(self.dataset.model, context, domain).query().group_by(self.group_by);
|
||||
$.when(grouping).done(function(groups) {
|
||||
var grouping_fields = self.group_by ? [self.group_by].concat(_.keys(self.aggregates)) : undefined;
|
||||
var grouping = new instance.web.Model(self.dataset.model, context, domain).query().group_by(grouping_fields);
|
||||
return self.alive($.when(grouping)).done(function(groups) {
|
||||
if (groups) {
|
||||
self.do_process_groups(groups);
|
||||
} else {
|
||||
@@ -635,6 +638,7 @@ instance.web_kanban.KanbanGroup = instance.web.Widget.extend({
|
||||
self.view.dataset.ids = ids.concat(self.dataset.ids);
|
||||
self.do_add_records(records);
|
||||
self.compute_cards_auto_height();
|
||||
self.view.postprocess_m2m_tags();
|
||||
return records;
|
||||
});
|
||||
},
|
||||
|
||||
@@ -34,16 +34,21 @@
|
||||
<t t-if="widget.view._is_quick_create_enabled()">
|
||||
<div class="oe_kanban_add oe_e" title="Quick create">]</div>
|
||||
</t>
|
||||
<div class="oe_dropdown_toggle oe_dropdown_kanban">
|
||||
<span class="oe_e">í</span>
|
||||
<ul class="oe_dropdown_menu oe_kanban_group_dropdown">
|
||||
<li><a data-action="toggle_fold" href="#">Fold</a></li>
|
||||
<t t-if="widget.view.grouped_by_m2o and widget.value">
|
||||
<li><a data-action="edit" href="#">Edit</a></li>
|
||||
<li><a data-action="delete" href="#">Delete</a></li>
|
||||
</t>
|
||||
</ul>
|
||||
<div class="oe_dropdown_toggle oe_dropdown_kanban">
|
||||
<div class="oe_kanban_group_length">
|
||||
<span class="oe_tag">
|
||||
<t t-if="widget.group.get('length') > 99"> 99+ </t><t t-if="widget.group.get('length') <= 99"> <t t-esc="widget.group.get('length')"/> </t>
|
||||
</span>
|
||||
</div>
|
||||
<span class="oe_e">í</span>
|
||||
<ul class="oe_dropdown_menu oe_kanban_group_dropdown">
|
||||
<li><a data-action="toggle_fold" href="#">Fold</a></li>
|
||||
<t t-if="widget.view.grouped_by_m2o and widget.value">
|
||||
<li><a data-action="edit" href="#">Edit</a></li>
|
||||
<li><a data-action="delete" href="#">Delete</a></li>
|
||||
</t>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="oe_fold_column">
|
||||
<div t-attf-class="oe_kanban_group_title #{widget.undefined_title ? 'oe_kanban_group_title_undefined' : ''}">
|
||||
<div class="oe_kanban_group_length oe_tag">
|
||||
@@ -57,7 +62,9 @@
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<span t-if="widget.title" class="oe_kanban_group_title_vertical"><t t-esc="widget.title"/></span>
|
||||
<span t-if="widget.title" class="oe_kanban_group_title_vertical">
|
||||
<t t-esc="widget.title"/>
|
||||
</span>
|
||||
</div>
|
||||
</t>
|
||||
<t t-if="! widget.view.group_by && widget.view._is_quick_create_enabled()">
|
||||
|
||||
@@ -0,0 +1,184 @@
|
||||
# Korean translation for openerp-web
|
||||
# Copyright (c) 2013 Rosetta Contributors and Canonical Ltd 2013
|
||||
# This file is distributed under the same license as the openerp-web package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2013.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: openerp-web\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2012-12-21 17:06+0000\n"
|
||||
"PO-Revision-Date: 2013-02-26 08:08+0000\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: Korean <ko@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2013-02-27 04:53+0000\n"
|
||||
"X-Generator: Launchpad (build 16506)\n"
|
||||
|
||||
#. module: web_view_editor
|
||||
#. openerp-web
|
||||
#: code:addons/web_view_editor/static/src/js/view_editor.js:164
|
||||
#, python-format
|
||||
msgid "The following fields are invalid :"
|
||||
msgstr "다음 필드는 유효하지 않습니다 :"
|
||||
|
||||
#. module: web_view_editor
|
||||
#. openerp-web
|
||||
#: code:addons/web_view_editor/static/src/js/view_editor.js:63
|
||||
#, python-format
|
||||
msgid "Create"
|
||||
msgstr "생성"
|
||||
|
||||
#. module: web_view_editor
|
||||
#. openerp-web
|
||||
#: code:addons/web_view_editor/static/src/js/view_editor.js:986
|
||||
#, python-format
|
||||
msgid "New Field"
|
||||
msgstr "신규 필드"
|
||||
|
||||
#. module: web_view_editor
|
||||
#. openerp-web
|
||||
#: code:addons/web_view_editor/static/src/js/view_editor.js:386
|
||||
#, python-format
|
||||
msgid "Do you really wants to create an inherited view here?"
|
||||
msgstr "정말로 여기에 전승된 화면을 생성하길 원하십니까?"
|
||||
|
||||
#. module: web_view_editor
|
||||
#. openerp-web
|
||||
#: code:addons/web_view_editor/static/src/js/view_editor.js:396
|
||||
#, python-format
|
||||
msgid "Preview"
|
||||
msgstr "미리보기"
|
||||
|
||||
#. module: web_view_editor
|
||||
#. openerp-web
|
||||
#: code:addons/web_view_editor/static/src/js/view_editor.js:183
|
||||
#, python-format
|
||||
msgid "Do you really want to remove this view?"
|
||||
msgstr "정말로 해당 화면을 제거하시겠습니까?"
|
||||
|
||||
#. module: web_view_editor
|
||||
#. openerp-web
|
||||
#: code:addons/web_view_editor/static/src/js/view_editor.js:90
|
||||
#, python-format
|
||||
msgid "Save"
|
||||
msgstr "저장"
|
||||
|
||||
#. module: web_view_editor
|
||||
#. openerp-web
|
||||
#: code:addons/web_view_editor/static/src/js/view_editor.js:393
|
||||
#, python-format
|
||||
msgid "Select an element"
|
||||
msgstr "요소 선택"
|
||||
|
||||
#. module: web_view_editor
|
||||
#. openerp-web
|
||||
#: code:addons/web_view_editor/static/src/js/view_editor.js:828
|
||||
#: code:addons/web_view_editor/static/src/js/view_editor.js:954
|
||||
#, python-format
|
||||
msgid "Update"
|
||||
msgstr "업데이트"
|
||||
|
||||
#. module: web_view_editor
|
||||
#. openerp-web
|
||||
#: code:addons/web_view_editor/static/src/js/view_editor.js:263
|
||||
#, python-format
|
||||
msgid "Please select view in list :"
|
||||
msgstr "목록에서 화면을 선택하세요 :"
|
||||
|
||||
#. module: web_view_editor
|
||||
#. openerp-web
|
||||
#: code:addons/web_view_editor/static/src/js/view_editor.js:37
|
||||
#, python-format
|
||||
msgid "Manage Views (%s)"
|
||||
msgstr "화면 관리 (%s)"
|
||||
|
||||
#. module: web_view_editor
|
||||
#. openerp-web
|
||||
#: code:addons/web_view_editor/static/src/js/view_editor.js:13
|
||||
#, python-format
|
||||
msgid "Manage Views"
|
||||
msgstr "화면 관리"
|
||||
|
||||
#. module: web_view_editor
|
||||
#. openerp-web
|
||||
#: code:addons/web_view_editor/static/src/js/view_editor.js:825
|
||||
#: code:addons/web_view_editor/static/src/js/view_editor.js:951
|
||||
#, python-format
|
||||
msgid "Properties"
|
||||
msgstr "속성"
|
||||
|
||||
#. module: web_view_editor
|
||||
#. openerp-web
|
||||
#: code:addons/web_view_editor/static/src/js/view_editor.js:64
|
||||
#, python-format
|
||||
msgid "Edit"
|
||||
msgstr "편집"
|
||||
|
||||
#. module: web_view_editor
|
||||
#. openerp-web
|
||||
#: code:addons/web_view_editor/static/src/js/view_editor.js:14
|
||||
#, python-format
|
||||
msgid "Could not find current view declaration"
|
||||
msgstr "현재 화면 선언을 찾을 수 없음"
|
||||
|
||||
#. module: web_view_editor
|
||||
#. openerp-web
|
||||
#: code:addons/web_view_editor/static/src/js/view_editor.js:382
|
||||
#, python-format
|
||||
msgid "Inherited View"
|
||||
msgstr "전승 화면"
|
||||
|
||||
#. module: web_view_editor
|
||||
#. openerp-web
|
||||
#: code:addons/web_view_editor/static/src/js/view_editor.js:65
|
||||
#, python-format
|
||||
msgid "Remove"
|
||||
msgstr "제거"
|
||||
|
||||
#. module: web_view_editor
|
||||
#. openerp-web
|
||||
#: code:addons/web_view_editor/static/src/js/view_editor.js:516
|
||||
#, python-format
|
||||
msgid "Do you really want to remove this node?"
|
||||
msgstr "정말로 이 노드를 삭제하시겠습니까?"
|
||||
|
||||
#. module: web_view_editor
|
||||
#. openerp-web
|
||||
#: code:addons/web_view_editor/static/src/js/view_editor.js:390
|
||||
#, python-format
|
||||
msgid "Can't Update View"
|
||||
msgstr "화면을 업데이트 할 수 없음"
|
||||
|
||||
#. module: web_view_editor
|
||||
#. openerp-web
|
||||
#: code:addons/web_view_editor/static/src/js/view_editor.js:379
|
||||
#, python-format
|
||||
msgid "View Editor %d - %s"
|
||||
msgstr "화면 편집기 %d - %s"
|
||||
|
||||
#. module: web_view_editor
|
||||
#. openerp-web
|
||||
#: code:addons/web_view_editor/static/src/js/view_editor.js:112
|
||||
#: code:addons/web_view_editor/static/src/js/view_editor.js:846
|
||||
#: code:addons/web_view_editor/static/src/js/view_editor.js:974
|
||||
#, python-format
|
||||
msgid "Cancel"
|
||||
msgstr "취소"
|
||||
|
||||
#. module: web_view_editor
|
||||
#. openerp-web
|
||||
#: code:addons/web_view_editor/static/src/js/view_editor.js:66
|
||||
#: code:addons/web_view_editor/static/src/js/view_editor.js:413
|
||||
#, python-format
|
||||
msgid "Close"
|
||||
msgstr "닫기"
|
||||
|
||||
#. module: web_view_editor
|
||||
#. openerp-web
|
||||
#: code:addons/web_view_editor/static/src/js/view_editor.js:88
|
||||
#, python-format
|
||||
msgid "Create a view (%s)"
|
||||
msgstr "화면 생성 (%s)"
|
||||
Reference in New Issue
Block a user