[MERGE] trunk
bzr revid: al@openerp.com-20120725074053-e3gltrdfzm8bb7j8
This commit is contained in:
commit
1d766a2bc6
|
@ -20,6 +20,7 @@
|
|||
"static/lib/jquery.form/jquery.form.js",
|
||||
"static/lib/jquery.validate/jquery.validate.js",
|
||||
"static/lib/jquery.ba-bbq/jquery.ba-bbq.js",
|
||||
"static/lib/spinjs/spin.js",
|
||||
"static/lib/jquery.blockUI/jquery.blockUI.js",
|
||||
"static/lib/jquery.ui/js/jquery-ui-1.8.17.custom.min.js",
|
||||
"static/lib/jquery.ui.timepicker/js/jquery-ui-timepicker-addon.js",
|
||||
|
@ -33,6 +34,7 @@
|
|||
"static/lib/underscore/underscore.js",
|
||||
"static/lib/underscore/underscore.string.js",
|
||||
"static/lib/backbone/backbone.js",
|
||||
"static/lib/cleditor/jquery.cleditor.js",
|
||||
"static/lib/py.js/lib/py.js",
|
||||
"static/src/js/boot.js",
|
||||
"static/src/js/corelib.js",
|
||||
|
@ -60,6 +62,7 @@
|
|||
"static/src/css/base.css",
|
||||
"static/src/css/data_export.css",
|
||||
"static/src/css/data_import.css",
|
||||
"static/lib/cleditor/jquery.cleditor.css",
|
||||
],
|
||||
'qweb' : [
|
||||
"static/src/xml/*.xml",
|
||||
|
|
|
@ -28,6 +28,7 @@ import werkzeug.wsgi
|
|||
from . import nonliterals
|
||||
from . import session
|
||||
from . import openerplib
|
||||
import urlparse
|
||||
|
||||
__all__ = ['Root', 'jsonrequest', 'httprequest', 'Controller',
|
||||
'WebRequest', 'JsonRequest', 'HttpRequest']
|
||||
|
@ -417,6 +418,20 @@ class ControllerType(type):
|
|||
class Controller(object):
|
||||
__metaclass__ = ControllerType
|
||||
|
||||
class DisableCacheMiddleware(object):
|
||||
def __init__(self, app):
|
||||
self.app = app
|
||||
def __call__(self, environ, start_response):
|
||||
def start_wrapped(status, headers):
|
||||
referer = environ.get('HTTP_REFERER', '')
|
||||
parsed = urlparse.urlparse(referer)
|
||||
debug = not urlparse.parse_qs(parsed.query).has_key('debug')
|
||||
filtered_headers = [(k,v) for k,v in headers if not (k=='Last-Modified' or (debug and k=='Cache-Control'))]
|
||||
if debug:
|
||||
filtered_headers.append(('Cache-Control', 'no-cache'))
|
||||
start_response(status, filtered_headers)
|
||||
return self.app(environ, start_wrapped)
|
||||
|
||||
class Root(object):
|
||||
"""Root WSGI application for the OpenERP Web Client.
|
||||
|
||||
|
@ -452,8 +467,8 @@ class Root(object):
|
|||
|
||||
static_dirs = self._load_addons(openerp_addons_namespace)
|
||||
if options.serve_static:
|
||||
self.dispatch = werkzeug.wsgi.SharedDataMiddleware(
|
||||
self.dispatch, static_dirs, cache=False)
|
||||
app = werkzeug.wsgi.SharedDataMiddleware( self.dispatch, static_dirs)
|
||||
self.dispatch = DisableCacheMiddleware(app)
|
||||
|
||||
if options.session_storage:
|
||||
if not os.path.exists(options.session_storage):
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
After Width: | Height: | Size: 3.0 KiB |
Binary file not shown.
After Width: | Height: | Size: 68 B |
|
@ -0,0 +1,24 @@
|
|||
.cleditorMain {border:1px solid #999; padding:0 1px 1px; background-color:white}
|
||||
.cleditorMain iframe {border:none; margin:0; padding:0}
|
||||
.cleditorMain textarea {border:none; margin:0; padding:0; overflow-y:scroll; font:10pt Arial,Verdana; resize:none; outline:none /* webkit grip focus */}
|
||||
.cleditorToolbar {background: url('images/toolbar.gif') repeat}
|
||||
.cleditorGroup {float:left; height:26px}
|
||||
.cleditorButton {float:left; width:24px; height:24px; margin:1px 0 1px 0; background: url('images/buttons.gif')}
|
||||
.cleditorDisabled {opacity:0.3; filter:alpha(opacity=30)}
|
||||
.cleditorDivider {float:left; width:1px; height:23px; margin:1px 0 1px 0; background:#CCC}
|
||||
.cleditorPopup {border:solid 1px #999; background-color:white; position:absolute; font:10pt Arial,Verdana; cursor:default; z-index:10000}
|
||||
.cleditorList div {padding:2px 4px 2px 4px}
|
||||
.cleditorList p,
|
||||
.cleditorList h1,
|
||||
.cleditorList h2,
|
||||
.cleditorList h3,
|
||||
.cleditorList h4,
|
||||
.cleditorList h5,
|
||||
.cleditorList h6,
|
||||
.cleditorList font {padding:0; margin:0; background-color:Transparent}
|
||||
.cleditorColor {width:150px; padding:1px 0 0 1px}
|
||||
.cleditorColor div {float:left; width:14px; height:14px; margin:0 1px 1px 0}
|
||||
.cleditorPrompt {background-color:#F6F7F9; padding:4px; font-size:8.5pt}
|
||||
.cleditorPrompt input,
|
||||
.cleditorPrompt textarea {font:8.5pt Arial,Verdana;}
|
||||
.cleditorMsg {background-color:#FDFCEE; width:150px; padding:4px; font-size:8.5pt}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
CLEditor WYSIWYG HTML Editor v1.3.0
|
||||
http://premiumsoftware.net/cleditor
|
||||
requires jQuery v1.4.2 or later
|
||||
|
||||
Copyright 2010, Chris Landowski, Premium Software, LLC
|
||||
Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
*/
|
||||
(function(e){function aa(a){var b=this,c=a.target,d=e.data(c,x),h=s[d],f=h.popupName,i=p[f];if(!(b.disabled||e(c).attr(n)==n)){var g={editor:b,button:c,buttonName:d,popup:i,popupName:f,command:h.command,useCSS:b.options.useCSS};if(h.buttonClick&&h.buttonClick(a,g)===false)return false;if(d=="source"){if(t(b)){delete b.range;b.$area.hide();b.$frame.show();c.title=h.title}else{b.$frame.hide();b.$area.show();c.title="Show Rich Text"}setTimeout(function(){u(b)},100)}else if(!t(b))if(f){var j=e(i);if(f==
|
||||
"url"){if(d=="link"&&M(b)===""){z(b,"A selection is required when inserting a link.",c);return false}j.children(":button").unbind(q).bind(q,function(){var k=j.find(":text"),o=e.trim(k.val());o!==""&&v(b,g.command,o,null,g.button);k.val("http://");r();w(b)})}else f=="pastetext"&&j.children(":button").unbind(q).bind(q,function(){var k=j.find("textarea"),o=k.val().replace(/\n/g,"<br />");o!==""&&v(b,g.command,o,null,g.button);k.val("");r();w(b)});if(c!==e.data(i,A)){N(b,i,c);return false}return}else if(d==
|
||||
"print")b.$frame[0].contentWindow.print();else if(!v(b,g.command,g.value,g.useCSS,c))return false;w(b)}}function O(a){a=e(a.target).closest("div");a.css(H,a.data(x)?"#FFF":"#FFC")}function P(a){e(a.target).closest("div").css(H,"transparent")}function ba(a){var b=a.data.popup,c=a.target;if(!(b===p.msg||e(b).hasClass(B))){var d=e.data(b,A),h=e.data(d,x),f=s[h],i=f.command,g,j=this.options.useCSS;if(h=="font")g=c.style.fontFamily.replace(/"/g,"");else if(h=="size"){if(c.tagName=="DIV")c=c.children[0];
|
||||
g=c.innerHTML}else if(h=="style")g="<"+c.tagName+">";else if(h=="color")g=Q(c.style.backgroundColor);else if(h=="highlight"){g=Q(c.style.backgroundColor);if(l)i="backcolor";else j=true}b={editor:this,button:d,buttonName:h,popup:b,popupName:f.popupName,command:i,value:g,useCSS:j};if(!(f.popupClick&&f.popupClick(a,b)===false)){if(b.command&&!v(this,b.command,b.value,b.useCSS,d))return false;r();w(this)}}}function C(a){for(var b=1,c=0,d=0;d<a.length;++d){b=(b+a.charCodeAt(d))%65521;c=(c+b)%65521}return c<<
|
||||
16|b}function R(a,b,c,d,h){if(p[a])return p[a];var f=e(m).hide().addClass(ca).appendTo("body");if(d)f.html(d);else if(a=="color"){b=b.colors.split(" ");b.length<10&&f.width("auto");e.each(b,function(i,g){e(m).appendTo(f).css(H,"#"+g)});c=da}else if(a=="font")e.each(b.fonts.split(","),function(i,g){e(m).appendTo(f).css("fontFamily",g).html(g)});else if(a=="size")e.each(b.sizes.split(","),function(i,g){e(m).appendTo(f).html("<font size="+g+">"+g+"</font>")});else if(a=="style")e.each(b.styles,function(i,
|
||||
g){e(m).appendTo(f).html(g[1]+g[0]+g[1].replace("<","</"))});else if(a=="url"){f.html('Enter URL:<br><input type=text value="http://" size=35><br><input type=button value="Submit">');c=B}else if(a=="pastetext"){f.html("Paste your content here and click submit.<br /><textarea cols=40 rows=3></textarea><br /><input type=button value=Submit>");c=B}if(!c&&!d)c=S;f.addClass(c);l&&f.attr(I,"on").find("div,font,p,h1,h2,h3,h4,h5,h6").attr(I,"on");if(f.hasClass(S)||h===true)f.children().hover(O,P);p[a]=f[0];
|
||||
return f[0]}function T(a,b){if(b){a.$area.attr(n,n);a.disabled=true}else{a.$area.removeAttr(n);delete a.disabled}try{if(l)a.doc.body.contentEditable=!b;else a.doc.designMode=!b?"on":"off"}catch(c){}u(a)}function v(a,b,c,d,h){D(a);if(!l){if(d===undefined||d===null)d=a.options.useCSS;a.doc.execCommand("styleWithCSS",0,d.toString())}d=true;var f;if(l&&b.toLowerCase()=="inserthtml")y(a).pasteHTML(c);else{try{d=a.doc.execCommand(b,0,c||null)}catch(i){f=i.description;d=false}d||("cutcopypaste".indexOf(b)>
|
||||
-1?z(a,"For security reasons, your browser does not support the "+b+" command. Try using the keyboard shortcut or context menu instead.",h):z(a,f?f:"Error executing the "+b+" command.",h))}u(a);return d}function w(a){setTimeout(function(){t(a)?a.$area.focus():a.$frame[0].contentWindow.focus();u(a)},0)}function y(a){if(l)return J(a).createRange();return J(a).getRangeAt(0)}function J(a){if(l)return a.doc.selection;return a.$frame[0].contentWindow.getSelection()}function Q(a){var b=/rgba?\((\d+), (\d+), (\d+)/.exec(a),
|
||||
c=a.split("");if(b)for(a=(b[1]<<16|b[2]<<8|b[3]).toString(16);a.length<6;)a="0"+a;return"#"+(a.length==6?a:c[1]+c[1]+c[2]+c[2]+c[3]+c[3])}function r(){e.each(p,function(a,b){e(b).hide().unbind(q).removeData(A)})}function U(){var a=e("link[href$='jquery.cleditor.css']").attr("href");return a.substr(0,a.length-19)+"images/"}function K(a){var b=a.$main,c=a.options;a.$frame&&a.$frame.remove();var d=a.$frame=e('<iframe frameborder="0" src="javascript:true;">').hide().appendTo(b),h=d[0].contentWindow,f=
|
||||
a.doc=h.document,i=e(f);f.open();f.write(c.docType+"<html>"+(c.docCSSFile===""?"":'<head><link rel="stylesheet" type="text/css" href="'+c.docCSSFile+'" /></head>')+'<body style="'+c.bodyStyle+'"></body></html>');f.close();l&&i.click(function(){w(a)});E(a);if(l){i.bind("beforedeactivate beforeactivate selectionchange keypress",function(g){if(g.type=="beforedeactivate")a.inactive=true;else if(g.type=="beforeactivate"){!a.inactive&&a.range&&a.range.length>1&&a.range.shift();delete a.inactive}else if(!a.inactive){if(!a.range)a.range=
|
||||
[];for(a.range.unshift(y(a));a.range.length>2;)a.range.pop()}});d.focus(function(){D(a)})}(e.browser.mozilla?i:e(h)).blur(function(){V(a,true)});i.click(r).bind("keyup mouseup",function(){u(a)});L?a.$area.show():d.show();e(function(){var g=a.$toolbar,j=g.children("div:last"),k=b.width();j=j.offset().top+j.outerHeight()-g.offset().top+1;g.height(j);j=(/%/.test(""+c.height)?b.height():parseInt(c.height))-j;d.width(k).height(j);a.$area.width(k).height(ea?j-2:j);T(a,a.disabled);u(a)})}function u(a){if(!L&&
|
||||
e.browser.webkit&&!a.focused){a.$frame[0].contentWindow.focus();window.focus();a.focused=true}var b=a.doc;if(l)b=y(a);var c=t(a);e.each(a.$toolbar.find("."+W),function(d,h){var f=e(h),i=e.cleditor.buttons[e.data(h,x)],g=i.command,j=true;if(a.disabled)j=false;else if(i.getEnabled){j=i.getEnabled({editor:a,button:h,buttonName:i.name,popup:p[i.popupName],popupName:i.popupName,command:i.command,useCSS:a.options.useCSS});if(j===undefined)j=true}else if((c||L)&&i.name!="source"||l&&(g=="undo"||g=="redo"))j=
|
||||
false;else if(g&&g!="print"){if(l&&g=="hilitecolor")g="backcolor";if(!l||g!="inserthtml")try{j=b.queryCommandEnabled(g)}catch(k){j=false}}if(j){f.removeClass(X);f.removeAttr(n)}else{f.addClass(X);f.attr(n,n)}})}function D(a){l&&a.range&&a.range[0].select()}function M(a){D(a);if(l)return y(a).text;return J(a).toString()}function z(a,b,c){var d=R("msg",a.options,fa);d.innerHTML=b;N(a,d,c)}function N(a,b,c){var d,h,f=e(b);if(c){var i=e(c);d=i.offset();h=--d.left;d=d.top+i.height()}else{i=a.$toolbar;
|
||||
d=i.offset();h=Math.floor((i.width()-f.width())/2)+d.left;d=d.top+i.height()-2}r();f.css({left:h,top:d}).show();if(c){e.data(b,A,c);f.bind(q,{popup:b},e.proxy(ba,a))}setTimeout(function(){f.find(":text,textarea").eq(0).focus().select()},100)}function t(a){return a.$area.is(":visible")}function E(a,b){var c=a.$area.val(),d=a.options,h=d.updateFrame,f=e(a.doc.body);if(h){var i=C(c);if(b&&a.areaChecksum==i)return;a.areaChecksum=i}c=h?h(c):c;c=c.replace(/<(?=\/?script)/ig,"<");if(d.updateTextArea)a.frameChecksum=
|
||||
C(c);if(c!=f.html()){f.html(c);e(a).triggerHandler(F)}}function V(a,b){var c=e(a.doc.body).html(),d=a.options,h=d.updateTextArea,f=a.$area;if(h){var i=C(c);if(b&&a.frameChecksum==i)return;a.frameChecksum=i}c=h?h(c):c;if(d.updateFrame)a.areaChecksum=C(c);if(c!=f.val()){f.val(c);e(a).triggerHandler(F)}}e.cleditor={defaultOptions:{width:500,height:250,controls:"bold italic underline strikethrough subscript superscript | font size style | color highlight removeformat | bullets numbering | outdent indent | alignleft center alignright justify | undo redo | rule image link unlink | cut copy paste pastetext | print source",
|
||||
colors:"FFF FCC FC9 FF9 FFC 9F9 9FF CFF CCF FCF CCC F66 F96 FF6 FF3 6F9 3FF 6FF 99F F9F BBB F00 F90 FC6 FF0 3F3 6CC 3CF 66C C6C 999 C00 F60 FC3 FC0 3C0 0CC 36F 63F C3C 666 900 C60 C93 990 090 399 33F 60C 939 333 600 930 963 660 060 366 009 339 636 000 300 630 633 330 030 033 006 309 303",fonts:"Arial,Arial Black,Comic Sans MS,Courier New,Narrow,Garamond,Georgia,Impact,Sans Serif,Serif,Tahoma,Trebuchet MS,Verdana",sizes:"1,2,3,4,5,6,7",styles:[["Paragraph","<p>"],["Header 1","<h1>"],["Header 2","<h2>"],
|
||||
["Header 3","<h3>"],["Header 4","<h4>"],["Header 5","<h5>"],["Header 6","<h6>"]],useCSS:false,docType:'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">',docCSSFile:"",bodyStyle:"margin:4px; font:10pt Arial,Verdana; cursor:text"},buttons:{init:"bold,,|italic,,|underline,,|strikethrough,,|subscript,,|superscript,,|font,,fontname,|size,Font Size,fontsize,|style,,formatblock,|color,Font Color,forecolor,|highlight,Text Highlight Color,hilitecolor,color|removeformat,Remove Formatting,|bullets,,insertunorderedlist|numbering,,insertorderedlist|outdent,,|indent,,|alignleft,Align Text Left,justifyleft|center,,justifycenter|alignright,Align Text Right,justifyright|justify,,justifyfull|undo,,|redo,,|rule,Insert Horizontal Rule,inserthorizontalrule|image,Insert Image,insertimage,url|link,Insert Hyperlink,createlink,url|unlink,Remove Hyperlink,|cut,,|copy,,|paste,,|pastetext,Paste as Text,inserthtml,|print,,|source,Show Source"},
|
||||
imagesPath:function(){return U()}};e.fn.cleditor=function(a){var b=e([]);this.each(function(c,d){if(d.tagName=="TEXTAREA"){var h=e.data(d,Y);h||(h=new cleditor(d,a));b=b.add(h)}});return b};var H="backgroundColor",A="button",x="buttonName",F="change",Y="cleditor",q="click",n="disabled",m="<div>",I="unselectable",W="cleditorButton",X="cleditorDisabled",ca="cleditorPopup",S="cleditorList",da="cleditorColor",B="cleditorPrompt",fa="cleditorMsg",l=e.browser.msie,ea=/msie\s6/i.test(navigator.userAgent),
|
||||
L=/iphone|ipad|ipod/i.test(navigator.userAgent),p={},Z,s=e.cleditor.buttons;e.each(s.init.split("|"),function(a,b){var c=b.split(","),d=c[0];s[d]={stripIndex:a,name:d,title:c[1]===""?d.charAt(0).toUpperCase()+d.substr(1):c[1],command:c[2]===""?d:c[2],popupName:c[3]===""?d:c[3]}});delete s.init;cleditor=function(a,b){var c=this;c.options=b=e.extend({},e.cleditor.defaultOptions,b);var d=c.$area=e(a).hide().data(Y,c).blur(function(){E(c,true)}),h=c.$main=e(m).addClass("cleditorMain").width(b.width).height(b.height),
|
||||
f=c.$toolbar=e(m).addClass("cleditorToolbar").appendTo(h),i=e(m).addClass("cleditorGroup").appendTo(f);e.each(b.controls.split(" "),function(g,j){if(j==="")return true;if(j=="|"){e(m).addClass("cleditorDivider").appendTo(i);i=e(m).addClass("cleditorGroup").appendTo(f)}else{var k=s[j],o=e(m).data(x,k.name).addClass(W).attr("title",k.title).bind(q,e.proxy(aa,c)).appendTo(i).hover(O,P),G={};if(k.css)G=k.css;else if(k.image)G.backgroundImage="url("+U()+k.image+")";if(k.stripIndex)G.backgroundPosition=
|
||||
k.stripIndex*-24;o.css(G);l&&o.attr(I,"on");k.popupName&&R(k.popupName,b,k.popupClass,k.popupContent,k.popupHover)}});h.insertBefore(d).append(d);if(!Z){e(document).click(function(g){g=e(g.target);g.add(g.parents()).is("."+B)||r()});Z=true}/auto|%/.test(""+b.width+b.height)&&e(window).resize(function(){K(c)});K(c)};var $=cleditor.prototype;e.each([["clear",function(a){a.$area.val("");E(a)}],["disable",T],["execCommand",v],["focus",w],["hidePopups",r],["sourceMode",t,true],["refresh",K],["select",
|
||||
function(a){setTimeout(function(){t(a)?a.$area.select():v(a,"selectall")},0)}],["selectedHTML",function(a){D(a);a=y(a);if(l)return a.htmlText;var b=e("<layer>")[0];b.appendChild(a.cloneContents());return b.innerHTML},true],["selectedText",M,true],["showMessage",z],["updateFrame",E],["updateTextArea",V]],function(a,b){$[b[0]]=function(){for(var c=[this],d=0;d<arguments.length;d++)c.push(arguments[d]);c=b[1].apply(this,c);if(b[2])return c;return this}});$.change=function(a){var b=e(this);return a?b.bind(F,
|
||||
a):b.trigger(F)}})(jQuery);
|
|
@ -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");
|
||||
|
@ -1448,20 +1448,31 @@
|
|||
filter: alpha(opacity=50);
|
||||
opacity: 0.5;
|
||||
}
|
||||
.openerp .oe_searchview .oe_searchview_search {
|
||||
font-size: 1px;
|
||||
letter-spacing: -1px;
|
||||
color: transparent;
|
||||
-moz-box-shadow: none;
|
||||
-webkit-box-shadow: none;
|
||||
box-shadow: none;
|
||||
-moz-border-radius: 0;
|
||||
-webkit-border-radius: 0;
|
||||
border-radius: 0;
|
||||
position: absolute;
|
||||
left: 3px;
|
||||
top: 1px;
|
||||
padding: 0;
|
||||
border: none;
|
||||
background: transparent;
|
||||
}
|
||||
.openerp .oe_searchview .oe_searchview_search:before {
|
||||
font: 21px "mnmliconsRegular";
|
||||
content: "r";
|
||||
color: #a3a3a3;
|
||||
}
|
||||
.openerp .oe_searchview .oe_searchview_facets {
|
||||
min-height: 22px;
|
||||
}
|
||||
.openerp .oe_searchview .oe_searchview_facets:before {
|
||||
color: #cccccc;
|
||||
font-family: "mnmliconsRegular";
|
||||
content: "r";
|
||||
font-size: 130%;
|
||||
display: inline;
|
||||
position: relative;
|
||||
left: 6px;
|
||||
top: 2px;
|
||||
color: #a3a3a3;
|
||||
padding-right: 4px;
|
||||
margin-left: 15px;
|
||||
}
|
||||
.openerp .oe_searchview .oe_searchview_facets * {
|
||||
vertical-align: top;
|
||||
|
@ -2220,9 +2231,33 @@
|
|||
height: auto;
|
||||
line-height: 16px;
|
||||
}
|
||||
.openerp .oe_form_field_one2many .oe_list_buttons.oe_editing .oe_list_save, .openerp .oe_form_field_many2many .oe_list_buttons.oe_editing .oe_list_save {
|
||||
visibility: hidden;
|
||||
}
|
||||
.openerp .oe_form .oe_form_field_many2many > .oe_list .oe_list_pager_single_page {
|
||||
display: none;
|
||||
}
|
||||
.openerp .oe_list_buttons .oe_list_save, .openerp .oe_list_buttons .oe_list_discard {
|
||||
display: none;
|
||||
}
|
||||
.openerp .oe_list_buttons.oe_editing .oe_list_add, .openerp .oe_list_buttons.oe_editing .oe_list_button_import {
|
||||
display: none;
|
||||
}
|
||||
.openerp .oe_list_buttons.oe_editing .oe_list_save {
|
||||
display: inline-block;
|
||||
}
|
||||
.openerp .oe_list_buttons.oe_editing .oe_list_discard {
|
||||
display: inline;
|
||||
}
|
||||
.openerp .oe_list {
|
||||
position: relative;
|
||||
}
|
||||
.openerp .oe_list .oe_form .oe_form_field {
|
||||
width: auto;
|
||||
position: absolute;
|
||||
margin: 0 !important;
|
||||
padding: 0;
|
||||
}
|
||||
.openerp .oe_list_content {
|
||||
width: 100%;
|
||||
}
|
||||
|
@ -2280,9 +2315,7 @@
|
|||
}
|
||||
.openerp .oe_list_content > tbody > tr > td.oe_list_field_cell {
|
||||
padding: 3px 6px;
|
||||
}
|
||||
.openerp .oe_list_content > tbody > tr > td.oe_list_field_cell progress {
|
||||
width: 100%;
|
||||
white-space: pre-line;
|
||||
}
|
||||
.openerp .oe_list_content > tbody > tr > td > button, .openerp .oe_list_content > tbody > tr > th > button {
|
||||
border: none;
|
||||
|
@ -2330,9 +2363,6 @@
|
|||
.openerp .oe_list_content .numeric input {
|
||||
text-align: right;
|
||||
}
|
||||
.openerp .oe_list_content .oe_list_edit_row_save:before {
|
||||
content: "S";
|
||||
}
|
||||
.openerp .oe_trad_field.touched {
|
||||
border: 1px solid green !important;
|
||||
}
|
||||
|
|
|
@ -92,9 +92,8 @@ $sheet-max-width: 860px
|
|||
letter-spacing: -1px
|
||||
color: transparent
|
||||
&:before
|
||||
font-family: "mnmliconsRegular"
|
||||
font: 21px "mnmliconsRegular"
|
||||
content: $icon-name
|
||||
font-size: 20px
|
||||
color: $color
|
||||
|
||||
// }}}
|
||||
|
@ -1126,19 +1125,20 @@ $sheet-max-width: 860px
|
|||
border-right: 5px solid transparent
|
||||
@include opacity()
|
||||
|
||||
.oe_searchview_search
|
||||
@include text-to-icon("r", #a3a3a3)
|
||||
@include box-shadow(none)
|
||||
@include radius(0)
|
||||
position: absolute
|
||||
left: 3px
|
||||
top: 1px
|
||||
padding: 0
|
||||
border: none
|
||||
background: transparent
|
||||
|
||||
.oe_searchview_facets
|
||||
min-height: 22px
|
||||
&:before
|
||||
color: #ccc
|
||||
font-family: "mnmliconsRegular"
|
||||
content: "r"
|
||||
font-size: 130%
|
||||
display: inline
|
||||
position: relative
|
||||
left: 6px
|
||||
top: 2px
|
||||
color: #a3a3a3
|
||||
padding-right: 4px
|
||||
margin-left: 15px
|
||||
*
|
||||
vertical-align: top
|
||||
display: inline-block
|
||||
|
@ -1745,6 +1745,9 @@ $sheet-max-width: 860px
|
|||
li
|
||||
height: auto
|
||||
line-height: 16px
|
||||
.oe_list_buttons.oe_editing .oe_list_save
|
||||
// keep "save row" button hidden in o2m
|
||||
visibility: hidden
|
||||
// }}}
|
||||
// FormView.many2many {{{
|
||||
.oe_form .oe_form_field_many2many > .oe_list
|
||||
|
@ -1752,6 +1755,25 @@ $sheet-max-width: 860px
|
|||
display: none
|
||||
// }}}
|
||||
// ListView {{{
|
||||
.oe_list_buttons
|
||||
.oe_list_save, .oe_list_discard
|
||||
display: none
|
||||
&.oe_editing
|
||||
.oe_list_add, .oe_list_button_import
|
||||
display: none
|
||||
.oe_list_save
|
||||
display: inline-block
|
||||
.oe_list_discard
|
||||
display: inline
|
||||
|
||||
.oe_list
|
||||
position: relative
|
||||
.oe_form .oe_form_field
|
||||
width: auto
|
||||
position: absolute
|
||||
margin: 0 !important // dammit
|
||||
padding: 0
|
||||
|
||||
.oe_list_content
|
||||
width: 100%
|
||||
td:first-child, th:first-child
|
||||
|
@ -1795,8 +1817,7 @@ $sheet-max-width: 860px
|
|||
border-top: 1px solid #ddd
|
||||
> td.oe_list_field_cell
|
||||
padding: 3px 6px
|
||||
progress
|
||||
width: 100%
|
||||
white-space: pre-line
|
||||
> td, > th
|
||||
> button
|
||||
border: none
|
||||
|
@ -1824,8 +1845,6 @@ $sheet-max-width: 860px
|
|||
width: 82px
|
||||
input
|
||||
text-align: right
|
||||
.oe_list_edit_row_save:before
|
||||
content: "S"
|
||||
// }}}
|
||||
// Translation {{{
|
||||
.oe_trad_field.touched
|
||||
|
@ -1934,6 +1953,7 @@ $sheet-max-width: 860px
|
|||
background-attachment: fixed
|
||||
>*
|
||||
opacity: 0.70
|
||||
|
||||
// }}}
|
||||
|
||||
div.ui-widget-overlay
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 7.0 KiB |
|
@ -24,7 +24,7 @@
|
|||
init: function(modules) {
|
||||
// By default only web will be loaded, the rest will be by loaded
|
||||
// by openerp.web.Session on the first session_authenticate
|
||||
modules = modules || ["web"];
|
||||
modules = _.union(['web'], modules || []);
|
||||
var new_instance = {
|
||||
// links to the global openerp
|
||||
_openerp: openerp,
|
||||
|
|
|
@ -135,8 +135,12 @@ instance.web.Dialog = instance.web.Widget.extend({
|
|||
this.$element.dialog('close');
|
||||
},
|
||||
on_close: function() {
|
||||
if (this.__tmp_dialog_destroying)
|
||||
return;
|
||||
if (this.dialog_options.destroy_on_close) {
|
||||
this.__tmp_dialog_closing = true;
|
||||
this.destroy();
|
||||
this.__tmp_dialog_closing = undefined;
|
||||
}
|
||||
},
|
||||
on_resized: function() {
|
||||
|
@ -145,6 +149,11 @@ instance.web.Dialog = instance.web.Widget.extend({
|
|||
_.each(this.getChildren(), function(el) {
|
||||
el.destroy();
|
||||
});
|
||||
if (! this.__tmp_dialog_closing) {
|
||||
this.__tmp_dialog_destroying = true;
|
||||
this.close();
|
||||
this.__tmp_dialog_destroying = undefined;
|
||||
}
|
||||
if (! this.isDestroyed()) {
|
||||
this.$element.dialog('destroy');
|
||||
}
|
||||
|
@ -248,13 +257,17 @@ instance.web.Loading = instance.web.Widget.extend({
|
|||
// Block UI after 3s
|
||||
this.long_running_timer = setTimeout(function () {
|
||||
self.blocked_ui = true;
|
||||
$.blockUI();
|
||||
instance.web.blockUI();
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
this.count += increment;
|
||||
if (this.count > 0) {
|
||||
this.$element.text(_.str.sprintf( _t("Loading (%d)"), this.count));
|
||||
if (instance.connection.debug) {
|
||||
this.$element.text(_.str.sprintf( _t("Loading (%d)"), this.count));
|
||||
} else {
|
||||
this.$element.text(_t("Loading"));
|
||||
}
|
||||
this.$element.show();
|
||||
this.getParent().$element.addClass('oe_wait');
|
||||
} else {
|
||||
|
@ -263,7 +276,7 @@ instance.web.Loading = instance.web.Widget.extend({
|
|||
// Don't unblock if blocked by somebody else
|
||||
if (self.blocked_ui) {
|
||||
this.blocked_ui = false;
|
||||
$.unblockUI();
|
||||
instance.web.unblockUI();
|
||||
}
|
||||
this.$element.fadeOut();
|
||||
this.getParent().$element.removeClass('oe_wait');
|
||||
|
@ -274,7 +287,7 @@ instance.web.Loading = instance.web.Widget.extend({
|
|||
instance.web.DatabaseManager = instance.web.Widget.extend({
|
||||
init: function(parent) {
|
||||
this._super(parent);
|
||||
this.unblockUIFunction = $.unblockUI;
|
||||
this.unblockUIFunction = instance.web.unblockUI;
|
||||
$.validator.addMethod('matches', function (s, _, re) {
|
||||
return new RegExp(re).test(s);
|
||||
}, _t("Invalid database name"));
|
||||
|
@ -341,16 +354,16 @@ instance.web.DatabaseManager = instance.web.Widget.extend({
|
|||
* from unblocking the UI
|
||||
*/
|
||||
blockUI: function () {
|
||||
$.blockUI();
|
||||
$.unblockUI = function () {};
|
||||
instance.web.blockUI();
|
||||
instance.web.unblockUI = function () {};
|
||||
},
|
||||
/**
|
||||
* Reinstates $.unblockUI so third parties can play with blockUI, and
|
||||
* unblocks the UI
|
||||
*/
|
||||
unblockUI: function () {
|
||||
$.unblockUI = this.unblockUIFunction;
|
||||
$.unblockUI();
|
||||
instance.web.unblockUI = this.unblockUIFunction;
|
||||
instance.web.unblockUI();
|
||||
},
|
||||
/**
|
||||
* Displays an error dialog resulting from the various RPC communications
|
||||
|
@ -856,44 +869,24 @@ instance.web.UserMenu = instance.web.Widget.extend({
|
|||
},
|
||||
});
|
||||
|
||||
instance.web.WebClient = instance.web.Widget.extend({
|
||||
init: function(parent) {
|
||||
var self = this;
|
||||
instance.web.Client = instance.web.Widget.extend({
|
||||
init: function(parent, origin) {
|
||||
instance.client = instance.webclient = this;
|
||||
this._super(parent);
|
||||
instance.webclient = this;
|
||||
this.querystring = '?' + jQuery.param.querystring();
|
||||
this._current_state = null;
|
||||
},
|
||||
_get_version_label: function() {
|
||||
if (this.session.openerp_entreprise) {
|
||||
return 'OpenERP';
|
||||
} else {
|
||||
return _t("OpenERP - Unsupported/Community Version");
|
||||
}
|
||||
},
|
||||
set_title: function(title) {
|
||||
title = _.str.clean(title);
|
||||
var sep = _.isEmpty(title) ? '' : ' - ';
|
||||
document.title = title + sep + 'OpenERP';
|
||||
this.origin = origin;
|
||||
},
|
||||
start: function() {
|
||||
var self = this;
|
||||
this.$element.addClass("openerp openerp_webclient_container");
|
||||
if (jQuery.param !== undefined && jQuery.deparam(jQuery.param.querystring()).kitten !== undefined) {
|
||||
$("body").addClass("kitten-mode-activated");
|
||||
if ($.blockUI) {
|
||||
$.blockUI.defaults.message = '<img src="http://www.amigrave.com/kitten.gif">';
|
||||
}
|
||||
}
|
||||
this.session.session_bind().then(function() {
|
||||
self.destroy_content();
|
||||
return instance.connection.session_bind(this.origin).then(function() {
|
||||
var $e = $(QWeb.render(self._template, {}));
|
||||
self.$element.replaceWith($e);
|
||||
self.$element = $e;
|
||||
self.bind_events();
|
||||
self.show_common();
|
||||
if (!self.session.session_is_valid()) {
|
||||
self.show_login();
|
||||
} else {
|
||||
self.show_application();
|
||||
}
|
||||
});
|
||||
},
|
||||
bind_events: function() {
|
||||
var self = this;
|
||||
this.$element.on('mouseenter', '.oe_systray > div:not([data-tipsy=true])', function() {
|
||||
$(this).attr('data-tipsy', 'true').tipsy().trigger('mouseenter');
|
||||
});
|
||||
|
@ -925,6 +918,45 @@ instance.web.WebClient = instance.web.Widget.extend({
|
|||
var self = this;
|
||||
this.crashmanager = new instance.web.CrashManager();
|
||||
instance.connection.on_rpc_error.add(this.crashmanager.on_rpc_error);
|
||||
self.notification = new instance.web.Notification(this);
|
||||
self.notification.appendTo(self.$element);
|
||||
self.loading = new instance.web.Loading(self);
|
||||
self.loading.appendTo(self.$element);
|
||||
self.action_manager = new instance.web.ActionManager(self);
|
||||
self.action_manager.appendTo(self.$('.oe_application'));
|
||||
},
|
||||
});
|
||||
|
||||
instance.web.WebClient = instance.web.Client.extend({
|
||||
_template: 'WebClient',
|
||||
init: function(parent) {
|
||||
this._super(parent);
|
||||
this._current_state = null;
|
||||
},
|
||||
start: function() {
|
||||
var self = this;
|
||||
return $.when(this._super()).pipe(function() {
|
||||
if (jQuery.param !== undefined && jQuery.deparam(jQuery.param.querystring()).kitten !== undefined) {
|
||||
$("body").addClass("kitten-mode-activated");
|
||||
if ($.blockUI) {
|
||||
$.blockUI.defaults.message = '<img src="http://www.amigrave.com/kitten.gif">';
|
||||
}
|
||||
}
|
||||
if (!self.session.session_is_valid()) {
|
||||
self.show_login();
|
||||
} else {
|
||||
self.show_application();
|
||||
}
|
||||
});
|
||||
},
|
||||
set_title: function(title) {
|
||||
title = _.str.clean(title);
|
||||
var sep = _.isEmpty(title) ? '' : ' - ';
|
||||
document.title = title + sep + 'OpenERP';
|
||||
},
|
||||
show_common: function() {
|
||||
var self = this;
|
||||
this._super();
|
||||
window.onerror = function (message, file, line) {
|
||||
self.crashmanager.on_traceback({
|
||||
type: _t("Client Error"),
|
||||
|
@ -932,23 +964,18 @@ instance.web.WebClient = instance.web.Widget.extend({
|
|||
data: {debug: file + ':' + line}
|
||||
});
|
||||
};
|
||||
self.notification = new instance.web.Notification(this);
|
||||
self.notification.appendTo(self.$element);
|
||||
self.loading = new instance.web.Loading(self);
|
||||
self.loading.appendTo(self.$element);
|
||||
// TODO: deprecate and use login client action
|
||||
self.login = new instance.web.Login(self);
|
||||
self.login.on("login",self,self.show_application);
|
||||
self.$table = $(QWeb.render("WebClient", {}));
|
||||
self.action_manager = new instance.web.ActionManager(self);
|
||||
self.action_manager.appendTo(self.$table.find('.oe_application'));
|
||||
},
|
||||
show_login: function() {
|
||||
var self = this;
|
||||
self.$('.oe_topbar').hide();
|
||||
self.login.appendTo(self.$element);
|
||||
},
|
||||
show_application: function() {
|
||||
var self = this;
|
||||
self.$element.append(self.$table);
|
||||
self.$('.oe_topbar').show();
|
||||
self.login.$element.hide();
|
||||
self.menu = new instance.web.Menu(self);
|
||||
self.menu.replace(this.$element.find('.oe_menu_placeholder'));
|
||||
|
@ -960,7 +987,7 @@ instance.web.WebClient = instance.web.Widget.extend({
|
|||
self.user_menu.do_update();
|
||||
self.bind_hashchange();
|
||||
if (!self.session.openerp_entreprise) {
|
||||
var version_label = self._get_version_label();
|
||||
var version_label = _t("OpenERP - Unsupported/Community Version");
|
||||
self.$element.find('.oe_footer_powered').append(_.str.sprintf('<span> - <a href="http://www.openerp.com/support-or-publisher-warranty-contract" target="_blank">%s</a></span>', version_label));
|
||||
}
|
||||
self.set_title();
|
||||
|
@ -1063,31 +1090,36 @@ instance.web.WebClient = instance.web.Widget.extend({
|
|||
}
|
||||
});
|
||||
|
||||
instance.web.EmbeddedClient = instance.web.Widget.extend({
|
||||
template: 'EmptyComponent',
|
||||
init: function(parent, action_id, options) {
|
||||
this._super(parent);
|
||||
// TODO take the xmlid of a action instead of its id
|
||||
instance.web.EmbeddedClient = instance.web.Client.extend({
|
||||
_template: 'EmbedClient',
|
||||
init: function(parent, origin, dbname, login, key, action_id, options) {
|
||||
this._super(parent, origin);
|
||||
|
||||
this.dbname = dbname;
|
||||
this.login = login;
|
||||
this.key = key;
|
||||
this.action_id = action_id;
|
||||
this.options = options || {};
|
||||
this.am = new instance.web.ActionManager(this);
|
||||
},
|
||||
start: function() {
|
||||
var self = this;
|
||||
this.am.appendTo(this.$element.addClass('openerp'));
|
||||
return this.rpc("/web/action/load", { action_id: this.action_id }, function(result) {
|
||||
var action = result.result;
|
||||
action.flags = _.extend({
|
||||
//views_switcher : false,
|
||||
search_view : false,
|
||||
action_buttons : false,
|
||||
sidebar : false
|
||||
//pager : false
|
||||
}, self.options, action.flags || {});
|
||||
return $.when(this._super()).pipe(function() {
|
||||
return instance.connection.session_authenticate(self.dbname, self.login, self.key, true).pipe(function() {
|
||||
return self.rpc("/web/action/load", { action_id: self.action_id }, function(result) {
|
||||
var action = result.result;
|
||||
action.flags = _.extend({
|
||||
//views_switcher : false,
|
||||
search_view : false,
|
||||
action_buttons : false,
|
||||
sidebar : false
|
||||
//pager : false
|
||||
}, self.options, action.flags || {});
|
||||
|
||||
self.am.do_action(action);
|
||||
self.action_manager.do_action(action);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
instance.web.embed = function (origin, dbname, login, key, action, options) {
|
||||
|
@ -1101,13 +1133,8 @@ instance.web.embed = function (origin, dbname, login, key, action, options) {
|
|||
var sc = document.getElementsByTagName('script');
|
||||
currentScript = sc[sc.length-1];
|
||||
}
|
||||
instance.connection.session_bind(origin).then(function () {
|
||||
instance.connection.session_authenticate(dbname, login, key, true).then(function () {
|
||||
var client = new instance.web.EmbeddedClient(null, action, options);
|
||||
client.insertAfter(currentScript);
|
||||
});
|
||||
});
|
||||
|
||||
var client = new instance.web.EmbeddedClient(null, origin, dbname, login, key, action, options);
|
||||
client.insertAfter(currentScript);
|
||||
};
|
||||
|
||||
};
|
||||
|
|
|
@ -550,7 +550,39 @@ $.async_when = function() {
|
|||
/** Setup blockui */
|
||||
if ($.blockUI) {
|
||||
$.blockUI.defaults.baseZ = 1100;
|
||||
$.blockUI.defaults.message = '<img src="/web/static/src/img/throbber2.gif">';
|
||||
$.blockUI.defaults.message = '<div class="oe_blockui_spin" style="height: 50px">';
|
||||
$.blockUI.defaults.css.border = '0';
|
||||
$.blockUI.defaults.css["background-color"] = '';
|
||||
$.blockUI.spinners = [];
|
||||
}
|
||||
instance.web.blockUI = function() {
|
||||
var tmp = $.blockUI.apply($, arguments);
|
||||
var target = $(".oe_blockui_spin")[0];
|
||||
var opts = {
|
||||
lines: 13, // The number of lines to draw
|
||||
length: 7, // The length of each line
|
||||
width: 4, // The line thickness
|
||||
radius: 10, // The radius of the inner circle
|
||||
rotate: 0, // The rotation offset
|
||||
color: '#FFF', // #rgb or #rrggbb
|
||||
speed: 1, // Rounds per second
|
||||
trail: 60, // Afterglow percentage
|
||||
shadow: false, // Whether to render a shadow
|
||||
hwaccel: false, // Whether to use hardware acceleration
|
||||
className: 'spinner', // The CSS class to assign to the spinner
|
||||
zIndex: 2e9, // The z-index (defaults to 2000000000)
|
||||
top: 'auto', // Top position relative to parent in px
|
||||
left: 'auto' // Left position relative to parent in px
|
||||
};
|
||||
var spinner = new Spinner(opts).spin(target);
|
||||
$.blockUI.spinners.push(spinner);
|
||||
return tmp;
|
||||
}
|
||||
instance.web.unblockUI = function() {
|
||||
_.each($.blockUI.spinners, function(el) {
|
||||
el.stop();
|
||||
});
|
||||
return $.unblockUI.apply($, arguments);
|
||||
}
|
||||
|
||||
/** Setup default session */
|
||||
|
|
|
@ -376,7 +376,7 @@ instance.web.DataExport = instance.web.Dialog.extend({
|
|||
|
||||
exported_fields.unshift({name: 'id', label: 'External ID'});
|
||||
var export_format = this.$element.find("#export_format").val();
|
||||
$.blockUI();
|
||||
instance.web.blockUI();
|
||||
this.session.get_file({
|
||||
url: '/web/export/' + export_format,
|
||||
data: {data: JSON.stringify({
|
||||
|
@ -387,7 +387,7 @@ instance.web.DataExport = instance.web.Dialog.extend({
|
|||
import_compat: Boolean(
|
||||
this.$element.find("#import_compat").val())
|
||||
})},
|
||||
complete: $.unblockUI
|
||||
complete: instance.web.unblockUI
|
||||
});
|
||||
},
|
||||
close: function() {
|
||||
|
|
|
@ -330,6 +330,12 @@ instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.Sea
|
|||
});
|
||||
}
|
||||
|
||||
// Launch a search on clicking the oe_searchview_search button
|
||||
this.$element.on('click', 'button.oe_searchview_search', function (e) {
|
||||
e.stopImmediatePropagation();
|
||||
self.do_search();
|
||||
});
|
||||
|
||||
this.$element.on('keydown',
|
||||
'.oe_searchview_input, .oe_searchview_facet', function (e) {
|
||||
switch(e.which) {
|
||||
|
@ -1475,7 +1481,17 @@ instance.web.search.ManyToOneField = instance.web.search.CharField.extend({
|
|||
facet_for: function (value) {
|
||||
var self = this;
|
||||
if (value instanceof Array) {
|
||||
return $.when(facet_from(this, value));
|
||||
if (value.length === 2 && _.isString(value[1])) {
|
||||
return $.when(facet_from(this, value));
|
||||
}
|
||||
if (value.length > 1) {
|
||||
// more than one search_default m2o id? Should we OR them?
|
||||
throw new Error(
|
||||
_("M2O search fields do not currently handle multiple default values"));
|
||||
}
|
||||
// there are many cases of {search_default_$m2ofield: [id]}, need
|
||||
// to handle this as if it were a single value.
|
||||
value = value[0];
|
||||
}
|
||||
return this.model.call('name_get', [value], {}).pipe(function (names) {
|
||||
if (_(names).isEmpty()) { return null; }
|
||||
|
@ -1669,6 +1685,7 @@ instance.web.search.AddToDashboard = instance.web.Widget.extend({
|
|||
return $.when(this.load_data(),this.data_loaded).pipe(this.proxy("render_data"));
|
||||
},
|
||||
load_data:function(){
|
||||
if (!instance.webclient) { return $.Deferred().reject(); }
|
||||
var self = this,dashboard_menu = instance.webclient.menu.data.data.children;
|
||||
var ir_model_data = new instance.web.Model('ir.model.data',{},[['name','=','menu_reporting_dashboard']]).query(['res_id']);
|
||||
var map_data = function(result){
|
||||
|
|
|
@ -80,7 +80,7 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
|
|||
this.reload_mutex = new $.Mutex();
|
||||
this.__clicked_inside = false;
|
||||
this.__blur_timeout = null;
|
||||
this.rendering_engine = new instance.web.form.FormRenderingEngineReadonly(this);
|
||||
this.rendering_engine = new instance.web.form.FormRenderingEngine(this);
|
||||
this.qweb = null; // A QWeb instance will be created if the view is a QWeb template
|
||||
},
|
||||
destroy: function() {
|
||||
|
@ -239,6 +239,13 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
|
|||
}
|
||||
}
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {Object} [options]
|
||||
* @param {Boolean} [editable=false] whether the form should be switched to edition mode. A value of ``false`` will keep the current mode.
|
||||
* @param {Boolean} [reload=true] whether the form should reload its content on show, or use the currently loaded record
|
||||
* @return {$.Deferred}
|
||||
*/
|
||||
do_show: function (options) {
|
||||
var self = this;
|
||||
options = options || {};
|
||||
|
@ -253,23 +260,24 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
|
|||
}
|
||||
this.$element.show().css('visibility', 'hidden');
|
||||
this.$element.add(this.$buttons).removeClass('oe_form_dirty');
|
||||
return this.has_been_loaded.pipe(function() {
|
||||
var result;
|
||||
if (self.dataset.index === null) {
|
||||
// null index means we should start a new record
|
||||
result = self.on_button_new();
|
||||
} else {
|
||||
result = self.dataset.read_index(_.keys(self.fields_view.fields), {
|
||||
context : { 'bin_size' : true }
|
||||
}).pipe(self.on_record_loaded);
|
||||
}
|
||||
result.pipe(function() {
|
||||
if (options.editable) {
|
||||
self.set({mode: "edit"});
|
||||
|
||||
var shown = this.has_been_loaded;
|
||||
if (options.reload !== false) {
|
||||
shown = shown.pipe(function() {
|
||||
if (self.dataset.index === null) {
|
||||
// null index means we should start a new record
|
||||
return self.on_button_new();
|
||||
}
|
||||
self.$element.css('visibility', 'visible');
|
||||
return self.dataset.read_index(_.keys(self.fields_view.fields), {
|
||||
context: { 'bin_size': true }
|
||||
}).pipe(self.on_record_loaded);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
return shown.pipe(function() {
|
||||
if (options.editable) {
|
||||
self.set({mode: "edit"});
|
||||
}
|
||||
self.$element.css('visibility', 'visible');
|
||||
});
|
||||
},
|
||||
do_hide: function () {
|
||||
|
@ -330,6 +338,20 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
|
|||
self.$element.add(self.$buttons).removeClass('oe_form_dirty');
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Loads and sets up the default values for the model as the current
|
||||
* record
|
||||
*
|
||||
* @return {$.Deferred}
|
||||
*/
|
||||
load_defaults: function () {
|
||||
var keys = _.keys(this.fields_view.fields);
|
||||
if (keys.length) {
|
||||
return this.dataset.default_get(keys)
|
||||
.pipe(this.on_record_loaded);
|
||||
}
|
||||
return this.on_record_loaded({});
|
||||
},
|
||||
on_form_changed: function() {
|
||||
this.trigger("view_content_has_changed");
|
||||
},
|
||||
|
@ -600,22 +622,11 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
|
|||
on_button_new: function() {
|
||||
var self = this;
|
||||
this.set({mode: "edit"});
|
||||
var def = $.Deferred();
|
||||
$.when(this.has_been_loaded).then(function() {
|
||||
return $.when(this.has_been_loaded).pipe(function() {
|
||||
if (self.can_be_discarded()) {
|
||||
var keys = _.keys(self.fields_view.fields);
|
||||
if (keys.length) {
|
||||
self.dataset.default_get(keys).pipe(self.on_record_loaded).then(function() {
|
||||
def.resolve();
|
||||
});
|
||||
} else {
|
||||
self.on_record_loaded({}).then(function() {
|
||||
def.resolve();
|
||||
});
|
||||
}
|
||||
return self.load_defaults();
|
||||
}
|
||||
});
|
||||
return def.promise();
|
||||
},
|
||||
on_button_edit: function() {
|
||||
return this.set({mode: "edit"});
|
||||
|
@ -674,13 +685,14 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
|
|||
values = {},
|
||||
first_invalid_field = null;
|
||||
for (var f in self.fields) {
|
||||
if (!self.fields.hasOwnProperty(f)) { continue; }
|
||||
f = self.fields[f];
|
||||
if (!f.is_valid()) {
|
||||
form_invalid = true;
|
||||
if (!first_invalid_field) {
|
||||
first_invalid_field = f;
|
||||
}
|
||||
} else if (f.name !== 'id' && !f.get("readonly") && (!self.datarecord.id || f._dirty_flag)) {
|
||||
} else if (f.name !== 'id' && (!self.datarecord.id || (!f.get("readonly") && f._dirty_flag))) {
|
||||
// Special case 'id' field, do not save this field
|
||||
// on 'create' : save all non readonly fields
|
||||
// on 'edit' : save non readonly modified fields
|
||||
|
@ -689,8 +701,9 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
|
|||
}
|
||||
if (form_invalid) {
|
||||
self.set({'display_invalid_fields': true});
|
||||
for (var f in self.fields) {
|
||||
self.fields[f]._check_css_flags();
|
||||
for (var g in self.fields) {
|
||||
if (!self.fields.hasOwnProperty(g)) { continue; }
|
||||
self.fields[g]._check_css_flags();
|
||||
}
|
||||
first_invalid_field.focus();
|
||||
self.on_invalid();
|
||||
|
@ -722,14 +735,15 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
|
|||
});});
|
||||
},
|
||||
on_invalid: function() {
|
||||
var msg = "<ul>";
|
||||
_.each(this.fields, function(f) {
|
||||
if (!f.is_valid()) {
|
||||
msg += "<li>" + f.string + "</li>";
|
||||
}
|
||||
});
|
||||
msg += "</ul>";
|
||||
this.do_warn("The following fields are invalid :", msg);
|
||||
var warnings = _(this.fields).chain()
|
||||
.filter(function (f) { return !f.is_valid(); })
|
||||
.map(function (f) {
|
||||
return _.str.sprintf('<li>%s</li>',
|
||||
_.escape(f.string));
|
||||
}).value();
|
||||
warnings.unshift('<ul>');
|
||||
warnings.push('</ul>');
|
||||
this.do_warn("The following fields are invalid :", warnings.join(''));
|
||||
},
|
||||
on_saved: function(r, success) {
|
||||
if (!r.result) {
|
||||
|
@ -807,10 +821,10 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
|
|||
var ids = this.get_selected_ids();
|
||||
values["id"] = ids.length > 0 ? ids[0] : false;
|
||||
_.each(this.fields, function(value_, key) {
|
||||
if (_.include(blacklist, key))
|
||||
if (_.include(blacklist, key)) {
|
||||
return;
|
||||
var val = value_.get_value();
|
||||
values[key] = val;
|
||||
}
|
||||
values[key] = value_.get_value();
|
||||
});
|
||||
return values;
|
||||
},
|
||||
|
@ -865,6 +879,9 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
|
|||
return option[0] === value;
|
||||
})[1];
|
||||
break;
|
||||
case 'many2one':
|
||||
displayed = field.get_displayed();
|
||||
break;
|
||||
}
|
||||
|
||||
return {
|
||||
|
@ -942,6 +959,9 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
|
|||
is_create_mode: function() {
|
||||
return !this.datarecord.id;
|
||||
},
|
||||
open_translate_dialog: function(field) {
|
||||
return this._super(field);
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
|
@ -985,7 +1005,6 @@ instance.web.form.FormRenderingEngine = instance.web.form.FormRenderingEngineInt
|
|||
}
|
||||
});
|
||||
}
|
||||
selector = 'form[version!="7.0"] page,form[version!="7.0"]';
|
||||
},
|
||||
render_to: function($target) {
|
||||
var self = this;
|
||||
|
@ -1119,7 +1138,7 @@ instance.web.form.FormRenderingEngine = instance.web.form.FormRenderingEngineInt
|
|||
if (found)
|
||||
return;
|
||||
|
||||
$label = $('<label/>').attr({
|
||||
var $label = $('<label/>').attr({
|
||||
'for' : name,
|
||||
"modifiers": JSON.stringify({invisible: field_modifiers.invisible}),
|
||||
"string": $field.attr('string'),
|
||||
|
@ -1212,12 +1231,6 @@ instance.web.form.FormRenderingEngine = instance.web.form.FormRenderingEngineInt
|
|||
$child = $td.children(':first');
|
||||
switch ($child[0].tagName.toLowerCase()) {
|
||||
case 'separator':
|
||||
if ($child.attr('orientation') === 'vertical') {
|
||||
$td.addClass('oe_vertical_separator').attr('width', '1');
|
||||
$td.empty();
|
||||
row_cols-= $td.attr('colspan') || 1;
|
||||
total--;
|
||||
}
|
||||
break;
|
||||
case 'label':
|
||||
if ($child.attr('for')) {
|
||||
|
@ -1339,7 +1352,7 @@ instance.web.form.FormRenderingEngine = instance.web.form.FormRenderingEngineInt
|
|||
return $new_label;
|
||||
},
|
||||
handle_common_properties: function($new_element, $node) {
|
||||
var str_modifiers = $node.attr("modifiers") || "{}"
|
||||
var str_modifiers = $node.attr("modifiers") || "{}";
|
||||
var modifiers = JSON.parse(str_modifiers);
|
||||
var ic = null;
|
||||
if (modifiers.invisible !== undefined)
|
||||
|
@ -1350,12 +1363,6 @@ instance.web.form.FormRenderingEngine = instance.web.form.FormRenderingEngineInt
|
|||
},
|
||||
});
|
||||
|
||||
instance.web.form.FormRenderingEngineReadonly = instance.web.form.FormRenderingEngine.extend({
|
||||
alter_field: function(field) {
|
||||
field.set({"force_readonly": true});
|
||||
},
|
||||
});
|
||||
|
||||
instance.web.form.FormDialog = instance.web.Dialog.extend({
|
||||
init: function(parent, options, view_id, dataset) {
|
||||
this._super(parent, options);
|
||||
|
@ -1464,24 +1471,27 @@ instance.web.form.compute_domain = function(expr, fields) {
|
|||
*/
|
||||
instance.web.form.InvisibilityChangerMixin = {
|
||||
init: function(field_manager, invisible_domain) {
|
||||
this._ic_field_manager = field_manager
|
||||
var self = this;
|
||||
this._ic_field_manager = field_manager;
|
||||
this._ic_invisible_modifier = invisible_domain;
|
||||
this._ic_field_manager.on("view_content_has_changed", this, function() {
|
||||
var result = this._ic_invisible_modifier === undefined ? false :
|
||||
instance.web.form.compute_domain(this._ic_invisible_modifier, this._ic_field_manager.fields);
|
||||
this.set({"invisible": result});
|
||||
var result = self._ic_invisible_modifier === undefined ? false :
|
||||
instance.web.form.compute_domain(
|
||||
self._ic_invisible_modifier,
|
||||
self._ic_field_manager.fields);
|
||||
self.set({"invisible": result});
|
||||
});
|
||||
this.set({invisible: this._ic_invisible_modifier === true, force_invisible: false});
|
||||
var check = function() {
|
||||
if (this.get("invisible") || this.get('force_invisible')) {
|
||||
this.set({"effective_invisible": true});
|
||||
if (self.get("invisible") || self.get('force_invisible')) {
|
||||
self.set({"effective_invisible": true});
|
||||
} else {
|
||||
this.set({"effective_invisible": false});
|
||||
self.set({"effective_invisible": false});
|
||||
}
|
||||
};
|
||||
this.on('change:invisible', this, check);
|
||||
this.on('change:force_invisible', this, check);
|
||||
_.bind(check, this)();
|
||||
check.call(this);
|
||||
},
|
||||
start: function() {
|
||||
this.on("change:effective_invisible", this, this._check_visibility);
|
||||
|
@ -1545,6 +1555,7 @@ instance.web.form.FormWidget = instance.web.Widget.extend(instance.web.form.Invi
|
|||
var compute_domain = instance.web.form.compute_domain;
|
||||
var to_set = {};
|
||||
for (var a in this.modifiers) {
|
||||
if (!this.modifiers.hasOwnProperty(a)) { continue; }
|
||||
if (!_.include(["invisible"], a)) {
|
||||
var val = compute_domain(this.modifiers[a], this.view.fields);
|
||||
to_set[a] = val;
|
||||
|
@ -1691,11 +1702,7 @@ instance.web.form.WidgetButton = instance.web.form.FormWidget.extend({
|
|||
on_confirmed: function() {
|
||||
var self = this;
|
||||
|
||||
var context = this.node.attrs.context;
|
||||
if (context && context.__ref) {
|
||||
context = new instance.web.CompoundContext(context);
|
||||
context.set_eval_context(this._build_eval_context());
|
||||
}
|
||||
var context = this.build_context();
|
||||
|
||||
return this.view.do_execute_action(
|
||||
_.extend({}, this.node.attrs, {context: context}),
|
||||
|
@ -1748,18 +1755,18 @@ instance.web.form.FieldInterface = {
|
|||
/**
|
||||
* Get the current value of the widget.
|
||||
*
|
||||
* Must always return a syntaxically correct value to be passed to the "write" method of the osv class in
|
||||
* Must always return a syntactically correct value to be passed to the "write" method of the osv class in
|
||||
* the OpenERP server, although it is not assumed to respect the constraints applied to the field.
|
||||
* For example if the field is marqued as "required", a call to get_value() can return false.
|
||||
* For example if the field is marked as "required", a call to get_value() can return false.
|
||||
*
|
||||
* get_value() can also be called *before* a call to set_value() and, in that case, is supposed to
|
||||
* return a defaut value according to the type of field.
|
||||
* return a default value according to the type of field.
|
||||
*
|
||||
* This method is always assumed to perform synchronously, it can not return a promise.
|
||||
*
|
||||
* If there was no user interaction to modify the value of the field, it is always assumed that
|
||||
* get_value() return the same semantic value than the one passed in the last call to set_value(),
|
||||
* altough the syntax can be different. This can be the case for type of fields that have a different
|
||||
* although the syntax can be different. This can be the case for type of fields that have a different
|
||||
* syntax for "read" and "write" (example: m2o: set_value([0, "Administrator"]), get_value() => 0).
|
||||
*/
|
||||
get_value: function() {},
|
||||
|
@ -1774,7 +1781,7 @@ instance.web.form.FieldInterface = {
|
|||
*/
|
||||
is_valid: function() {},
|
||||
/**
|
||||
* Returns true if the field holds a value which is syntaxically correct, ignoring
|
||||
* Returns true if the field holds a value which is syntactically correct, ignoring
|
||||
* the potential semantic restrictions applied to the field.
|
||||
*/
|
||||
is_syntax_valid: function() {},
|
||||
|
@ -1804,6 +1811,7 @@ instance.web.form.AbstractField = instance.web.form.FormWidget.extend(instance.w
|
|||
* @param node
|
||||
*/
|
||||
init: function(field_manager, node) {
|
||||
var self = this
|
||||
this._super(field_manager, node);
|
||||
this.field_manager = field_manager;
|
||||
this.name = this.node.attrs.name;
|
||||
|
@ -1816,13 +1824,13 @@ instance.web.form.AbstractField = instance.web.form.FormWidget.extend(instance.w
|
|||
// some events to make the property "effective_readonly" sync automatically with "readonly" and
|
||||
// "force_readonly"
|
||||
this.set({"readonly": this.modifiers['readonly'] === true});
|
||||
this.set({"force_readonly": false});
|
||||
var test_effective_readonly = function() {
|
||||
this.set({"effective_readonly": this.get("readonly") || !!this.get("force_readonly")});
|
||||
self.set({"effective_readonly": self.get("readonly") || !!self.get("force_readonly")});
|
||||
};
|
||||
this.on("change:readonly", this, test_effective_readonly);
|
||||
this.on("change:force_readonly", this, test_effective_readonly);
|
||||
_.bind(test_effective_readonly, this)();
|
||||
|
||||
test_effective_readonly.call(this);
|
||||
this.on("change:value", this, function() {
|
||||
if (! this._inhibit_on_change)
|
||||
this.trigger('changed_value');
|
||||
|
@ -1899,7 +1907,7 @@ instance.web.form.AbstractField = instance.web.form.FormWidget.extend(instance.w
|
|||
*/
|
||||
delay_focus: function($elem) {
|
||||
setTimeout(function() {
|
||||
$elem.focus();
|
||||
$elem[0].focus();
|
||||
}, 50);
|
||||
},
|
||||
/**
|
||||
|
@ -2242,6 +2250,11 @@ instance.web.form.FieldText = instance.web.form.AbstractField.extend(instance.we
|
|||
} else {
|
||||
this.$textarea.attr('disabled', 'disabled');
|
||||
}
|
||||
this.$element.keyup(function (e) {
|
||||
if (e.which === $.ui.keyCode.ENTER) {
|
||||
e.stopPropagation();
|
||||
}
|
||||
});
|
||||
this.setupFocus(this.$textarea);
|
||||
},
|
||||
set_value: function(value_) {
|
||||
|
@ -2294,9 +2307,58 @@ instance.web.form.FieldText = instance.web.form.AbstractField.extend(instance.we
|
|||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* FieldTextHtml Widget
|
||||
* Intended for FieldText widgets meant to display HTML content. This
|
||||
* widget will instantiate the CLEditor (see cleditor in static/src/lib)
|
||||
* To find more information about CLEditor configutation: go to
|
||||
* http://premiumsoftware.net/cleditor/docs/GettingStarted.html
|
||||
*/
|
||||
instance.web.form.FieldTextHtml = instance.web.form.FieldText.extend({
|
||||
|
||||
initialize_content: function() {
|
||||
this.$textarea = this.$element.find('textarea');
|
||||
var width = ((this.node.attrs || {}).editor_width || 468);
|
||||
var height = ((this.node.attrs || {}).editor_height || 100);
|
||||
this.$textarea.cleditor({
|
||||
width: width, // width not including margins, borders or padding
|
||||
height: height, // height not including margins, borders or padding
|
||||
controls: // controls to add to the toolbar
|
||||
"bold italic underline strikethrough | size " +
|
||||
"| removeformat | bullets numbering | outdent " +
|
||||
"indent | link unlink",
|
||||
sizes: // sizes in the font size popup
|
||||
"1,2,3,4,5,6,7",
|
||||
bodyStyle: // style to assign to document body contained within the editor
|
||||
"margin:4px; font:12px monospace; cursor:text; color:#1F1F1F"
|
||||
});
|
||||
this.$cleditor = this.$textarea.cleditor()[0];
|
||||
// call super now, because cleditor resets the disable attr
|
||||
this._super.apply(this, arguments);
|
||||
// propagate disabled property to cleditor
|
||||
this.$cleditor.disable(this.$textarea.prop('disabled'));
|
||||
},
|
||||
|
||||
set_value: function(value_) {
|
||||
this._super.apply(this, arguments);
|
||||
this._dirty_flag = true;
|
||||
},
|
||||
|
||||
render_value: function() {
|
||||
this._super.apply(this, arguments);
|
||||
this.$cleditor.updateFrame();
|
||||
},
|
||||
|
||||
get_value: function() {
|
||||
this.$cleditor.updateTextArea();
|
||||
return this.$textarea.val();
|
||||
},
|
||||
});
|
||||
|
||||
instance.web.form.FieldBoolean = instance.web.form.AbstractField.extend({
|
||||
template: 'FieldBoolean',
|
||||
start: function() {
|
||||
var self = this;
|
||||
this._super.apply(this, arguments);
|
||||
this.$checkbox = $("input", this.$element);
|
||||
this.setupFocus(this.$checkbox);
|
||||
|
@ -2304,10 +2366,10 @@ instance.web.form.FieldBoolean = instance.web.form.AbstractField.extend({
|
|||
this.set({'value': this.$checkbox.is(':checked')});
|
||||
}, this));
|
||||
var check_readonly = function() {
|
||||
this.$checkbox.prop('disabled', this.get("effective_readonly"));
|
||||
self.$checkbox.prop('disabled', self.get("effective_readonly"));
|
||||
};
|
||||
this.on("change:effective_readonly", this, check_readonly);
|
||||
_.bind(check_readonly, this)();
|
||||
check_readonly.call(this);
|
||||
},
|
||||
set_value: function(value_) {
|
||||
this._super.apply(this, arguments);
|
||||
|
@ -2745,10 +2807,20 @@ instance.web.form.FieldMany2One = instance.web.form.AbstractField.extend(instanc
|
|||
this.$input.val(str.split("\n")[0]);
|
||||
this.current_display = this.$input.val();
|
||||
} else {
|
||||
str = _.escape(str).split("\n").join("<br />");
|
||||
var lines = _.escape(str).split("\n");
|
||||
var link = "";
|
||||
var follow = "";
|
||||
if (! this.get_definition_options().highlight_first_line) {
|
||||
link = lines.join("<br />");
|
||||
} else {
|
||||
link = lines[0];
|
||||
follow = _.rest(lines).join("<br />");
|
||||
if (follow)
|
||||
link += "<br />";
|
||||
}
|
||||
this.$element.find('a')
|
||||
.unbind('click')
|
||||
.html(str)
|
||||
.html(link)
|
||||
.click(function () {
|
||||
self.do_action({
|
||||
type: 'ir.actions.act_window',
|
||||
|
@ -2760,6 +2832,7 @@ instance.web.form.FieldMany2One = instance.web.form.AbstractField.extend(instanc
|
|||
});
|
||||
return false;
|
||||
});
|
||||
$(".oe_form_m2o_follow", this.$element).html(follow);
|
||||
}
|
||||
},
|
||||
set_value: function(value_) {
|
||||
|
@ -2776,6 +2849,9 @@ instance.web.form.FieldMany2One = instance.web.form.AbstractField.extend(instanc
|
|||
this._super(value_);
|
||||
this.inhibit_on_change = false;
|
||||
},
|
||||
get_displayed: function() {
|
||||
return this.display_value["" + this.get("value")];
|
||||
},
|
||||
add_id: function(id) {
|
||||
this.display_value = {};
|
||||
this.set({value: id});
|
||||
|
@ -2906,6 +2982,7 @@ instance.web.form.FieldOne2Many = instance.web.form.AbstractField.extend({
|
|||
selectable: self.multi_selection,
|
||||
sortable: false,
|
||||
import_enabled: false,
|
||||
deletable: true
|
||||
});
|
||||
if (self.get("effective_readonly")) {
|
||||
_.extend(view.options, {
|
||||
|
@ -2950,8 +3027,11 @@ instance.web.form.FieldOne2Many = instance.web.form.AbstractField.extend({
|
|||
this.viewmanager.on_controller_inited.add_last(function(view_type, controller) {
|
||||
controller.o2m = self;
|
||||
if (view_type == "list") {
|
||||
if (self.get("effective_readonly"))
|
||||
controller.set_editable(false);
|
||||
if (self.get("effective_readonly")) {
|
||||
controller.on('edit:before', self, function (e) {
|
||||
e.cancel = true;
|
||||
});
|
||||
}
|
||||
} else if (view_type === "form") {
|
||||
if (self.get("effective_readonly")) {
|
||||
$(".oe_form_buttons", controller.$element).children().remove();
|
||||
|
@ -3135,6 +3215,7 @@ instance.web.form.One2ManyViewManager = instance.web.ViewManager.extend({
|
|||
form: 'instance.web.form.One2ManyFormView',
|
||||
kanban: 'instance.web.form.One2ManyKanbanView',
|
||||
});
|
||||
this.__ignore_blur = false;
|
||||
},
|
||||
switch_view: function(mode, unused) {
|
||||
if (mode !== 'form') {
|
||||
|
@ -3184,19 +3265,34 @@ instance.web.form.One2ManyListView = instance.web.ListView.extend({
|
|||
this._super(parent, dataset, view_id, _.extend(options || {}, {
|
||||
ListType: instance.web.form.One2ManyList
|
||||
}));
|
||||
this.on('edit:before', this, this.proxy('_before_edit'));
|
||||
this.on('save:before cancel:before', this, this.proxy('_before_unedit'));
|
||||
|
||||
this.records
|
||||
.bind('add', this.proxy("changed_records"))
|
||||
.bind('edit', this.proxy("changed_records"))
|
||||
.bind('remove', this.proxy("changed_records"));
|
||||
},
|
||||
start: function () {
|
||||
var ret = this._super();
|
||||
this.$element
|
||||
.off('mousedown.handleButtons')
|
||||
.on('mousedown.handleButtons', 'table button', this.proxy('_button_down'));
|
||||
return ret;
|
||||
},
|
||||
changed_records: function () {
|
||||
this.o2m.trigger_on_change();
|
||||
},
|
||||
is_valid: function () {
|
||||
var form;
|
||||
// A list not being edited is always valid
|
||||
if (!(form = this.first_edition_form())) {
|
||||
return true;
|
||||
}
|
||||
var form = this.editor.form;
|
||||
|
||||
// If the form has not been modified, the view can only be valid
|
||||
// NB: is_dirty will also be set on defaults/onchanges/whatever?
|
||||
// oe_form_dirty seems to only be set on actual user actions
|
||||
if (!form.$element.is('.oe_form_dirty')) {
|
||||
return true;
|
||||
}
|
||||
this.o2m._dirty_flag = true;
|
||||
|
||||
// Otherwise validate internal form
|
||||
return _(form.fields).chain()
|
||||
|
@ -3207,21 +3303,8 @@ instance.web.form.One2ManyListView = instance.web.ListView.extend({
|
|||
.all(_.identity)
|
||||
.value();
|
||||
},
|
||||
first_edition_form: function () {
|
||||
var get_form = function (group_or_list) {
|
||||
if (group_or_list.edition) {
|
||||
return group_or_list.edition_form;
|
||||
}
|
||||
return _(group_or_list.children).chain()
|
||||
.map(get_form)
|
||||
.compact()
|
||||
.first()
|
||||
.value();
|
||||
};
|
||||
return get_form(this.groups);
|
||||
},
|
||||
do_add_record: function () {
|
||||
if (this.options.editable) {
|
||||
if (this.editable()) {
|
||||
this._super.apply(this, arguments);
|
||||
} else {
|
||||
var self = this;
|
||||
|
@ -3274,55 +3357,58 @@ instance.web.form.One2ManyListView = instance.web.ListView.extend({
|
|||
});
|
||||
},
|
||||
do_button_action: function (name, id, callback) {
|
||||
var _super = _.bind(this._super, this);
|
||||
|
||||
this.o2m.view.do_save().then(function () {
|
||||
_super(name, id, callback);
|
||||
});
|
||||
}
|
||||
});
|
||||
instance.web.form.One2ManyList = instance.web.ListView.List.extend({
|
||||
KEY_RETURN: 13,
|
||||
// blurring caused by hitting the [Return] key, should skip the
|
||||
// autosave-on-blur and let the handler for [Return] do its thing
|
||||
__return_blur: false,
|
||||
render_row_as_form: function () {
|
||||
if (!_.isNumber(id)) {
|
||||
instance.webclient.notification.warn(
|
||||
_t("Action Button"),
|
||||
_t("The o2m record must be saved before an action can be used"));
|
||||
return;
|
||||
}
|
||||
var parent_form = this.o2m.view;
|
||||
var self = this;
|
||||
return this._super.apply(this, arguments).then(function () {
|
||||
// Replace the "Save Row" button with "Cancel Edition"
|
||||
self.edition_form.$element
|
||||
.undelegate('button.oe_list_edit_row_save', 'click')
|
||||
.delegate('button.oe_list_edit_row_save', 'click', function () {
|
||||
self.cancel_pending_edition();
|
||||
});
|
||||
|
||||
// Overload execute_action on the edition form to perform a simple
|
||||
// reload_record after the action is done, rather than fully
|
||||
// reload the parent view (or something)
|
||||
var _execute_action = self.edition_form.do_execute_action;
|
||||
self.edition_form.do_execute_action = function (action, dataset, record_id, _callback) {
|
||||
return _execute_action.call(this, action, dataset, record_id, function () {
|
||||
self.view.reload_record(
|
||||
self.view.records.get(record_id));
|
||||
});
|
||||
};
|
||||
|
||||
self.edition_form.on('blurred', null, function () {
|
||||
if (self.__return_blur) {
|
||||
delete self.__return_blur;
|
||||
return;
|
||||
}
|
||||
if (!self.edition_form.widget_is_stopped) {
|
||||
self.view.ensure_saved();
|
||||
}
|
||||
});
|
||||
this.ensure_saved().pipe(function () {
|
||||
return parent_form.do_save();
|
||||
}).then(function () {
|
||||
self.handle_button(name, id, callback);
|
||||
});
|
||||
},
|
||||
on_row_keyup: function (e) {
|
||||
if (e.which === this.KEY_RETURN) {
|
||||
this.__return_blur = true;
|
||||
|
||||
_before_edit: function () {
|
||||
this.__ignore_blur = false;
|
||||
this.editor.form.on('blurred', this, this._on_form_blur);
|
||||
},
|
||||
_before_unedit: function () {
|
||||
this.editor.form.off('blurred', this, this._on_form_blur);
|
||||
},
|
||||
_button_down: function () {
|
||||
// If a button is clicked (usually some sort of action button), it's
|
||||
// the button's responsibility to ensure the editable list is in the
|
||||
// correct state -> ignore form blurring
|
||||
this.__ignore_blur = true;
|
||||
},
|
||||
/**
|
||||
* Handles blurring of the nested form (saves the currently edited row),
|
||||
* unless the flag to ignore the event is set to ``true``
|
||||
*
|
||||
* Makes the internal form go away
|
||||
*/
|
||||
_on_form_blur: function () {
|
||||
if (this.__ignore_blur) {
|
||||
this.__ignore_blur = false;
|
||||
return;
|
||||
}
|
||||
this._super(e);
|
||||
// FIXME: why isn't there an API for this?
|
||||
if (this.editor.form.$element.hasClass('oe_form_dirty')) {
|
||||
this.save_edition();
|
||||
return;
|
||||
}
|
||||
this.cancel_edition();
|
||||
},
|
||||
keyup_ENTER: function () {
|
||||
// blurring caused by hitting the [Return] key, should skip the
|
||||
// autosave-on-blur and let the handler for [Return] do its thing (save
|
||||
// the current row *anyway*, then create a new one/edit the next one)
|
||||
this.__ignore_blur = true;
|
||||
this._super.apply(this, arguments);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -3491,7 +3577,7 @@ instance.web.form.FieldMany2Many = instance.web.form.AbstractField.extend({
|
|||
},
|
||||
start: function() {
|
||||
this._super.apply(this, arguments);
|
||||
this.$element.addClass('oe_form_field_many2many');
|
||||
this.$element.addClass('oe_form_field oe_form_field_many2many');
|
||||
|
||||
var self = this;
|
||||
|
||||
|
@ -3866,14 +3952,16 @@ instance.web.form.AbstractFormPopup = instance.web.OldWidget.extend({
|
|||
display_popup: function() {
|
||||
var self = this;
|
||||
this.renderElement();
|
||||
new instance.web.Dialog(this, {
|
||||
var dialog = new instance.web.Dialog(this, {
|
||||
min_width: '800px',
|
||||
dialogClass: 'oe_act_window',
|
||||
dialogClass: 'oe_act_window',
|
||||
close: function() {
|
||||
self.check_exit(true);
|
||||
},
|
||||
title: this.options.title || "",
|
||||
buttons: [{text:"tmp"}],
|
||||
}, this.$element).open();
|
||||
this.$buttonpane = dialog.$element.dialog("widget").find(".ui-dialog-buttonpane").html("");
|
||||
this.start();
|
||||
},
|
||||
on_write_completed: function() {},
|
||||
|
@ -3889,16 +3977,18 @@ instance.web.form.AbstractFormPopup = instance.web.OldWidget.extend({
|
|||
if (this.row_id !== null) {
|
||||
options.initial_mode = this.options.readonly ? "view" : "edit";
|
||||
}
|
||||
_.extend(options, {
|
||||
$buttons: this.$buttonpane,
|
||||
});
|
||||
this.view_form = new instance.web.FormView(this, this.dataset, false, options);
|
||||
if (this.options.alternative_form_view) {
|
||||
this.view_form.set_embedded_view(this.options.alternative_form_view);
|
||||
}
|
||||
this.view_form.appendTo(this.$element.find(".oe_popup_form"));
|
||||
this.view_form.on_loaded.add_last(function() {
|
||||
var $buttons = self.view_form.$element.find(".oe_form_buttons");
|
||||
var multi_select = self.row_id === null && ! self.options.disable_multiple_selection;
|
||||
$buttons.html(QWeb.render("AbstractFormPopup.buttons", {multi_select: multi_select}));
|
||||
var $snbutton = $buttons.find(".oe_abstractformpopup-form-save-new");
|
||||
self.$buttonpane.html(QWeb.render("AbstractFormPopup.buttons", {multi_select: multi_select}));
|
||||
var $snbutton = self.$buttonpane.find(".oe_abstractformpopup-form-save-new");
|
||||
$snbutton.click(function() {
|
||||
$.when(self.view_form.do_save()).then(function() {
|
||||
self.view_form.reload_mutex.exec(function() {
|
||||
|
@ -3906,7 +3996,7 @@ instance.web.form.AbstractFormPopup = instance.web.OldWidget.extend({
|
|||
});
|
||||
});
|
||||
});
|
||||
var $sbutton = $buttons.find(".oe_abstractformpopup-form-save");
|
||||
var $sbutton = self.$buttonpane.find(".oe_abstractformpopup-form-save");
|
||||
$sbutton.click(function() {
|
||||
$.when(self.view_form.do_save()).then(function() {
|
||||
self.view_form.reload_mutex.exec(function() {
|
||||
|
@ -3914,7 +4004,7 @@ instance.web.form.AbstractFormPopup = instance.web.OldWidget.extend({
|
|||
});
|
||||
});
|
||||
});
|
||||
var $cbutton = $buttons.find(".oe_abstractformpopup-form-close");
|
||||
var $cbutton = self.$buttonpane.find(".oe_abstractformpopup-form-close");
|
||||
$cbutton.click(function() {
|
||||
self.check_exit();
|
||||
});
|
||||
|
@ -4021,9 +4111,12 @@ instance.web.form.SelectCreatePopup = instance.web.form.AbstractFormPopup.extend
|
|||
self.dataset, false,
|
||||
_.extend({'deletable': false,
|
||||
'selectable': !self.options.disable_multiple_selection,
|
||||
'read_only': true,
|
||||
'import_enabled': false,
|
||||
'$buttons': self.$buttonpane,
|
||||
}, self.options.list_view_options || {}));
|
||||
self.view_list.on('edit:before', self, function (e) {
|
||||
e.cancel = true;
|
||||
});
|
||||
self.view_list.popup = self;
|
||||
self.view_list.appendTo($(".oe_popup_list", self.$element)).pipe(function() {
|
||||
self.view_list.do_show();
|
||||
|
@ -4031,16 +4124,12 @@ instance.web.form.SelectCreatePopup = instance.web.form.AbstractFormPopup.extend
|
|||
self.searchview.do_search();
|
||||
});
|
||||
self.view_list.on_loaded.add_last(function() {
|
||||
var $buttons = self.view_list.$element.find(".oe-actions");
|
||||
$buttons.prepend(QWeb.render("SelectCreatePopup.search.buttons"));
|
||||
var $cbutton = $buttons.find(".oe_selectcreatepopup-search-close");
|
||||
self.$buttonpane.html(QWeb.render("SelectCreatePopup.search.buttons", {widget:self}));
|
||||
var $cbutton = self.$buttonpane.find(".oe_selectcreatepopup-search-close");
|
||||
$cbutton.click(function() {
|
||||
self.destroy();
|
||||
});
|
||||
var $sbutton = $buttons.find(".oe_selectcreatepopup-search-select");
|
||||
if(self.options.disable_multiple_selection) {
|
||||
$sbutton.hide();
|
||||
}
|
||||
var $sbutton = self.$buttonpane.find(".oe_selectcreatepopup-search-select");
|
||||
$sbutton.click(function() {
|
||||
self.on_select_elements(self.selected_ids);
|
||||
self.destroy();
|
||||
|
@ -4259,7 +4348,7 @@ instance.web.form.FieldBinary = instance.web.form.AbstractField.extend(instance.
|
|||
//link.target = '_blank';
|
||||
link.href = "data:application/octet-stream;base64," + value;
|
||||
} else {
|
||||
$.blockUI();
|
||||
instance.web.blockUI();
|
||||
this.session.get_file({
|
||||
url: '/web/binary/saveas_ajax',
|
||||
data: {data: JSON.stringify({
|
||||
|
@ -4269,7 +4358,7 @@ instance.web.form.FieldBinary = instance.web.form.AbstractField.extend(instance.
|
|||
filename_field: (this.node.attrs.filename || ''),
|
||||
context: this.view.dataset.get_context()
|
||||
})},
|
||||
complete: $.unblockUI,
|
||||
complete: instance.web.unblockUI,
|
||||
error: instance.webclient.crashmanager.on_rpc_error
|
||||
});
|
||||
ev.stopPropagation();
|
||||
|
@ -4518,6 +4607,7 @@ instance.web.form.widgets = new instance.web.Registry({
|
|||
'email' : 'instance.web.form.FieldEmail',
|
||||
'url' : 'instance.web.form.FieldUrl',
|
||||
'text' : 'instance.web.form.FieldText',
|
||||
'text_html' : 'instance.web.form.FieldTextHtml',
|
||||
'date' : 'instance.web.form.FieldDate',
|
||||
'datetime' : 'instance.web.form.FieldDatetime',
|
||||
'selection' : 'instance.web.form.FieldSelection',
|
||||
|
|
|
@ -21,9 +21,6 @@ instance.web.ListView = instance.web.View.extend( /** @lends instance.web.ListVi
|
|||
// whether the view rows can be reordered (via vertical drag & drop)
|
||||
'reorderable': true,
|
||||
'action_buttons': true,
|
||||
// if true, the view can't be editable, ignoring the view's and the context's
|
||||
// instructions
|
||||
'read_only': false,
|
||||
// if true, the 'Import', 'Export', etc... buttons will be shown
|
||||
'import_enabled': true,
|
||||
},
|
||||
|
@ -142,7 +139,7 @@ instance.web.ListView = instance.web.View.extend( /** @lends instance.web.ListVi
|
|||
});
|
||||
},
|
||||
/**
|
||||
* View startup method, the default behavior is to set the ``oe_listw``
|
||||
* View startup method, the default behavior is to set the ``oe_list``
|
||||
* class on its root element and to perform an RPC load call.
|
||||
*
|
||||
* @returns {$.Deferred} loading promise
|
||||
|
@ -288,7 +285,7 @@ instance.web.ListView = instance.web.View.extend( /** @lends instance.web.ListVi
|
|||
}
|
||||
this.$buttons.find('.oe_list_add')
|
||||
.click(this.proxy('do_add_record'))
|
||||
.prop('disabled', grouped && this.options.editable);
|
||||
.prop('disabled', grouped);
|
||||
this.$buttons.on('click', '.oe_list_button_import', function() {
|
||||
self.on_sidebar_import();
|
||||
return false;
|
||||
|
@ -411,20 +408,27 @@ instance.web.ListView = instance.web.View.extend( /** @lends instance.web.ListVi
|
|||
if (column.modifiers) {
|
||||
var modifiers = JSON.parse(column.modifiers);
|
||||
column.modifiers_for = function (fields) {
|
||||
if (!modifiers.invisible) {
|
||||
return {};
|
||||
var out = {};
|
||||
|
||||
for (var attr in modifiers) {
|
||||
if (!modifiers.hasOwnProperty(attr)) { continue; }
|
||||
var modifier = modifiers[attr];
|
||||
out[attr] = _.isBoolean(modifier)
|
||||
? modifier
|
||||
: domain_computer(modifier, fields);
|
||||
}
|
||||
return {
|
||||
'invisible': domain_computer(modifiers.invisible, fields)
|
||||
};
|
||||
|
||||
return out;
|
||||
};
|
||||
if (modifiers['tree_invisible']) {
|
||||
column.invisible = '1';
|
||||
} else {
|
||||
delete column.invisible;
|
||||
}
|
||||
column.modifiers = modifiers;
|
||||
} else {
|
||||
column.modifiers_for = noop;
|
||||
column.modifiers = {};
|
||||
}
|
||||
return column;
|
||||
};
|
||||
|
@ -436,10 +440,12 @@ instance.web.ListView = instance.web.View.extend( /** @lends instance.web.ListVi
|
|||
if (grouped) {
|
||||
this.columns.unshift({
|
||||
id: '_group', tag: '', string: _t("Group"), meta: true,
|
||||
modifiers_for: function () { return {}; }
|
||||
modifiers_for: function () { return {}; },
|
||||
modifiers: {}
|
||||
}, {
|
||||
id: '_count', tag: '', string: '#', meta: true,
|
||||
modifiers_for: function () { return {}; }
|
||||
modifiers_for: function () { return {}; },
|
||||
modifiers: {}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -667,6 +673,19 @@ instance.web.ListView = instance.web.View.extend( /** @lends instance.web.ListVi
|
|||
* @param {Function} callback should be called after the action is executed, if non-null
|
||||
*/
|
||||
do_button_action: function (name, id, callback) {
|
||||
this.handle_button(name, id, callback);
|
||||
},
|
||||
/**
|
||||
* Base handling of buttons, can be called when overriding do_button_action
|
||||
* in order to bypass parent overrides.
|
||||
*
|
||||
* This method should not be overridden.
|
||||
*
|
||||
* @param {String} name action name
|
||||
* @param {Object} id id of the record the action should be called on
|
||||
* @param {Function} callback should be called after the action is executed, if non-null
|
||||
*/
|
||||
handle_button: function (name, id, callback) {
|
||||
var action = _.detect(this.columns, function (field) {
|
||||
return field.name === name;
|
||||
});
|
||||
|
@ -911,27 +930,42 @@ instance.web.ListView.List = instance.web.Class.extend( /** @lends instance.web.
|
|||
|
||||
this.record_callbacks = {
|
||||
'remove': function (event, record) {
|
||||
var $row = self.$current.find(
|
||||
'[data-id=' + record.get('id') + ']');
|
||||
var $row = self.$current.children(
|
||||
'[data-id=' + record.get('id') + ']');
|
||||
var index = $row.data('index');
|
||||
$row.remove();
|
||||
self.refresh_zebra(index);
|
||||
},
|
||||
'reset': function () { return self.on_records_reset(); },
|
||||
'change': function (event, record) {
|
||||
var $row = self.$current.find('[data-id=' + record.get('id') + ']');
|
||||
'change': function (event, record, attribute, value, old_value) {
|
||||
var $row;
|
||||
if (attribute === 'id') {
|
||||
if (old_value) {
|
||||
throw new Error("Setting 'id' attribute on existing record "
|
||||
+ JSON.stringify(record.attributes));
|
||||
}
|
||||
if (!_.contains(self.dataset.ids, value)) {
|
||||
// add record to dataset if not already in (added by
|
||||
// the form view?)
|
||||
self.dataset.ids.splice(
|
||||
self.records.indexOf(record), 0, value);
|
||||
}
|
||||
// Set id on new record
|
||||
$row = self.$current.children('[data-id=false]');
|
||||
} else {
|
||||
$row = self.$current.children(
|
||||
'[data-id=' + record.get('id') + ']');
|
||||
}
|
||||
$row.replaceWith(self.render_record(record));
|
||||
},
|
||||
'add': function (ev, records, record, index) {
|
||||
var $new_row = $('<tr>').attr({
|
||||
'data-id': record.get('id')
|
||||
});
|
||||
var $new_row = $(self.render_record(record));
|
||||
|
||||
if (index === 0) {
|
||||
$new_row.prependTo(self.$current);
|
||||
} else {
|
||||
var previous_record = records.at(index-1),
|
||||
$previous_sibling = self.$current.find(
|
||||
$previous_sibling = self.$current.children(
|
||||
'[data-id=' + previous_record.get('id') + ']');
|
||||
$new_row.insertAfter($previous_sibling);
|
||||
}
|
||||
|
@ -975,11 +1009,11 @@ instance.web.ListView.List = instance.web.Class.extend( /** @lends instance.web.
|
|||
e.stopPropagation();
|
||||
})
|
||||
.delegate('tr', 'click', function (e) {
|
||||
e.stopPropagation();
|
||||
var row_id = self.row_id(e.currentTarget);
|
||||
if (row_id !== undefined) {
|
||||
if (row_id) {
|
||||
e.stopPropagation();
|
||||
if (!self.dataset.select_id(row_id)) {
|
||||
throw "Could not find id in dataset"
|
||||
throw new Error("Could not find id in dataset");
|
||||
}
|
||||
self.row_clicked(e);
|
||||
}
|
||||
|
@ -1139,6 +1173,7 @@ instance.web.ListView.List = instance.web.Class.extend( /** @lends instance.web.
|
|||
* @returns {String} QWeb rendering of the selected record
|
||||
*/
|
||||
render_record: function (record) {
|
||||
var self = this;
|
||||
var index = this.records.indexOf(record);
|
||||
return QWeb.render('ListView.row', {
|
||||
columns: this.columns,
|
||||
|
@ -1147,7 +1182,7 @@ instance.web.ListView.List = instance.web.Class.extend( /** @lends instance.web.
|
|||
row_parity: (index % 2 === 0) ? 'even' : 'odd',
|
||||
view: this.view,
|
||||
render_cell: function () {
|
||||
return this.render_cell.apply(this, arguments); }
|
||||
return self.render_cell.apply(self, arguments); }
|
||||
});
|
||||
},
|
||||
/**
|
||||
|
@ -1831,7 +1866,7 @@ var Collection = instance.web.Class.extend(/** @lends Collection# */{
|
|||
* @returns this
|
||||
*/
|
||||
remove: function (record) {
|
||||
var index = _(this.records).indexOf(record);
|
||||
var index = this.indexOf(record);
|
||||
if (index === -1) {
|
||||
_(this._proxies).each(function (proxy) {
|
||||
proxy.remove(record);
|
||||
|
@ -1847,13 +1882,42 @@ var Collection = instance.web.Class.extend(/** @lends Collection# */{
|
|||
return this;
|
||||
},
|
||||
|
||||
_onRecordEvent: function (event, record, options) {
|
||||
_onRecordEvent: function (event) {
|
||||
switch(event) {
|
||||
// don't propagate reset events
|
||||
if (event === 'reset') { return; }
|
||||
case 'reset': return;
|
||||
case 'change:id':
|
||||
var record = arguments[1];
|
||||
var new_value = arguments[2];
|
||||
var old_value = arguments[3];
|
||||
// [change:id, record, new_value, old_value]
|
||||
if (this._byId[old_value] === record) {
|
||||
delete this._byId[old_value];
|
||||
this._byId[new_value] = record;
|
||||
}
|
||||
break;
|
||||
}
|
||||
this.trigger.apply(this, arguments);
|
||||
},
|
||||
|
||||
// underscore-type methods
|
||||
find: function (callback) {
|
||||
var record;
|
||||
for(var section in this._proxies) {
|
||||
if (!this._proxies.hasOwnProperty(section)) {
|
||||
continue
|
||||
}
|
||||
if ((record = this._proxies[section].find(callback))) {
|
||||
return record;
|
||||
}
|
||||
}
|
||||
for(var i=0; i<this.length; ++i) {
|
||||
record = this.records[i];
|
||||
if (callback(record)) {
|
||||
return record;
|
||||
}
|
||||
}
|
||||
},
|
||||
each: function (callback) {
|
||||
for(var section in this._proxies) {
|
||||
if (this._proxies.hasOwnProperty(section)) {
|
||||
|
@ -1878,6 +1942,46 @@ var Collection = instance.web.Class.extend(/** @lends Collection# */{
|
|||
},
|
||||
indexOf: function (record) {
|
||||
return _(this.records).indexOf(record);
|
||||
},
|
||||
succ: function (record, options) {
|
||||
options = options || {wraparound: false};
|
||||
var result;
|
||||
for(var section in this._proxies) {
|
||||
if (!this._proxies.hasOwnProperty(section)) {
|
||||
continue;
|
||||
}
|
||||
if ((result = this._proxies[section].succ(record, options))) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
var index = this.indexOf(record);
|
||||
if (index === -1) { return null; }
|
||||
var next_index = index + 1;
|
||||
if (options.wraparound && (next_index === this.length)) {
|
||||
return this.at(0);
|
||||
}
|
||||
return this.at(next_index);
|
||||
},
|
||||
pred: function (record, options) {
|
||||
options = options || {wraparound: false};
|
||||
|
||||
var result;
|
||||
for (var section in this._proxies) {
|
||||
if (!this._proxies.hasOwnProperty(section)) {
|
||||
continue;
|
||||
}
|
||||
if ((result = this._proxies[section].pred(record, options))) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
var index = this.indexOf(record);
|
||||
if (index === -1) { return null; }
|
||||
var next_index = index - 1;
|
||||
if (options.wraparound && (next_index === -1)) {
|
||||
return this.at(this.length - 1);
|
||||
}
|
||||
return this.at(next_index);
|
||||
}
|
||||
});
|
||||
Collection.include(Events);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -274,7 +274,7 @@ instance.web.ActionManager = instance.web.Widget.extend({
|
|||
},
|
||||
ir_actions_report_xml: function(action, on_closed) {
|
||||
var self = this;
|
||||
$.blockUI();
|
||||
instance.web.blockUI();
|
||||
self.rpc("/web/session/eval_domain_and_context", {
|
||||
contexts: [action.context],
|
||||
domains: []
|
||||
|
@ -284,7 +284,7 @@ instance.web.ActionManager = instance.web.Widget.extend({
|
|||
self.session.get_file({
|
||||
url: '/web/report',
|
||||
data: {action: JSON.stringify(action)},
|
||||
complete: $.unblockUI,
|
||||
complete: instance.web.unblockUI,
|
||||
success: function(){
|
||||
if (!self.dialog && on_closed) {
|
||||
on_closed();
|
||||
|
@ -657,32 +657,6 @@ instance.web.ViewManagerAction = instance.web.ViewManager.extend({
|
|||
|
||||
this.$element.find('.oe_debug_view').change(this.on_debug_changed);
|
||||
this.$element.addClass("oe_view_manager_" + (this.action.target || 'current'));
|
||||
|
||||
if (this.action.help && !this.flags.low_profile) {
|
||||
var Users = new instance.web.DataSet(self, 'res.users'),
|
||||
$tips = this.$element.find('.oe_view_manager_menu_tips');
|
||||
$tips.delegate('blockquote button', 'click', function() {
|
||||
var $this = $(this);
|
||||
//noinspection FallthroughInSwitchStatementJS
|
||||
switch ($this.attr('name')) {
|
||||
case 'disable':
|
||||
Users.write(self.session.uid, {menu_tips:false});
|
||||
case 'hide':
|
||||
$this.closest('blockquote').hide();
|
||||
self.session.hidden_menutips[self.action.id] = true;
|
||||
}
|
||||
});
|
||||
if (!(self.action.id in self.session.hidden_menutips)) {
|
||||
Users.read_ids([this.session.uid], ['menu_tips']).then(function(users) {
|
||||
var user = users[0];
|
||||
if (!(user && user.id === self.session.uid)) {
|
||||
return;
|
||||
}
|
||||
$tips.find('blockquote').toggle(user.menu_tips);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return manager_ready;
|
||||
},
|
||||
on_debug_changed: function (evt) {
|
||||
|
@ -867,7 +841,7 @@ instance.web.Sidebar = instance.web.Widget.extend({
|
|||
} else {
|
||||
self.do_attachement_update(self.dataset, self.model_id);
|
||||
}
|
||||
$.unblockUI();
|
||||
instance.web.unblockUI();
|
||||
});
|
||||
},
|
||||
start: function() {
|
||||
|
@ -1006,7 +980,7 @@ instance.web.Sidebar = instance.web.Widget.extend({
|
|||
$e.parent().find('input[type=file]').prop('disabled', true);
|
||||
$e.parent().find('button').prop('disabled', true).find('img, span').toggle();
|
||||
this.$('.oe_sidebar_add_attachment span').text(_t('Uploading...'));
|
||||
$.blockUI();
|
||||
instance.web.blockUI();
|
||||
}
|
||||
},
|
||||
on_attachment_delete: function(e) {
|
||||
|
@ -1100,11 +1074,13 @@ instance.web.TranslateDialog = instance.web.Dialog.extend({
|
|||
if (self.view.translatable_fields && self.view.translatable_fields.length) {
|
||||
self.do_load_fields_values(function() {
|
||||
sup.call(self);
|
||||
// desactivated because it created an exception, plus it does not seem very useful
|
||||
/*
|
||||
if (field) {
|
||||
var $field_input = self.$element.find('tr[data-field="' + field.name + '"] td:nth-child(2) *:first-child');
|
||||
self.$element.scrollTo($field_input);
|
||||
$field_input.focus();
|
||||
}
|
||||
}*/
|
||||
});
|
||||
} else {
|
||||
sup.call(self);
|
||||
|
@ -1372,7 +1348,9 @@ instance.web.json_node_to_xml = function(node, human_readable, indent) {
|
|||
if (typeof(node) === 'string') {
|
||||
return sindent + node;
|
||||
} else if (typeof(node.tag) !== 'string' || !node.children instanceof Array || !node.attrs instanceof Object) {
|
||||
throw("Node a json node");
|
||||
throw new Error(
|
||||
_.str.sprintf("Node [%s] is not a JSONified XML node",
|
||||
JSON.stringify(node)));
|
||||
}
|
||||
for (var attr in node.attrs) {
|
||||
var vattr = node.attrs[attr];
|
||||
|
|
|
@ -370,6 +370,7 @@
|
|||
</t>
|
||||
|
||||
<t t-name="WebClient">
|
||||
<div class="openerp openerp_webclient_container">
|
||||
<table class="oe_webclient">
|
||||
<tr>
|
||||
<td colspan="2" class="oe_topbar">
|
||||
|
@ -393,6 +394,13 @@
|
|||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<t t-name="EmbedClient">
|
||||
<div class="openerp">
|
||||
<div class="oe_application"></div>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<t t-name="ViewManager">
|
||||
|
@ -621,9 +629,9 @@
|
|||
<button type="button" class="oe_button oe_list_add oe_highlight">
|
||||
<t t-esc="widget.options.addable"/>
|
||||
</button>
|
||||
<t t-if="widget.options.import_enabled">
|
||||
<span class="oe_alternative" t-if="widget.options.import_enabled">
|
||||
<span class="oe_fade">or</span> <a href="#" class="oe_bold oe_list_button_import">Import</a>
|
||||
</t>
|
||||
</span>
|
||||
</t>
|
||||
</div>
|
||||
<t t-name="ListView.pager">
|
||||
|
@ -643,6 +651,7 @@
|
|||
<tr t-name="ListView.row" t-att-class="row_parity"
|
||||
t-att-data-id="record.get('id')"
|
||||
t-att-style="view.style_for(record)">
|
||||
<t t-set="asData" t-value="record.toForm().data"/>
|
||||
<t t-foreach="columns" t-as="column">
|
||||
<td t-if="column.meta">
|
||||
|
||||
|
@ -654,23 +663,26 @@
|
|||
<input t-if="!options.radio" type="checkbox" name="radiogroup" t-att-checked="checked"/>
|
||||
</th>
|
||||
<t t-foreach="columns" t-as="column">
|
||||
<t t-set="align" t-value="column.type === 'integer' or column.type == 'float'"/>
|
||||
<t t-set="number" t-value="column.type === 'integer' or column.type == 'float'"/>
|
||||
<t t-set="modifiers" t-value="column.modifiers_for(asData)"/>
|
||||
<td t-if="!column.meta and column.invisible !== '1'" t-att-title="column.help"
|
||||
t-att-class="'oe_list_field_cell' + (align ? ' oe_number' : '')
|
||||
+ (column.tag === 'button' ? ' oe_button' : '')"
|
||||
t-att-data-field="column.id">
|
||||
<t t-raw="render_cell(record, column)"/>
|
||||
</td>
|
||||
t-attf-class="oe_list_field_cell oe_list_field_#{column.widget or column.type} #{number ? 'oe_number' : ''} #{column.tag === 'button' ? 'oe-button' : ''} #{modifiers.readonly ? 'oe_readonly' : ''}"
|
||||
t-att-data-field="column.id"
|
||||
><t t-raw="render_cell(record, column)"/></td>
|
||||
</t>
|
||||
<td t-if="options.deletable" class='oe_list_record_delete' width="1">
|
||||
<button type="button" name="delete" class="oe_i">d</button>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<t t-name="ListView.row.save">
|
||||
<td>
|
||||
<button class='oe_i oe_list_edit_row_save' type='button' name='save'/>
|
||||
</td>
|
||||
<t t-extend="ListView.buttons">
|
||||
<t t-jquery="button.oe_list_add" t-operation="after">
|
||||
<button class="oe_button oe_list_save oe_highlight"
|
||||
type="button">Save</button>
|
||||
</t>
|
||||
<t t-jquery="a.oe_list_button_import" t-operation="after">
|
||||
<a href="#" class="oe_bold oe_list_discard">discard</a>
|
||||
</t>
|
||||
</t>
|
||||
|
||||
<t t-name="FormView">
|
||||
|
@ -786,7 +798,7 @@
|
|||
</div>
|
||||
</t>
|
||||
<t t-name="FormRenderingSeparator">
|
||||
<div t-attf-class="oe_horizontal_separator #{classnames}">
|
||||
<div t-attf-class="oe_horizontal_separator oe_clear #{classnames}">
|
||||
<t t-esc="string"/>
|
||||
</div>
|
||||
</t>
|
||||
|
@ -942,9 +954,12 @@
|
|||
</t>
|
||||
<t t-name="FieldMany2One">
|
||||
<span class="oe_form_field oe_form_field_many2one oe_form_field_with_button" t-att-style="widget.node.attrs.style">
|
||||
<a t-if="widget.get('effective_readonly')" href="#" class="oe_form_uri"/>
|
||||
<t t-if="widget.get('effective_readonly')">
|
||||
<a href="#" class="oe_form_uri"/>
|
||||
<span class="oe_form_m2o_follow"/>
|
||||
</t>
|
||||
<t t-if="!widget.get('effective_readonly')">
|
||||
<a href="#" class="oe_m2o_cm_button oe_e oe_right">/</a>
|
||||
<a href="#" tabindex="-1" class="oe_m2o_cm_button oe_e oe_right">/</a>
|
||||
<div>
|
||||
<input type="text"
|
||||
t-att-id="widget.id_for_label"
|
||||
|
@ -1204,6 +1219,8 @@
|
|||
<div class="oe_searchview_clear"/>
|
||||
<div class="oe_searchview_unfold_drawer" title="Advanced Search..."/>
|
||||
<div class="oe_searchview_drawer"/>
|
||||
<button type="button" class="oe_searchview_search"
|
||||
title="Search Again">Search</button>
|
||||
</div>
|
||||
|
||||
<div t-name="SearchView.InputView"
|
||||
|
@ -1464,8 +1481,11 @@
|
|||
</div>
|
||||
</t>
|
||||
<t t-name="SelectCreatePopup.search.buttons">
|
||||
<button type="button" class="oe_button oe_selectcreatepopup-search-select" disabled="disabled">Select</button>
|
||||
<button type="button" class="oe_button oe_selectcreatepopup-search-close">Cancel</button>
|
||||
<t t-if="! widget.options.disable_multiple_selection">
|
||||
<button type="button" class="oe_button oe_selectcreatepopup-search-select" disabled="disabled">Select</button>
|
||||
or
|
||||
</t>
|
||||
<a class="oe_button oe_selectcreatepopup-search-close oe_bold oe_form_button_cancel" href="javascript:void(0)">Cancel</a>
|
||||
</t>
|
||||
<t t-name="AbstractFormPopup.buttons">
|
||||
<t t-if="! multi_select">
|
||||
|
@ -1475,7 +1495,7 @@
|
|||
<button type="button" class="oe_button oe_abstractformpopup-form-save-new oe_highlight">Save & New</button>
|
||||
<button type="button" class="oe_button oe_abstractformpopup-form-save oe_highlight">Save & Close</button>
|
||||
</t>
|
||||
<button type="button" class="oe_button oe_abstractformpopup-form-close">Cancel</button>
|
||||
or <a class="oe_button oe_abstractformpopup-form-close oe_bold oe_form_button_cancel" href="javascript:void(0)">Cancel</a>
|
||||
</t>
|
||||
<t t-extend="ListView.row">
|
||||
<!-- adds back padding to row being rendered after edition, if necessary
|
||||
|
@ -1483,7 +1503,7 @@
|
|||
missing columns
|
||||
-->
|
||||
<t t-jquery="> :last" t-operation="after">
|
||||
<td t-if="edited and !options.deletable" class="oe_list_padding"/>
|
||||
<td t-if="edited and !options.deletable" class="oe-listview-padding"/>
|
||||
</t>
|
||||
</t>
|
||||
|
||||
|
|
|
@ -0,0 +1,352 @@
|
|||
$(document).ready(function () {
|
||||
var $fix = $('#qunit-fixture');
|
||||
|
||||
var instance;
|
||||
var baseSetup = function () {
|
||||
instance = openerp.testing.instanceFor('list_editable');
|
||||
|
||||
openerp.testing.loadTemplate(instance);
|
||||
|
||||
openerp.testing.mockifyRPC(instance);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {String} name
|
||||
* @param {Object} [attrs]
|
||||
* @param {String} [attrs.type="char"]
|
||||
* @param {Boolean} [attrs.required]
|
||||
* @param {Boolean} [attrs.invisible]
|
||||
* @param {Boolean} [attrs.readonly]
|
||||
* @return {Object}
|
||||
*/
|
||||
function field(name, attrs) {
|
||||
attrs = attrs || {};
|
||||
attrs.name = name;
|
||||
return _.defaults(attrs, {
|
||||
type: 'char'
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Array} fields
|
||||
* @return {Object}
|
||||
*/
|
||||
function makeFormView(fields) {
|
||||
var fobj = {};
|
||||
_(fields).each(function (field) {
|
||||
fobj[field.name] = {
|
||||
type: field.type,
|
||||
string: field.string
|
||||
};
|
||||
});
|
||||
var children = _(fields).map(function (field) {
|
||||
return {
|
||||
tag: 'field',
|
||||
attrs: {
|
||||
name: field.name,
|
||||
modifiers: JSON.stringify({
|
||||
required: field.required,
|
||||
invisible: field.invisible,
|
||||
readonly: field.readonly
|
||||
})
|
||||
}
|
||||
}
|
||||
});
|
||||
return {
|
||||
arch: {
|
||||
tag: 'form',
|
||||
attrs: {
|
||||
version: '7.0',
|
||||
'class': 'oe_form_container'
|
||||
},
|
||||
children: children
|
||||
},
|
||||
fields: fobj
|
||||
};
|
||||
}
|
||||
|
||||
module('editor', {
|
||||
setup: baseSetup
|
||||
});
|
||||
asyncTest('base-state', 2, function () {
|
||||
var e = new instance.web.list.Editor({
|
||||
dataset: {},
|
||||
edition_view: function () {
|
||||
return makeFormView();
|
||||
}
|
||||
});
|
||||
e.appendTo($fix)
|
||||
.always(start)
|
||||
.fail(function (error) { ok(false, error && error.message); })
|
||||
.done(function () {
|
||||
ok(!e.is_editing(), "should not be editing");
|
||||
ok(e.form instanceof instance.web.FormView,
|
||||
"should use default form type");
|
||||
});
|
||||
});
|
||||
asyncTest('toggle-edition-save', 4, function () {
|
||||
instance.connection.responses['/web/dataset/call_kw:create'] = function () {
|
||||
return { result: 42 };
|
||||
};
|
||||
instance.connection.responses['/web/dataset/call_kw:read'] = function () {
|
||||
return { result: [{
|
||||
id: 42,
|
||||
a: false,
|
||||
b: false,
|
||||
c: false
|
||||
}]};
|
||||
};
|
||||
var e = new instance.web.list.Editor({
|
||||
dataset: new instance.web.DataSetSearch(),
|
||||
prepends_on_create: function () { return false; },
|
||||
edition_view: function () {
|
||||
return makeFormView([ field('a'), field('b'), field('c') ]);
|
||||
}
|
||||
});
|
||||
var counter = 0;
|
||||
e.appendTo($fix)
|
||||
.pipe(function () {
|
||||
return e.edit({}, function () {
|
||||
++counter;
|
||||
});
|
||||
})
|
||||
.pipe(function (form) {
|
||||
ok(e.is_editing(), "should be editing");
|
||||
equal(counter, 3, "should have configured all fields");
|
||||
return e.save();
|
||||
})
|
||||
.always(start)
|
||||
.fail(function (error) { ok(false, error && error.message); })
|
||||
.done(function (record) {
|
||||
ok(!e.is_editing(), "should have stopped editing");
|
||||
equal(record.id, 42, "should have newly created id");
|
||||
})
|
||||
});
|
||||
asyncTest('toggle-edition-cancel', 2, function () {
|
||||
instance.connection.responses['/web/dataset/call_kw:create'] = function () {
|
||||
return { result: 42 };
|
||||
};
|
||||
var e = new instance.web.list.Editor({
|
||||
dataset: new instance.web.DataSetSearch(),
|
||||
prepends_on_create: function () { return false; },
|
||||
edition_view: function () {
|
||||
return makeFormView([ field('a'), field('b'), field('c') ]);
|
||||
}
|
||||
});
|
||||
var counter = 0;
|
||||
e.appendTo($fix)
|
||||
.pipe(function () {
|
||||
return e.edit({}, function () {
|
||||
++counter;
|
||||
});
|
||||
})
|
||||
.pipe(function (form) {
|
||||
return e.cancel();
|
||||
})
|
||||
.always(start)
|
||||
.fail(function (error) { ok(false, error && error.message); })
|
||||
.done(function (record) {
|
||||
ok(!e.is_editing(), "should have stopped editing");
|
||||
ok(!record.id, "should have no id");
|
||||
})
|
||||
});
|
||||
asyncTest('toggle-save-required', 2, function () {
|
||||
instance.connection.responses['/web/dataset/call_kw:create'] = function () {
|
||||
return { result: 42 };
|
||||
};
|
||||
var e = new instance.web.list.Editor({
|
||||
do_warn: function () {
|
||||
warnings++;
|
||||
},
|
||||
dataset: new instance.web.DataSetSearch(),
|
||||
prepends_on_create: function () { return false; },
|
||||
edition_view: function () {
|
||||
return makeFormView([
|
||||
field('a', {required: true}), field('b'), field('c') ]);
|
||||
}
|
||||
});
|
||||
var counter = 0;
|
||||
var warnings = 0;
|
||||
e.appendTo($fix)
|
||||
.pipe(function () {
|
||||
return e.edit({}, function () {
|
||||
++counter;
|
||||
});
|
||||
})
|
||||
.pipe(function (form) {
|
||||
return e.save();
|
||||
})
|
||||
.always(start)
|
||||
.done(function () { ok(false, "cancel should not succeed"); })
|
||||
.fail(function () {
|
||||
equal(warnings, 1, "should have been warned");
|
||||
ok(e.is_editing(), "should have kept editing");
|
||||
})
|
||||
});
|
||||
|
||||
module('list-edition', {
|
||||
setup: function () {
|
||||
baseSetup();
|
||||
|
||||
var records = {};
|
||||
_.extend(instance.connection.responses, {
|
||||
'/web/listview/load': function () {
|
||||
return {result: {
|
||||
type: 'tree',
|
||||
fields: {
|
||||
a: {type: 'char', string: "A"},
|
||||
b: {type: 'char', string: "B"},
|
||||
c: {type: 'char', string: "C"}
|
||||
},
|
||||
arch: {
|
||||
tag: 'tree',
|
||||
attrs: {},
|
||||
children: [
|
||||
{tag: 'field', attrs: {name: 'a'}},
|
||||
{tag: 'field', attrs: {name: 'b'}},
|
||||
{tag: 'field', attrs: {name: 'c'}}
|
||||
]
|
||||
}
|
||||
}};
|
||||
},
|
||||
'/web/dataset/call_kw:create': function (params) {
|
||||
records[42] = _.extend({}, params.params.args[0]);
|
||||
return {result: 42};
|
||||
},
|
||||
'/web/dataset/call_kw:read': function (params) {
|
||||
var id = params.params.args[0][0];
|
||||
if (id in records) {
|
||||
return {result: [records[id]]};
|
||||
}
|
||||
return {result: []};
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
asyncTest('newrecord', 6, function () {
|
||||
var got_defaults = false;
|
||||
instance.connection.responses['/web/dataset/call_kw:default_get'] = function (params) {
|
||||
var fields = params.params.args[0];
|
||||
deepEqual(
|
||||
fields, ['a', 'b', 'c'],
|
||||
"should ask defaults for all fields");
|
||||
got_defaults = true;
|
||||
return {result: {
|
||||
a: "qux",
|
||||
b: "quux"
|
||||
}};
|
||||
};
|
||||
|
||||
var ds = new instance.web.DataSetStatic(null, 'demo', null, [1]);
|
||||
var l = new instance.web.ListView({}, ds);
|
||||
l.set_editable(true);
|
||||
|
||||
l.appendTo($fix)
|
||||
.pipe(l.proxy('reload_content'))
|
||||
.pipe(function () {
|
||||
return l.start_edition();
|
||||
})
|
||||
.always(start)
|
||||
.pipe(function () {
|
||||
ok(got_defaults, "should have fetched default values for form");
|
||||
return l.save_edition();
|
||||
})
|
||||
.pipe(function (result) {
|
||||
ok(result.created, "should yield newly created record");
|
||||
equal(result.record.get('a'), "qux",
|
||||
"should have used default values");
|
||||
equal(result.record.get('b'), "quux",
|
||||
"should have used default values");
|
||||
ok(!result.record.get('c'),
|
||||
"should have no value if there was no default");
|
||||
})
|
||||
.fail(function (e) { ok(false, e && e.message || e); });
|
||||
});
|
||||
|
||||
module('list-edition-events', {
|
||||
setup: function () {
|
||||
baseSetup();
|
||||
_.extend(instance.connection.responses, {
|
||||
'/web/listview/load': function () {
|
||||
return {result: {
|
||||
type: 'tree',
|
||||
fields: {
|
||||
a: {type: 'char', string: "A"},
|
||||
b: {type: 'char', string: "B"},
|
||||
c: {type: 'char', string: "C"}
|
||||
},
|
||||
arch: {
|
||||
tag: 'tree',
|
||||
attrs: {},
|
||||
children: [
|
||||
{tag: 'field', attrs: {name: 'a'}},
|
||||
{tag: 'field', attrs: {name: 'b'}},
|
||||
{tag: 'field', attrs: {name: 'c'}}
|
||||
]
|
||||
}
|
||||
}};
|
||||
},
|
||||
'/web/dataset/call_kw:read': function (params) {
|
||||
return {result: [{
|
||||
id: 1,
|
||||
a: 'foo',
|
||||
b: 'bar',
|
||||
c: 'baz'
|
||||
}]};
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
asyncTest('edition events', 4, function () {
|
||||
var ds = new instance.web.DataSetStatic(null, 'demo', null, [1]);
|
||||
var o = {
|
||||
counter: 0,
|
||||
onEvent: function (e) { this.counter++; }
|
||||
};
|
||||
var l = new instance.web.ListView({}, ds);
|
||||
l.set_editable(true);
|
||||
l.on('edit:before edit:after', o, o.onEvent);
|
||||
l.appendTo($fix)
|
||||
.pipe(l.proxy('reload_content'))
|
||||
.always(start)
|
||||
.pipe(function () {
|
||||
ok(l.options.editable, "should be editable");
|
||||
equal(o.counter, 0, "should have seen no event yet");
|
||||
return l.start_edition(l.records.get(1));
|
||||
})
|
||||
.pipe(function () {
|
||||
ok(l.editor.is_editing(), "should be editing");
|
||||
equal(o.counter, 2, "should have seen two edition events");
|
||||
})
|
||||
.fail(function (e) { ok(false, e && e.message); });
|
||||
});
|
||||
|
||||
asyncTest('edition events: cancelling', 3, function () {
|
||||
var edit_after = false;
|
||||
var ds = new instance.web.DataSetStatic(null, 'demo', null, [1]);
|
||||
var l = new instance.web.ListView({}, ds);
|
||||
l.set_editable(true);
|
||||
l.on('edit:before', {}, function (e) {
|
||||
e.cancel = true;
|
||||
});
|
||||
l.on('edit:after', {}, function () {
|
||||
edit_after = true;
|
||||
});
|
||||
l.appendTo($fix)
|
||||
.pipe(l.proxy('reload_content'))
|
||||
.always(start)
|
||||
.pipe(function () {
|
||||
ok(l.options.editable, "should be editable");
|
||||
return l.start_edition();
|
||||
})
|
||||
// cancelling an event rejects the deferred
|
||||
.pipe($.Deferred().reject(), function () {
|
||||
ok(!l.editor.is_editing(), "should not be editing");
|
||||
ok(!edit_after, "should not have fired the edit:after event");
|
||||
return $.when();
|
||||
})
|
||||
.fail(function (e) { ok(false, e && e.message || e); });
|
||||
});
|
||||
});
|
|
@ -133,7 +133,7 @@ $(document).ready(function () {
|
|||
strictEqual(changed, 1);
|
||||
});
|
||||
|
||||
module('list-collections-degenerate', {
|
||||
module('list-collections', {
|
||||
setup: function () {
|
||||
openerp = window.openerp.init([]);
|
||||
window.openerp.web.corelib(openerp);
|
||||
|
@ -145,7 +145,7 @@ $(document).ready(function () {
|
|||
window.openerp.web.list(openerp);
|
||||
}
|
||||
});
|
||||
test('Fetch from collection', function () {
|
||||
test('degenerate-fetch', function () {
|
||||
var c = new openerp.web.list.Collection();
|
||||
strictEqual(c.length, 0);
|
||||
c.add({id: 1, value: 2});
|
||||
|
@ -163,7 +163,7 @@ $(document).ready(function () {
|
|||
strictEqual(r2.get('id'), 1);
|
||||
strictEqual(r2.get('value'), 2);
|
||||
});
|
||||
test('Add at index', function () {
|
||||
test('degenerate-indexed-add', function () {
|
||||
var c = new openerp.web.list.Collection([
|
||||
{id: 1, value: 5},
|
||||
{id: 2, value: 10},
|
||||
|
@ -175,7 +175,7 @@ $(document).ready(function () {
|
|||
strictEqual(c.at(1).get('value'), 55);
|
||||
strictEqual(c.at(3).get('value'), 20);
|
||||
});
|
||||
test('Remove record', function () {
|
||||
test('degenerate-remove', function () {
|
||||
var c = new openerp.web.list.Collection([
|
||||
{id: 1, value: 5},
|
||||
{id: 2, value: 10},
|
||||
|
@ -188,7 +188,7 @@ $(document).ready(function () {
|
|||
equal(c.get(2), undefined);
|
||||
strictEqual(c.at(1).get('value'), 20);
|
||||
});
|
||||
test('Remove unbind', function () {
|
||||
test('degenerate-remove-bound', function () {
|
||||
var changed = false,
|
||||
c = new openerp.web.list.Collection([ {id: 1, value: 5} ]);
|
||||
c.bind('change', function () { changed = true; });
|
||||
|
@ -198,7 +198,7 @@ $(document).ready(function () {
|
|||
ok(!changed, 'removed records should not trigger events in their ' +
|
||||
'parent collection');
|
||||
});
|
||||
test('Reset', function () {
|
||||
test('degenerate-reset', function () {
|
||||
var event, obj, c = new openerp.web.list.Collection([
|
||||
{id: 1, value: 5},
|
||||
{id: 2, value: 10},
|
||||
|
@ -218,7 +218,7 @@ $(document).ready(function () {
|
|||
strictEqual(c.length, 1);
|
||||
strictEqual(c.get(42).get('value'), 55);
|
||||
});
|
||||
test('Reset unbind', function () {
|
||||
test('degenerate-reset-bound', function () {
|
||||
var changed = false,
|
||||
c = new openerp.web.list.Collection([ {id: 1, value: 5} ]);
|
||||
c.bind('change', function () { changed = true; });
|
||||
|
@ -229,7 +229,7 @@ $(document).ready(function () {
|
|||
'parent collection');
|
||||
});
|
||||
|
||||
test('Events propagation', function () {
|
||||
test('degenerate-propagations', function () {
|
||||
var values = [];
|
||||
var c = new openerp.web.list.Collection([
|
||||
{id: 1, value: 5},
|
||||
|
@ -260,6 +260,82 @@ $(document).ready(function () {
|
|||
c.at(1).set('wealth', 5);
|
||||
strictEqual(total, 47);
|
||||
});
|
||||
test('degenerate-successor', function () {
|
||||
var root = new openerp.web.list.Collection([
|
||||
{id: 1, value: 1},
|
||||
{id: 2, value: 2},
|
||||
{id: 3, value: 3},
|
||||
{id: 4, value: 5},
|
||||
{id: 5, value: 8}
|
||||
]);
|
||||
|
||||
deepEqual(root.succ(root.at(2)).attributes,
|
||||
root.at(3).attributes,
|
||||
"should return the record at (index + 1) from the pivot");
|
||||
equal(root.succ(root.at(4)), null,
|
||||
"should return null as successor to last record");
|
||||
deepEqual(root.succ(root.at(4), {wraparound: true}).attributes,
|
||||
root.at(0).attributes,
|
||||
"should return index 0 as successor to last record if" +
|
||||
" wraparound is set");
|
||||
deepEqual(root.succ(root.at(2), {wraparound: true}).attributes,
|
||||
root.at(3).attributes,
|
||||
"wraparound should have no effect if not succ(last_record)");
|
||||
});
|
||||
test('successor', function () {
|
||||
var root = new openerp.web.list.Collection();
|
||||
root.proxy('first').add([{id: 1, value: 1}, {id: 2, value: 2}]);
|
||||
root.proxy('second').add([{id: 3, value: 3}, {id: 4, value: 5}]);
|
||||
root.proxy('third').add([{id: 5, value: 8}, {id: 6, value: 13}]);
|
||||
|
||||
deepEqual(root.succ(root.get(3)).attributes,
|
||||
root.get(4).attributes,
|
||||
"should get successor");
|
||||
equal(root.succ(root.get(4)),
|
||||
null,
|
||||
"successors do not cross collections");
|
||||
deepEqual(root.succ(root.get(4), {wraparound: true}).attributes,
|
||||
root.get(3).attributes,
|
||||
"should wraparound within a collection");
|
||||
});
|
||||
test('degenerate-predecessor', function () {
|
||||
var root = new openerp.web.list.Collection([
|
||||
{id: 1, value: 1},
|
||||
{id: 2, value: 2},
|
||||
{id: 3, value: 3},
|
||||
{id: 4, value: 5},
|
||||
{id: 5, value: 8}
|
||||
]);
|
||||
|
||||
deepEqual(root.pred(root.at(2)).attributes,
|
||||
root.at(1).attributes,
|
||||
"should return the record at (index - 1) from the pivot");
|
||||
equal(root.pred(root.at(0)), null,
|
||||
"should return null as predecessor to first record");
|
||||
deepEqual(root.pred(root.at(0), {wraparound: true}).attributes,
|
||||
root.at(4).attributes,
|
||||
"should return last record as predecessor to first record" +
|
||||
" if wraparound is set");
|
||||
deepEqual(root.pred(root.at(1), {wraparound: true}).attributes,
|
||||
root.at(0).attributes,
|
||||
"wraparound should have no effect if not pred(first_record)");
|
||||
});
|
||||
test('predecessor', function () {
|
||||
var root = new openerp.web.list.Collection();
|
||||
root.proxy('first').add([{id: 1, value: 1}, {id: 2, value: 2}]);
|
||||
root.proxy('second').add([{id: 3, value: 3}, {id: 4, value: 5}]);
|
||||
root.proxy('third').add([{id: 5, value: 8}, {id: 6, value: 13}]);
|
||||
|
||||
deepEqual(root.pred(root.get(4)).attributes,
|
||||
root.get(3).attributes,
|
||||
"should get predecessor");
|
||||
equal(root.pred(root.get(3)),
|
||||
null,
|
||||
"predecessor do not cross collections");
|
||||
deepEqual(root.pred(root.get(3), {wraparound: true}).attributes,
|
||||
root.get(4).attributes,
|
||||
"should wraparound within a collection");
|
||||
});
|
||||
|
||||
module('list-hofs', {
|
||||
setup: function () {
|
||||
|
@ -338,4 +414,33 @@ $(document).ready(function () {
|
|||
ids, [1, 2, 3, 10, 20, 30],
|
||||
'tree collections should be deeply iterated');
|
||||
});
|
||||
|
||||
module("list-weirds", {
|
||||
setup: function () {
|
||||
openerp = window.openerp.init([]);
|
||||
window.openerp.web.corelib(openerp);
|
||||
window.openerp.web.coresetup(openerp);
|
||||
window.openerp.web.chrome(openerp);
|
||||
// views loader stuff
|
||||
window.openerp.web.data(openerp);
|
||||
window.openerp.web.views(openerp);
|
||||
window.openerp.web.list(openerp);
|
||||
}
|
||||
});
|
||||
test('set-from-noid', function () {
|
||||
var root = new openerp.web.list.Collection();
|
||||
root.add({v: 3});
|
||||
root.at(0).set('id', 42);
|
||||
var record = root.get(42);
|
||||
equal(root.length, 1);
|
||||
equal(record.get('v'), 3, "should have fetched the original record");
|
||||
});
|
||||
test('set-from-previd', function () {
|
||||
var root = new openerp.web.list.Collection();
|
||||
root.add({id: 1, v: 2});
|
||||
root.get(1).set('id', 42);
|
||||
var record = root.get(42);
|
||||
equal(root.length, 1);
|
||||
equal(record.get('v'), 2, "should have fetched the original record");
|
||||
});
|
||||
});
|
||||
|
|
|
@ -9,21 +9,6 @@ $(document).ready(function () {
|
|||
openerp.web.Foo2 = {};
|
||||
}
|
||||
});
|
||||
test('key fetch', function () {
|
||||
var reg = new openerp.web.Registry({
|
||||
foo: 'openerp.web.Foo',
|
||||
bar: 'openerp.web.Bar',
|
||||
quux: 'openerp.web.Quux'
|
||||
});
|
||||
|
||||
strictEqual(reg.get_object('foo'), openerp.web.Foo);
|
||||
raises(function () { reg.get_object('qux'); },
|
||||
openerp.web.KeyNotFound,
|
||||
"Unknown keys should raise KeyNotFound");
|
||||
raises(function () { reg.get_object('quux'); },
|
||||
openerp.web.ObjectNotFound,
|
||||
"Incorrect file paths should raise ObjectNotFound");
|
||||
});
|
||||
test('key set', function () {
|
||||
var reg = new openerp.web.Registry();
|
||||
|
||||
|
|
|
@ -1,37 +1,8 @@
|
|||
$(document).ready(function () {
|
||||
var xhr = QWeb2.Engine.prototype.get_xhr();
|
||||
xhr.open('GET', '/web/static/src/xml/base.xml', false);
|
||||
xhr.send(null);
|
||||
var doc = xhr.responseXML;
|
||||
|
||||
var noop = function () {};
|
||||
/**
|
||||
* Make connection RPC responses mockable by setting keys on the
|
||||
* Connection#responses object (key is the URL, value is the function to
|
||||
* call with the RPC request payload)
|
||||
*
|
||||
* @param {openerp.web.Connection} connection connection instance to mockify
|
||||
* @param {Object} [responses] url:function mapping to seed the mock connection
|
||||
*/
|
||||
var mockifyRPC = function (connection, responses) {
|
||||
connection.responses = responses || {};
|
||||
connection.rpc_function = function (url, payload) {
|
||||
if (!(url.url in this.responses)) {
|
||||
return $.Deferred().reject({}, 'failed', _.str.sprintf("Url %s not found in mock responses", url.url)).promise();
|
||||
}
|
||||
return $.when(this.responses[url.url](payload));
|
||||
};
|
||||
};
|
||||
|
||||
var instance;
|
||||
module('query', {
|
||||
setup: function () {
|
||||
instance = window.openerp.init([]);
|
||||
window.openerp.web.corelib(instance);
|
||||
window.openerp.web.coresetup(instance);
|
||||
window.openerp.web.chrome(instance);
|
||||
window.openerp.web.data(instance);
|
||||
window.openerp.web.search(instance);
|
||||
instance = openerp.testing.instanceFor('search');
|
||||
}
|
||||
});
|
||||
test('Adding a facet to the query creates a facet and a value', function () {
|
||||
|
@ -167,16 +138,11 @@ $(document).ready(function () {
|
|||
|
||||
module('defaults', {
|
||||
setup: function () {
|
||||
instance = window.openerp.init([]);
|
||||
window.openerp.web.corelib(instance);
|
||||
window.openerp.web.coresetup(instance);
|
||||
window.openerp.web.chrome(instance);
|
||||
window.openerp.web.data(instance);
|
||||
window.openerp.web.search(instance);
|
||||
instance = openerp.testing.instanceFor('search');
|
||||
|
||||
instance.web.qweb.add_template(doc);
|
||||
openerp.testing.loadTemplate(instance);
|
||||
|
||||
mockifyRPC(instance.connection);
|
||||
openerp.testing.mockifyRPC(instance);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -404,18 +370,11 @@ $(document).ready(function () {
|
|||
|
||||
module('completions', {
|
||||
setup: function () {
|
||||
instance = window.openerp.init([]);
|
||||
window.openerp.web.corelib(instance);
|
||||
window.openerp.web.coresetup(instance);
|
||||
window.openerp.web.chrome(instance);
|
||||
window.openerp.web.data(instance);
|
||||
// date complete
|
||||
window.openerp.web.formats(instance);
|
||||
window.openerp.web.search(instance);
|
||||
instance = openerp.testing.instanceFor('search');
|
||||
|
||||
instance.web.qweb.add_template(doc);
|
||||
openerp.testing.loadTemplate(instance);
|
||||
|
||||
mockifyRPC(instance.connection);
|
||||
openerp.testing.mockifyRPC(instance);
|
||||
}
|
||||
});
|
||||
asyncTest('calling', 4, function () {
|
||||
|
@ -432,10 +391,7 @@ $(document).ready(function () {
|
|||
}
|
||||
});
|
||||
view.appendTo($('#qunit-fixture'))
|
||||
.always(start)
|
||||
.fail(function (error) { ok(false, error.message); })
|
||||
.done(function () {
|
||||
stop();
|
||||
view.complete_global_search({term: "dum"}, function (completions) {
|
||||
start();
|
||||
equal(completions.length, 1, "should have a single completion");
|
||||
|
@ -454,7 +410,11 @@ $(document).ready(function () {
|
|||
var completion = {
|
||||
label: "Dummy",
|
||||
facet: {
|
||||
field: {get_domain: noop, get_context: noop, get_groupby: noop},
|
||||
field: {
|
||||
get_domain: openerp.testing.noop,
|
||||
get_context: openerp.testing.noop,
|
||||
get_groupby: openerp.testing.noop
|
||||
},
|
||||
category: 'Dummy',
|
||||
values: [{label: 'dummy', value: 42}]
|
||||
}
|
||||
|
@ -476,7 +436,11 @@ $(document).ready(function () {
|
|||
});
|
||||
});
|
||||
asyncTest('facet selection: new value existing facet', 3, function () {
|
||||
var field = {get_domain: noop, get_context: noop, get_groupby: noop};
|
||||
var field = {
|
||||
get_domain: openerp.testing.noop,
|
||||
get_context: openerp.testing.noop,
|
||||
get_groupby: openerp.testing.noop
|
||||
};
|
||||
var completion = {
|
||||
label: "Dummy",
|
||||
facet: {
|
||||
|
@ -663,16 +627,11 @@ $(document).ready(function () {
|
|||
|
||||
module('search-serialization', {
|
||||
setup: function () {
|
||||
instance = window.openerp.init([]);
|
||||
window.openerp.web.corelib(instance);
|
||||
window.openerp.web.coresetup(instance);
|
||||
window.openerp.web.chrome(instance);
|
||||
window.openerp.web.data(instance);
|
||||
window.openerp.web.search(instance);
|
||||
instance = openerp.testing.instanceFor('search');
|
||||
|
||||
instance.web.qweb.add_template(doc);
|
||||
openerp.testing.loadTemplate(instance);
|
||||
|
||||
mockifyRPC(instance.connection);
|
||||
openerp.testing.mockifyRPC(instance);
|
||||
}
|
||||
});
|
||||
asyncTest('No facet, no call', 6, function () {
|
||||
|
@ -940,16 +899,11 @@ $(document).ready(function () {
|
|||
|
||||
module('removal', {
|
||||
setup: function () {
|
||||
instance = window.openerp.init([]);
|
||||
window.openerp.web.corelib(instance);
|
||||
window.openerp.web.coresetup(instance);
|
||||
window.openerp.web.chrome(instance);
|
||||
window.openerp.web.data(instance);
|
||||
window.openerp.web.search(instance);
|
||||
instance = openerp.testing.instanceFor('search');
|
||||
|
||||
instance.web.qweb.add_template(doc);
|
||||
openerp.testing.loadTemplate(instance);
|
||||
|
||||
mockifyRPC(instance.connection);
|
||||
openerp.testing.mockifyRPC(instance);
|
||||
}
|
||||
});
|
||||
asyncTest('clear button', function () {
|
||||
|
@ -975,16 +929,11 @@ $(document).ready(function () {
|
|||
|
||||
module('drawer', {
|
||||
setup: function () {
|
||||
instance = window.openerp.init([]);
|
||||
window.openerp.web.corelib(instance);
|
||||
window.openerp.web.coresetup(instance);
|
||||
window.openerp.web.chrome(instance);
|
||||
window.openerp.web.data(instance);
|
||||
window.openerp.web.search(instance);
|
||||
instance = openerp.testing.instanceFor('search');
|
||||
|
||||
instance.web.qweb.add_template(doc);
|
||||
openerp.testing.loadTemplate(instance);
|
||||
|
||||
mockifyRPC(instance.connection);
|
||||
openerp.testing.mockifyRPC(instance);
|
||||
}
|
||||
});
|
||||
asyncTest('is-drawn', 2, function () {
|
||||
|
@ -1003,16 +952,11 @@ $(document).ready(function () {
|
|||
|
||||
module('filters', {
|
||||
setup: function () {
|
||||
instance = window.openerp.init([]);
|
||||
window.openerp.web.corelib(instance);
|
||||
window.openerp.web.coresetup(instance);
|
||||
window.openerp.web.chrome(instance);
|
||||
window.openerp.web.data(instance);
|
||||
window.openerp.web.search(instance);
|
||||
instance = openerp.testing.instanceFor('search');
|
||||
|
||||
instance.web.qweb.add_template(doc);
|
||||
openerp.testing.loadTemplate(instance);
|
||||
|
||||
mockifyRPC(instance.connection, {
|
||||
openerp.testing.mockifyRPC(instance, {
|
||||
'/web/searchview/load': function () {
|
||||
// view with a single group of filters
|
||||
return {result: {fields_view: {
|
||||
|
@ -1117,17 +1061,11 @@ $(document).ready(function () {
|
|||
|
||||
module('saved_filters', {
|
||||
setup: function () {
|
||||
instance = window.openerp.init([]);
|
||||
window.openerp.web.corelib(instance);
|
||||
window.openerp.web.coresetup(instance);
|
||||
window.openerp.web.chrome(instance);
|
||||
window.openerp.web.data(instance);
|
||||
window.openerp.web.formats(instance);
|
||||
window.openerp.web.search(instance);
|
||||
instance = openerp.testing.instanceFor('search');
|
||||
|
||||
instance.web.qweb.add_template(doc);
|
||||
openerp.testing.loadTemplate(instance);
|
||||
|
||||
mockifyRPC(instance.connection);
|
||||
openerp.testing.mockifyRPC(instance);
|
||||
}
|
||||
});
|
||||
asyncTest('checkboxing', 6, function () {
|
||||
|
@ -1183,17 +1121,11 @@ $(document).ready(function () {
|
|||
|
||||
module('advanced', {
|
||||
setup: function () {
|
||||
instance = window.openerp.init([]);
|
||||
window.openerp.web.corelib(instance);
|
||||
window.openerp.web.coresetup(instance);
|
||||
window.openerp.web.chrome(instance);
|
||||
window.openerp.web.data(instance);
|
||||
window.openerp.web.formats(instance);
|
||||
window.openerp.web.search(instance);
|
||||
instance = openerp.testing.instanceFor('search');
|
||||
|
||||
instance.web.qweb.add_template(doc);
|
||||
openerp.testing.loadTemplate(instance);
|
||||
|
||||
mockifyRPC(instance.connection);
|
||||
openerp.testing.mockifyRPC(instance);
|
||||
}
|
||||
});
|
||||
asyncTest('single-advanced', 6, function () {
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
<script src="/web/static/lib/backbone/backbone.js" type="text/javascript"></script>
|
||||
|
||||
<!-- jquery -->
|
||||
<script src="/web/static/lib/jquery/jquery-1.7.2b1.js"></script>
|
||||
<script src="/web/static/lib/jquery/jquery-1.7.2.js"></script>
|
||||
<script src="/web/static/lib/jquery.ui/js/jquery-ui-1.8.17.custom.min.js"></script>
|
||||
<script src="/web/static/lib/jquery.ba-bbq/jquery.ba-bbq.js"></script>
|
||||
|
||||
|
@ -38,6 +38,12 @@
|
|||
<script src="/web/static/src/js/search.js"></script>
|
||||
<script src="/web/static/src/js/view_form.js"></script>
|
||||
<script src="/web/static/src/js/view_list.js"></script>
|
||||
<script src="/web/static/src/js/view_list_editable.js"></script>
|
||||
|
||||
<script src="/web/static/test/testing.js"></script>
|
||||
<script type="text/javascript">
|
||||
QUnit.config.testTimeout = 500;
|
||||
</script>
|
||||
</head>
|
||||
<body id="oe" class="openerp">
|
||||
<h1 id="qunit-header">OpenERP web Test Suite</h1>
|
||||
|
@ -55,4 +61,5 @@
|
|||
<script type="text/javascript" src="/web/static/test/rpc.js"></script>
|
||||
<script type="text/javascript" src="/web/static/test/evals.js"></script>
|
||||
<script type="text/javascript" src="/web/static/test/search.js"></script>
|
||||
<script type="text/javascript" src="/web/static/test/list-editable.js"></script>
|
||||
</html>
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
// Test support structures and methods for OpenERP
|
||||
openerp.testing = (function () {
|
||||
var xhr = QWeb2.Engine.prototype.get_xhr();
|
||||
xhr.open('GET', '/web/static/src/xml/base.xml', false);
|
||||
xhr.send(null);
|
||||
var doc = xhr.responseXML;
|
||||
|
||||
var dependencies = {
|
||||
corelib: [],
|
||||
coresetup: ['corelib'],
|
||||
data: ['corelib', 'coresetup'],
|
||||
dates: [],
|
||||
formats: ['coresetup', 'dates'],
|
||||
chrome: ['corelib', 'coresetup'],
|
||||
views: ['corelib', 'coresetup', 'data', 'chrome'],
|
||||
search: ['data', 'coresetup', 'formats'],
|
||||
list: ['views', 'data'],
|
||||
form: ['data', 'views', 'list', 'formats'],
|
||||
list_editable: ['list', 'form', 'data'],
|
||||
};
|
||||
|
||||
return {
|
||||
/**
|
||||
* Function which does not do anything
|
||||
*/
|
||||
noop: function () { },
|
||||
/**
|
||||
* Loads 'base.xml' template file into qweb for the provided instance
|
||||
*
|
||||
* @param instance openerp instance being initialized, to load the template file in
|
||||
*/
|
||||
loadTemplate: function (instance) {
|
||||
instance.web.qweb.add_template(doc);
|
||||
},
|
||||
/**
|
||||
* Alter provided instance's ``connection`` attribute to make response
|
||||
* mockable:
|
||||
*
|
||||
* * The ``responses`` parameter can be used to provide a map of (RPC)
|
||||
* paths (e.g. ``/web/view/load``) to a function returning a response
|
||||
* to the query.
|
||||
* * ``instance,connection`` grows a ``responses`` attribute which is
|
||||
* a map of the same (and is in fact initialized to the ``responses``
|
||||
* parameter if one is provided)
|
||||
*
|
||||
* Note that RPC requests to un-mocked URLs will be rejected with an
|
||||
* error message: only explicitly specified urls will get a response.
|
||||
*
|
||||
* Mocked connections will *never* perform an actual RPC connection.
|
||||
*
|
||||
* @param instance openerp instance being initialized
|
||||
* @param {Object} [responses]
|
||||
*/
|
||||
mockifyRPC: function (instance, responses) {
|
||||
var connection = instance.connection;
|
||||
connection.responses = responses || {};
|
||||
connection.rpc_function = function (url, payload) {
|
||||
var fn = this.responses[url.url + ':' + payload.params.method]
|
||||
|| this.responses[url.url];
|
||||
|
||||
if (!fn) {
|
||||
return $.Deferred().reject({}, 'failed',
|
||||
_.str.sprintf("Url %s not found in mock responses, with arguments %s",
|
||||
url.url, JSON.stringify(payload.params))
|
||||
).promise();
|
||||
}
|
||||
return $.when(fn(payload));
|
||||
};
|
||||
},
|
||||
/**
|
||||
* Creates an openerp web instance loading the specified module after
|
||||
* all of its dependencies.
|
||||
*
|
||||
* @param {String} module
|
||||
* @returns OpenERP Web instance
|
||||
*/
|
||||
instanceFor: function (module) {
|
||||
var instance = openerp.init([]);
|
||||
this._load(instance, module);
|
||||
return instance;
|
||||
},
|
||||
_load: function (instance, module, loaded) {
|
||||
if (!loaded) { loaded = []; }
|
||||
|
||||
var deps = dependencies[module];
|
||||
if (!deps) { throw new Error("Unknown dependencies for " + module); }
|
||||
|
||||
var to_load = _.difference(deps, loaded);
|
||||
while (!_.isEmpty(to_load)) {
|
||||
this._load(instance, to_load[0], loaded);
|
||||
to_load = _.difference(deps, loaded);
|
||||
}
|
||||
openerp.web[module](instance);
|
||||
loaded.push(module);
|
||||
}
|
||||
}
|
||||
})();
|
|
@ -8,135 +8,135 @@ msgstr ""
|
|||
"Project-Id-Version: openerp-web\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2012-07-02 09:06+0200\n"
|
||||
"PO-Revision-Date: 2012-02-22 02:18+0000\n"
|
||||
"Last-Translator: Masaki Yamaya <Unknown>\n"
|
||||
"PO-Revision-Date: 2012-07-19 01:27+0000\n"
|
||||
"Last-Translator: Akira Hiyama <Unknown>\n"
|
||||
"Language-Team: Japanese <ja@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: 2012-07-03 05:55+0000\n"
|
||||
"X-Generator: Launchpad (build 15531)\n"
|
||||
"X-Launchpad-Export-Date: 2012-07-20 04:45+0000\n"
|
||||
"X-Generator: Launchpad (build 15644)\n"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_calendar/static/src/js/calendar.js:12
|
||||
#: addons/web_calendar/static/src/js/calendar.js:11
|
||||
msgid "Calendar"
|
||||
msgstr "カレンダー"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_calendar/static/src/js/calendar.js:73
|
||||
#: addons/web_calendar/static/src/js/calendar.js:70
|
||||
msgid "Filter"
|
||||
msgstr ""
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_calendar/static/src/js/calendar.js:139
|
||||
msgid "Today"
|
||||
msgstr ""
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_calendar/static/src/js/calendar.js:140
|
||||
msgid "Day"
|
||||
msgstr ""
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_calendar/static/src/js/calendar.js:141
|
||||
msgid "Week"
|
||||
msgstr ""
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_calendar/static/src/js/calendar.js:142
|
||||
msgid "Month"
|
||||
msgstr ""
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_calendar/static/src/js/calendar.js:143
|
||||
msgid "New event"
|
||||
msgstr ""
|
||||
msgstr "フィルタ"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_calendar/static/src/js/calendar.js:144
|
||||
msgid "Save"
|
||||
msgstr ""
|
||||
msgid "Today"
|
||||
msgstr "本日"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_calendar/static/src/js/calendar.js:145
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
msgid "Day"
|
||||
msgstr "日"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_calendar/static/src/js/calendar.js:146
|
||||
msgid "Details"
|
||||
msgstr ""
|
||||
msgid "Week"
|
||||
msgstr "週"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_calendar/static/src/js/calendar.js:147
|
||||
msgid "Edit"
|
||||
msgstr ""
|
||||
msgid "Month"
|
||||
msgstr "月"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_calendar/static/src/js/calendar.js:148
|
||||
msgid "Delete"
|
||||
msgstr ""
|
||||
msgid "New event"
|
||||
msgstr "新規イベント"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_calendar/static/src/js/calendar.js:149
|
||||
msgid "Save"
|
||||
msgstr "保存"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_calendar/static/src/js/calendar.js:150
|
||||
msgid "Event will be deleted permanently, are you sure?"
|
||||
msgstr ""
|
||||
msgid "Cancel"
|
||||
msgstr "キャンセル"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_calendar/static/src/js/calendar.js:151
|
||||
#: addons/web_calendar/static/src/js/calendar.js:164
|
||||
msgid "Description"
|
||||
msgstr ""
|
||||
msgid "Details"
|
||||
msgstr "詳細"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_calendar/static/src/js/calendar.js:152
|
||||
msgid "Time period"
|
||||
msgstr ""
|
||||
msgid "Edit"
|
||||
msgstr "編集"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_calendar/static/src/js/calendar.js:153
|
||||
msgid "Full day"
|
||||
msgstr ""
|
||||
msgid "Delete"
|
||||
msgstr "削除"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_calendar/static/src/js/calendar.js:155
|
||||
msgid "Event will be deleted permanently, are you sure?"
|
||||
msgstr "イベントは完全に削除されます。よろしいですか?"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_calendar/static/src/js/calendar.js:156
|
||||
msgid "Do you want to edit the whole set of repeated events?"
|
||||
msgstr ""
|
||||
#: addons/web_calendar/static/src/js/calendar.js:169
|
||||
msgid "Description"
|
||||
msgstr "詳細"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_calendar/static/src/js/calendar.js:157
|
||||
msgid "Repeat event"
|
||||
msgstr ""
|
||||
msgid "Time period"
|
||||
msgstr "期間"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_calendar/static/src/js/calendar.js:158
|
||||
msgid "Disabled"
|
||||
msgstr ""
|
||||
msgid "Full day"
|
||||
msgstr "終日"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_calendar/static/src/js/calendar.js:159
|
||||
msgid "Enabled"
|
||||
msgstr ""
|
||||
#: addons/web_calendar/static/src/js/calendar.js:161
|
||||
msgid "Do you want to edit the whole set of repeated events?"
|
||||
msgstr "繰り返しイベントのセット全体を編集しますか?"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_calendar/static/src/js/calendar.js:162
|
||||
#: addons/web_calendar/static/src/js/calendar.js:170
|
||||
msgid "Agenda"
|
||||
msgstr ""
|
||||
msgid "Repeat event"
|
||||
msgstr "繰り返しイベント"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_calendar/static/src/js/calendar.js:163
|
||||
msgid "Date"
|
||||
msgstr ""
|
||||
msgid "Disabled"
|
||||
msgstr "無効"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_calendar/static/src/js/calendar.js:164
|
||||
msgid "Enabled"
|
||||
msgstr "有効"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_calendar/static/src/js/calendar.js:167
|
||||
msgid "Year"
|
||||
msgstr ""
|
||||
#: addons/web_calendar/static/src/js/calendar.js:175
|
||||
msgid "Agenda"
|
||||
msgstr "議事"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_calendar/static/src/xml/web_calendar.xml:8
|
||||
#: addons/web_calendar/static/src/xml/web_calendar.xml:9
|
||||
#: addons/web_calendar/static/src/js/calendar.js:168
|
||||
msgid "Date"
|
||||
msgstr "日付"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_calendar/static/src/js/calendar.js:172
|
||||
msgid "Year"
|
||||
msgstr "年"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_calendar/static/src/xml/web_calendar.xml:5
|
||||
#: addons/web_calendar/static/src/xml/web_calendar.xml:6
|
||||
msgid " "
|
||||
msgstr " "
|
||||
|
||||
|
|
|
@ -8,29 +8,29 @@ msgstr ""
|
|||
"Project-Id-Version: openerp-web\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2012-07-02 09:06+0200\n"
|
||||
"PO-Revision-Date: 2012-03-26 22:14+0000\n"
|
||||
"Last-Translator: Masaki Yamaya <Unknown>\n"
|
||||
"PO-Revision-Date: 2012-07-19 01:29+0000\n"
|
||||
"Last-Translator: Akira Hiyama <Unknown>\n"
|
||||
"Language-Team: Japanese <ja@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: 2012-07-03 05:55+0000\n"
|
||||
"X-Generator: Launchpad (build 15531)\n"
|
||||
"X-Launchpad-Export-Date: 2012-07-20 04:45+0000\n"
|
||||
"X-Generator: Launchpad (build 15644)\n"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_dashboard/static/src/js/dashboard.js:61
|
||||
#: addons/web_dashboard/static/src/js/dashboard.js:60
|
||||
msgid "Edit Layout"
|
||||
msgstr "レイアウトを編集"
|
||||
msgstr "レイアウトの編集"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_dashboard/static/src/js/dashboard.js:107
|
||||
#: addons/web_dashboard/static/src/js/dashboard.js:106
|
||||
msgid "Are you sure you want to remove this item ?"
|
||||
msgstr "この項目を取り除きますか?"
|
||||
msgstr "この項目を削除しますか?"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:4
|
||||
msgid "Reset Layout.."
|
||||
msgstr "レイアウトをリセット"
|
||||
msgstr "レイアウトのリセット"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:6
|
||||
|
@ -40,12 +40,12 @@ msgstr "リセット"
|
|||
#. openerp-web
|
||||
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:8
|
||||
msgid "Change Layout.."
|
||||
msgstr "レイアウトを変更…"
|
||||
msgstr "レイアウトの変更…"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:10
|
||||
msgid "Change Layout"
|
||||
msgstr "レイアウトを変更"
|
||||
msgstr "レイアウトの変更"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:27
|
||||
|
@ -60,7 +60,7 @@ msgstr "作成"
|
|||
#. openerp-web
|
||||
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:39
|
||||
msgid "Choose dashboard layout"
|
||||
msgstr "ダッシュボードのレイアウトを選択"
|
||||
msgstr "ダッシュボードレイアウトの選択"
|
||||
|
||||
#, python-format
|
||||
#~ msgid "Execute task \"%s\""
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
# Ukrainian translation for openerp-web
|
||||
# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012
|
||||
# This file is distributed under the same license as the openerp-web package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2012.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: openerp-web\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2012-07-02 09:06+0200\n"
|
||||
"PO-Revision-Date: 2012-07-22 09:32+0000\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: Ukrainian <uk@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: 2012-07-23 05:21+0000\n"
|
||||
"X-Generator: Launchpad (build 15654)\n"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_dashboard/static/src/js/dashboard.js:60
|
||||
msgid "Edit Layout"
|
||||
msgstr ""
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_dashboard/static/src/js/dashboard.js:106
|
||||
msgid "Are you sure you want to remove this item ?"
|
||||
msgstr ""
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:4
|
||||
msgid "Reset Layout.."
|
||||
msgstr ""
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:6
|
||||
msgid "Reset"
|
||||
msgstr ""
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:8
|
||||
msgid "Change Layout.."
|
||||
msgstr ""
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:10
|
||||
msgid "Change Layout"
|
||||
msgstr ""
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:27
|
||||
msgid " "
|
||||
msgstr ""
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:28
|
||||
msgid "Create"
|
||||
msgstr ""
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:39
|
||||
msgid "Choose dashboard layout"
|
||||
msgstr ""
|
|
@ -37,11 +37,12 @@ instance.web.form.DashBoard = instance.web.form.FormWidget.extend({
|
|||
delete(action.attrs.width);
|
||||
delete(action.attrs.height);
|
||||
delete(action.attrs.colspan);
|
||||
self.rpc('/web/action/load', {
|
||||
action_id: parseInt(action.attrs.name, 10)
|
||||
}, function(result) {
|
||||
self.on_load_action(result, column_index + '_' + action_index, action.attrs);
|
||||
});
|
||||
var action_id = _.str.toNumber(action.attrs.name);
|
||||
if (!_.isNaN(action_id)) {
|
||||
self.rpc('/web/action/load', {action_id: action_id}, function(result) {
|
||||
self.on_load_action(result, column_index + '_' + action_index, action.attrs);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
</div>
|
||||
</t>
|
||||
<t t-name="DashBoard.xml">
|
||||
<form t-att-string="form_title">
|
||||
<form t-att-string="form_title" version="7.0">
|
||||
<board t-att-style="style">
|
||||
<column t-foreach="columns" t-as="column">
|
||||
<action t-foreach="column" t-as="action" t-att="action"/>
|
||||
|
|
|
@ -8,14 +8,14 @@ msgstr ""
|
|||
"Project-Id-Version: openerp-web\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2012-07-02 09:06+0200\n"
|
||||
"PO-Revision-Date: 2012-03-26 22:02+0000\n"
|
||||
"Last-Translator: Masaki Yamaya <Unknown>\n"
|
||||
"PO-Revision-Date: 2012-07-19 01:37+0000\n"
|
||||
"Last-Translator: Akira Hiyama <Unknown>\n"
|
||||
"Language-Team: Japanese <ja@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: 2012-07-03 05:55+0000\n"
|
||||
"X-Generator: Launchpad (build 15531)\n"
|
||||
"X-Launchpad-Export-Date: 2012-07-20 04:45+0000\n"
|
||||
"X-Generator: Launchpad (build 15644)\n"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_diagram/static/src/js/diagram.js:11
|
||||
|
@ -25,7 +25,7 @@ msgstr "ダイアグラム"
|
|||
#. openerp-web
|
||||
#: addons/web_diagram/static/src/js/diagram.js:165
|
||||
msgid "Are you sure?"
|
||||
msgstr ""
|
||||
msgstr "本当によろしいですか?"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_diagram/static/src/js/diagram.js:195
|
||||
|
@ -35,6 +35,10 @@ msgid ""
|
|||
"\n"
|
||||
"Are you sure ?"
|
||||
msgstr ""
|
||||
"このノードの削除は元に戻すことができません。\n"
|
||||
"また、接続している全ての取引を削除します。\n"
|
||||
"\n"
|
||||
"本当によろしいですか?"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_diagram/static/src/js/diagram.js:213
|
||||
|
@ -43,18 +47,21 @@ msgid ""
|
|||
"\n"
|
||||
"Are you sure ?"
|
||||
msgstr ""
|
||||
"この取引の削除は元に戻すことができません。\n"
|
||||
"\n"
|
||||
"本当によろしいですか?"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_diagram/static/src/js/diagram.js:224
|
||||
#: addons/web_diagram/static/src/js/diagram.js:257
|
||||
msgid "Activity"
|
||||
msgstr "アクティビティ"
|
||||
msgstr "活動"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_diagram/static/src/js/diagram.js:232
|
||||
#: addons/web_diagram/static/src/js/diagram.js:296
|
||||
msgid "Open: "
|
||||
msgstr "開く: "
|
||||
msgstr "開く: "
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_diagram/static/src/js/diagram.js:262
|
||||
|
@ -66,9 +73,9 @@ msgstr "作成:"
|
|||
#: addons/web_diagram/static/src/js/diagram.js:289
|
||||
#: addons/web_diagram/static/src/js/diagram.js:308
|
||||
msgid "Transition"
|
||||
msgstr "変遷"
|
||||
msgstr "遷移"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_diagram/static/src/xml/base_diagram.xml:6
|
||||
msgid "New Node"
|
||||
msgstr "新しいノード"
|
||||
msgstr "新規ノード"
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
# Hungarian translation for openerp-web
|
||||
# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012
|
||||
# This file is distributed under the same license as the openerp-web package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2012.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: openerp-web\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2012-07-02 09:06+0200\n"
|
||||
"PO-Revision-Date: 2012-07-19 06:30+0000\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: Hungarian <hu@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: 2012-07-20 04:45+0000\n"
|
||||
"X-Generator: Launchpad (build 15644)\n"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_gantt/static/src/js/gantt.js:11
|
||||
msgid "Gantt"
|
||||
msgstr ""
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_gantt/static/src/xml/web_gantt.xml:10
|
||||
msgid "Create"
|
||||
msgstr "Létrehozás"
|
|
@ -8,14 +8,14 @@ msgstr ""
|
|||
"Project-Id-Version: openerp-web\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2012-07-02 09:06+0200\n"
|
||||
"PO-Revision-Date: 2012-03-26 21:57+0000\n"
|
||||
"Last-Translator: Masaki Yamaya <Unknown>\n"
|
||||
"PO-Revision-Date: 2012-07-19 01:37+0000\n"
|
||||
"Last-Translator: Akira Hiyama <Unknown>\n"
|
||||
"Language-Team: Japanese <ja@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: 2012-07-03 05:55+0000\n"
|
||||
"X-Generator: Launchpad (build 15531)\n"
|
||||
"X-Launchpad-Export-Date: 2012-07-20 04:45+0000\n"
|
||||
"X-Generator: Launchpad (build 15644)\n"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_gantt/static/src/js/gantt.js:11
|
||||
|
@ -25,4 +25,4 @@ msgstr "ガント"
|
|||
#. openerp-web
|
||||
#: addons/web_gantt/static/src/xml/web_gantt.xml:10
|
||||
msgid "Create"
|
||||
msgstr "作成する"
|
||||
msgstr "作成"
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
# Hungarian translation for openerp-web
|
||||
# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012
|
||||
# This file is distributed under the same license as the openerp-web package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2012.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: openerp-web\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2012-07-02 09:06+0200\n"
|
||||
"PO-Revision-Date: 2012-07-19 06:27+0000\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: Hungarian <hu@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: 2012-07-20 04:45+0000\n"
|
||||
"X-Generator: Launchpad (build 15644)\n"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_graph/static/src/js/graph.js:19
|
||||
msgid "Graph"
|
||||
msgstr "Grafikon"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_graph/static/src/xml/web_graph.xml:5
|
||||
msgid "Graph Options"
|
||||
msgstr ""
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_graph/static/src/xml/web_graph.xml:7
|
||||
msgid "Graph Mode"
|
||||
msgstr ""
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_graph/static/src/xml/web_graph.xml:11
|
||||
msgid "Pie"
|
||||
msgstr ""
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_graph/static/src/xml/web_graph.xml:12
|
||||
msgid "Bars"
|
||||
msgstr ""
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_graph/static/src/xml/web_graph.xml:14
|
||||
msgid "Lines"
|
||||
msgstr ""
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_graph/static/src/xml/web_graph.xml:15
|
||||
msgid "Areas"
|
||||
msgstr ""
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_graph/static/src/xml/web_graph.xml:18
|
||||
msgid "Radar"
|
||||
msgstr ""
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_graph/static/src/xml/web_graph.xml:20
|
||||
msgid "Legend"
|
||||
msgstr ""
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_graph/static/src/xml/web_graph.xml:24
|
||||
msgid "Hidden"
|
||||
msgstr ""
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_graph/static/src/xml/web_graph.xml:25
|
||||
msgid "Inside"
|
||||
msgstr ""
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_graph/static/src/xml/web_graph.xml:26
|
||||
msgid "Top"
|
||||
msgstr ""
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_graph/static/src/xml/web_graph.xml:28
|
||||
msgid "Actions"
|
||||
msgstr ""
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_graph/static/src/xml/web_graph.xml:32
|
||||
msgid "Switch Axis"
|
||||
msgstr ""
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_graph/static/src/xml/web_graph.xml:33
|
||||
msgid "Show Data"
|
||||
msgstr ""
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_graph/static/src/xml/web_graph.xml:34
|
||||
msgid "Download as PNG"
|
||||
msgstr ""
|
|
@ -8,91 +8,91 @@ msgstr ""
|
|||
"Project-Id-Version: openerp-web\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2012-07-02 09:06+0200\n"
|
||||
"PO-Revision-Date: 2012-02-22 02:21+0000\n"
|
||||
"Last-Translator: Masaki Yamaya <Unknown>\n"
|
||||
"PO-Revision-Date: 2012-07-19 03:25+0000\n"
|
||||
"Last-Translator: Akira Hiyama <Unknown>\n"
|
||||
"Language-Team: Japanese <ja@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: 2012-07-03 05:55+0000\n"
|
||||
"X-Generator: Launchpad (build 15531)\n"
|
||||
"X-Launchpad-Export-Date: 2012-07-20 04:45+0000\n"
|
||||
"X-Generator: Launchpad (build 15644)\n"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_graph/static/src/js/graph.js:22
|
||||
#: addons/web_graph/static/src/js/graph.js:19
|
||||
msgid "Graph"
|
||||
msgstr "グラフ"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_graph/static/src/xml/web_graph.xml:5
|
||||
msgid "Graph Options"
|
||||
msgstr ""
|
||||
msgstr "グラフオプション"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_graph/static/src/xml/web_graph.xml:7
|
||||
msgid "Graph Mode"
|
||||
msgstr ""
|
||||
msgstr "グラフモード"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_graph/static/src/xml/web_graph.xml:11
|
||||
msgid "Pie"
|
||||
msgstr ""
|
||||
msgstr "パイ"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_graph/static/src/xml/web_graph.xml:12
|
||||
msgid "Bars"
|
||||
msgstr ""
|
||||
msgstr "バー"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_graph/static/src/xml/web_graph.xml:14
|
||||
msgid "Lines"
|
||||
msgstr ""
|
||||
msgstr "ライン"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_graph/static/src/xml/web_graph.xml:15
|
||||
msgid "Areas"
|
||||
msgstr ""
|
||||
msgstr "エリア"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_graph/static/src/xml/web_graph.xml:18
|
||||
msgid "Radar"
|
||||
msgstr ""
|
||||
msgstr "レーダー"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_graph/static/src/xml/web_graph.xml:20
|
||||
msgid "Legend"
|
||||
msgstr ""
|
||||
msgstr "凡例"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_graph/static/src/xml/web_graph.xml:24
|
||||
msgid "Hidden"
|
||||
msgstr ""
|
||||
msgstr "非表示"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_graph/static/src/xml/web_graph.xml:25
|
||||
msgid "Inside"
|
||||
msgstr ""
|
||||
msgstr "内側"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_graph/static/src/xml/web_graph.xml:26
|
||||
msgid "Top"
|
||||
msgstr ""
|
||||
msgstr "上"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_graph/static/src/xml/web_graph.xml:28
|
||||
msgid "Actions"
|
||||
msgstr ""
|
||||
msgstr "アクション"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_graph/static/src/xml/web_graph.xml:32
|
||||
msgid "Switch Axis"
|
||||
msgstr ""
|
||||
msgstr "Axisに切替"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_graph/static/src/xml/web_graph.xml:33
|
||||
msgid "Show Data"
|
||||
msgstr ""
|
||||
msgstr "データの表示"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_graph/static/src/xml/web_graph.xml:34
|
||||
msgid "Download as PNG"
|
||||
msgstr ""
|
||||
msgstr "PNGとしてダウンロード"
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
# Hungarian translation for openerp-web
|
||||
# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012
|
||||
# This file is distributed under the same license as the openerp-web package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2012.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: openerp-web\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2012-07-02 09:06+0200\n"
|
||||
"PO-Revision-Date: 2012-07-19 06:26+0000\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: Hungarian <hu@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: 2012-07-20 04:45+0000\n"
|
||||
"X-Generator: Launchpad (build 15644)\n"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_kanban/static/src/js/kanban.js:10
|
||||
msgid "Kanban"
|
||||
msgstr "Kanban"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_kanban/static/src/js/kanban.js:293
|
||||
msgid "Undefined"
|
||||
msgstr "Nem definiált"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_kanban/static/src/js/kanban.js:468
|
||||
msgid "Are you sure you want to delete this record ?"
|
||||
msgstr "Biztosan törölni szeretné ezt a bejegyzést?"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_kanban/static/src/js/kanban.js:839
|
||||
msgid "Create: "
|
||||
msgstr ""
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_kanban/static/src/xml/web_kanban.xml:41
|
||||
msgid "Show more... ("
|
||||
msgstr ""
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_kanban/static/src/xml/web_kanban.xml:41
|
||||
msgid "remaining)"
|
||||
msgstr ""
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_kanban/static/src/xml/web_kanban.xml:71
|
||||
msgid "Add"
|
||||
msgstr ""
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_kanban/static/src/xml/web_kanban.xml:71
|
||||
msgid "or"
|
||||
msgstr ""
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_kanban/static/src/xml/web_kanban.xml:72
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
|
||||
#~ msgid "Create"
|
||||
#~ msgstr "Létrehozás"
|
|
@ -8,59 +8,59 @@ msgstr ""
|
|||
"Project-Id-Version: openerp-web\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2012-07-02 09:06+0200\n"
|
||||
"PO-Revision-Date: 2012-03-06 06:35+0000\n"
|
||||
"Last-Translator: Masaki Yamaya <Unknown>\n"
|
||||
"PO-Revision-Date: 2012-07-19 03:34+0000\n"
|
||||
"Last-Translator: Akira Hiyama <Unknown>\n"
|
||||
"Language-Team: Japanese <ja@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: 2012-07-03 05:55+0000\n"
|
||||
"X-Generator: Launchpad (build 15531)\n"
|
||||
"X-Launchpad-Export-Date: 2012-07-20 04:45+0000\n"
|
||||
"X-Generator: Launchpad (build 15644)\n"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_kanban/static/src/js/kanban.js:10
|
||||
msgid "Kanban"
|
||||
msgstr "看板"
|
||||
msgstr "かんばん"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_kanban/static/src/js/kanban.js:372
|
||||
#: addons/web_kanban/static/src/js/kanban.js:293
|
||||
msgid "Undefined"
|
||||
msgstr "未定義"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_kanban/static/src/js/kanban.js:684
|
||||
#: addons/web_kanban/static/src/js/kanban.js:468
|
||||
msgid "Are you sure you want to delete this record ?"
|
||||
msgstr "このレコードを削除しますか?"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_kanban/static/src/js/kanban.js:839
|
||||
msgid "Create: "
|
||||
msgstr ""
|
||||
msgstr "作成: "
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_kanban/static/src/xml/web_kanban.xml:53
|
||||
#: addons/web_kanban/static/src/xml/web_kanban.xml:41
|
||||
msgid "Show more... ("
|
||||
msgstr "もっと表示する…("
|
||||
msgstr "さらに表示…("
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_kanban/static/src/xml/web_kanban.xml:53
|
||||
#: addons/web_kanban/static/src/xml/web_kanban.xml:41
|
||||
msgid "remaining)"
|
||||
msgstr "残り)"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_kanban/static/src/xml/web_kanban.xml:71
|
||||
msgid "Add"
|
||||
msgstr ""
|
||||
msgstr "追加"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_kanban/static/src/xml/web_kanban.xml:71
|
||||
msgid "or"
|
||||
msgstr ""
|
||||
msgstr "または"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_kanban/static/src/xml/web_kanban.xml:72
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
msgstr "キャンセル"
|
||||
|
||||
#~ msgid "</tr><tr>"
|
||||
#~ msgstr "</tr><tr>"
|
||||
|
|
|
@ -8,14 +8,14 @@ msgstr ""
|
|||
"Project-Id-Version: openerp-web\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2012-07-02 09:06+0200\n"
|
||||
"PO-Revision-Date: 2012-03-31 18:42+0000\n"
|
||||
"Last-Translator: Masaki Yamaya <Unknown>\n"
|
||||
"PO-Revision-Date: 2012-07-19 04:00+0000\n"
|
||||
"Last-Translator: Akira Hiyama <Unknown>\n"
|
||||
"Language-Team: Japanese <ja@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: 2012-07-03 05:55+0000\n"
|
||||
"X-Generator: Launchpad (build 15531)\n"
|
||||
"X-Launchpad-Export-Date: 2012-07-20 04:45+0000\n"
|
||||
"X-Generator: Launchpad (build 15644)\n"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_mobile/static/src/xml/web_mobile.xml:17
|
||||
|
@ -25,7 +25,7 @@ msgstr "OpenERP"
|
|||
#. openerp-web
|
||||
#: addons/web_mobile/static/src/xml/web_mobile.xml:22
|
||||
msgid "Database:"
|
||||
msgstr "データベース:"
|
||||
msgstr "データベース:"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_mobile/static/src/xml/web_mobile.xml:30
|
||||
|
@ -65,7 +65,7 @@ msgstr "お気に入り"
|
|||
#. openerp-web
|
||||
#: addons/web_mobile/static/src/xml/web_mobile.xml:58
|
||||
msgid "Preference"
|
||||
msgstr "優先"
|
||||
msgstr "プリファレンス"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_mobile/static/src/xml/web_mobile.xml:123
|
||||
|
@ -75,7 +75,7 @@ msgstr "ログアウト"
|
|||
#. openerp-web
|
||||
#: addons/web_mobile/static/src/xml/web_mobile.xml:132
|
||||
msgid "There are no records to show."
|
||||
msgstr "表示するレコードはありません"
|
||||
msgstr "表示するレコードはありません。"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_mobile/static/src/xml/web_mobile.xml:183
|
||||
|
|
|
@ -0,0 +1,118 @@
|
|||
# Hungarian translation for openerp-web
|
||||
# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012
|
||||
# This file is distributed under the same license as the openerp-web package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2012.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: openerp-web\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2012-07-02 09:06+0200\n"
|
||||
"PO-Revision-Date: 2012-07-19 06:28+0000\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: Hungarian <hu@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: 2012-07-20 04:45+0000\n"
|
||||
"X-Generator: Launchpad (build 15644)\n"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_process/static/src/js/process.js:261
|
||||
msgid "Cancel"
|
||||
msgstr "Mégsem"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_process/static/src/js/process.js:262
|
||||
msgid "Save"
|
||||
msgstr "Mentés"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_process/static/src/xml/web_process.xml:6
|
||||
msgid "Process View"
|
||||
msgstr ""
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_process/static/src/xml/web_process.xml:19
|
||||
msgid "Documentation"
|
||||
msgstr "Dokumentáció"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_process/static/src/xml/web_process.xml:19
|
||||
msgid "Read Documentation Online"
|
||||
msgstr "Olvassa a dokumentációt online"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_process/static/src/xml/web_process.xml:25
|
||||
msgid "Forum"
|
||||
msgstr "Fórum"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_process/static/src/xml/web_process.xml:25
|
||||
msgid "Community Discussion"
|
||||
msgstr "Közösségi vitafórum"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_process/static/src/xml/web_process.xml:31
|
||||
msgid "Books"
|
||||
msgstr "Könyvek"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_process/static/src/xml/web_process.xml:31
|
||||
msgid "Get the books"
|
||||
msgstr ""
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_process/static/src/xml/web_process.xml:37
|
||||
msgid "OpenERP Enterprise"
|
||||
msgstr ""
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_process/static/src/xml/web_process.xml:37
|
||||
msgid "Purchase OpenERP Enterprise"
|
||||
msgstr ""
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_process/static/src/xml/web_process.xml:52
|
||||
msgid "Process"
|
||||
msgstr ""
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_process/static/src/xml/web_process.xml:56
|
||||
msgid "Notes:"
|
||||
msgstr "Megjegyzések:"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_process/static/src/xml/web_process.xml:59
|
||||
msgid "Last modified by:"
|
||||
msgstr "Utoljára módosította:"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_process/static/src/xml/web_process.xml:59
|
||||
msgid "N/A"
|
||||
msgstr ""
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_process/static/src/xml/web_process.xml:62
|
||||
msgid "Subflows:"
|
||||
msgstr "Alfolyamatok:"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_process/static/src/xml/web_process.xml:75
|
||||
msgid "Related:"
|
||||
msgstr "Kapcsolódó:"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_process/static/src/xml/web_process.xml:88
|
||||
msgid "Select Process"
|
||||
msgstr "Folyamat kiválasztása"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_process/static/src/xml/web_process.xml:98
|
||||
msgid "Select"
|
||||
msgstr "Kiválaszt"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_process/static/src/xml/web_process.xml:109
|
||||
msgid "Edit Process"
|
||||
msgstr ""
|
|
@ -8,14 +8,14 @@ msgstr ""
|
|||
"Project-Id-Version: openerp-web\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2012-07-02 09:06+0200\n"
|
||||
"PO-Revision-Date: 2012-03-26 22:04+0000\n"
|
||||
"Last-Translator: Masaki Yamaya <Unknown>\n"
|
||||
"PO-Revision-Date: 2012-07-19 04:29+0000\n"
|
||||
"Last-Translator: Akira Hiyama <Unknown>\n"
|
||||
"Language-Team: Japanese <ja@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: 2012-07-03 05:55+0000\n"
|
||||
"X-Generator: Launchpad (build 15531)\n"
|
||||
"X-Launchpad-Export-Date: 2012-07-20 04:45+0000\n"
|
||||
"X-Generator: Launchpad (build 15644)\n"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_process/static/src/js/process.js:261
|
||||
|
@ -30,7 +30,7 @@ msgstr "保存"
|
|||
#. openerp-web
|
||||
#: addons/web_process/static/src/xml/web_process.xml:6
|
||||
msgid "Process View"
|
||||
msgstr "プロセス一覧"
|
||||
msgstr "プロセスビュー"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_process/static/src/xml/web_process.xml:19
|
||||
|
@ -40,7 +40,7 @@ msgstr "ドキュメンテーション"
|
|||
#. openerp-web
|
||||
#: addons/web_process/static/src/xml/web_process.xml:19
|
||||
msgid "Read Documentation Online"
|
||||
msgstr "オンラインのドキュメンテーションを読んでください。"
|
||||
msgstr "オンラインのドキュメントを読んで下さい"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_process/static/src/xml/web_process.xml:25
|
||||
|
@ -55,12 +55,12 @@ msgstr "コミュニティの議論"
|
|||
#. openerp-web
|
||||
#: addons/web_process/static/src/xml/web_process.xml:31
|
||||
msgid "Books"
|
||||
msgstr "帳簿"
|
||||
msgstr "本"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_process/static/src/xml/web_process.xml:31
|
||||
msgid "Get the books"
|
||||
msgstr "帳簿を取る"
|
||||
msgstr "本を手に入れる"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_process/static/src/xml/web_process.xml:37
|
||||
|
@ -85,7 +85,7 @@ msgstr "注記"
|
|||
#. openerp-web
|
||||
#: addons/web_process/static/src/xml/web_process.xml:59
|
||||
msgid "Last modified by:"
|
||||
msgstr "最後に変更:"
|
||||
msgstr "最終更新者:"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_process/static/src/xml/web_process.xml:59
|
||||
|
@ -105,14 +105,14 @@ msgstr "関係:"
|
|||
#. openerp-web
|
||||
#: addons/web_process/static/src/xml/web_process.xml:88
|
||||
msgid "Select Process"
|
||||
msgstr "プロセスを選んでください"
|
||||
msgstr "プロセスの選択"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_process/static/src/xml/web_process.xml:98
|
||||
msgid "Select"
|
||||
msgstr "選択する"
|
||||
msgstr "選択"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_process/static/src/xml/web_process.xml:109
|
||||
msgid "Edit Process"
|
||||
msgstr "プロセスを編集"
|
||||
msgstr "プロセスの編集"
|
||||
|
|
|
@ -8,14 +8,14 @@ msgstr ""
|
|||
"Project-Id-Version: openerp-web\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2012-07-02 09:06+0200\n"
|
||||
"PO-Revision-Date: 2012-03-29 11:39+0000\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"PO-Revision-Date: 2012-07-24 06:25+0000\n"
|
||||
"Last-Translator: Tor Syversen <sol-moe@online.no>\n"
|
||||
"Language-Team: Norwegian Bokmal <nb@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: 2012-07-03 05:55+0000\n"
|
||||
"X-Generator: Launchpad (build 15531)\n"
|
||||
"X-Launchpad-Export-Date: 2012-07-25 04:52+0000\n"
|
||||
"X-Generator: Launchpad (build 15679)\n"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_process/static/src/js/process.js:261
|
||||
|
@ -85,12 +85,12 @@ msgstr "Notater:"
|
|||
#. openerp-web
|
||||
#: addons/web_process/static/src/xml/web_process.xml:59
|
||||
msgid "Last modified by:"
|
||||
msgstr ""
|
||||
msgstr "Sist revidert av:"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_process/static/src/xml/web_process.xml:59
|
||||
msgid "N/A"
|
||||
msgstr ""
|
||||
msgstr "N/A"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_process/static/src/xml/web_process.xml:62
|
||||
|
@ -105,7 +105,7 @@ msgstr ""
|
|||
#. openerp-web
|
||||
#: addons/web_process/static/src/xml/web_process.xml:88
|
||||
msgid "Select Process"
|
||||
msgstr ""
|
||||
msgstr "Velg prosess"
|
||||
|
||||
#. openerp-web
|
||||
#: addons/web_process/static/src/xml/web_process.xml:98
|
||||
|
@ -115,4 +115,4 @@ msgstr "Velg"
|
|||
#. openerp-web
|
||||
#: addons/web_process/static/src/xml/web_process.xml:109
|
||||
msgid "Edit Process"
|
||||
msgstr ""
|
||||
msgstr "Rediger prosess"
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
Notes on the usage of the Form View as a sub-widget
|
||||
===================================================
|
||||
|
||||
Undocumented stuff
|
||||
------------------
|
||||
|
||||
* ``initial_mode`` *option* defines the starting mode of the form
|
||||
view, one of ``view`` and ``edit`` (?). Default value is ``view``
|
||||
(non-editable form).
|
||||
|
||||
* ``embedded_view`` *attribute* has to be set separately when
|
||||
providing a view directly, no option available for that usage.
|
||||
|
||||
* View arch **must** contain node with
|
||||
``@class="oe_form_container"``, otherwise everything will break
|
||||
without any info
|
||||
|
||||
* Root element of view arch not being ``form`` may or may not work
|
||||
correctly, no idea.
|
||||
|
||||
* Freeform views => ``@version="7.0"``
|
||||
|
||||
* Form is not entirely loaded (some widgets may not appear) unless
|
||||
``on_record_loaded`` is called (or ``do_show``, which itself calls
|
||||
``on_record_loaded``).
|
||||
|
||||
* "Empty" form => ``on_button_new`` (...), or manually call
|
||||
``default_get`` + ``on_record_loaded``
|
||||
|
||||
* Form fields default to width: 100%, padding, !important margin, can
|
||||
be reached via ``.oe_form_field``
|
||||
|
||||
* Form *will* render buttons and a pager, offers options to locate
|
||||
both outside of form itself (``$buttons`` and ``$pager``), providing
|
||||
empty jquery objects (``$()``) seems to stop displaying both but not
|
||||
sure if there are deleterious side-effects.
|
||||
|
||||
Other options:
|
||||
|
||||
* Pass in ``$(document.createDocumentFragment)`` to ensure it's a
|
||||
DOM-compatible tree completely outside of the actual DOM.
|
||||
|
||||
* ???
|
||||
|
||||
* readonly fields probably don't have a background, beware if need of
|
||||
overlay
|
||||
|
||||
* What is the difference between ``readonly`` and
|
||||
``effective_readonly``?
|
||||
|
||||
* No facilities for DOM events handling/delegations e.g. handling
|
||||
keyup/keydown/keypress from a form fields into the form's user.
|
||||
|
||||
* Also no way to reverse from a DOM node (e.g. DOMEvent#target) back to a
|
||||
form view field easily
|
|
@ -18,6 +18,9 @@ Contents:
|
|||
|
||||
search-view
|
||||
|
||||
list-view
|
||||
form-notes
|
||||
|
||||
Older stuff
|
||||
-----------
|
||||
|
||||
|
|
|
@ -0,0 +1,466 @@
|
|||
List View
|
||||
=========
|
||||
|
||||
Style Hooks
|
||||
-----------
|
||||
|
||||
The list view provides a few style hook classes for re-styling of list views in
|
||||
various situations:
|
||||
|
||||
``.oe_list``
|
||||
|
||||
The root element of the list view, styling rules should be rooted
|
||||
on that class.
|
||||
|
||||
``table.oe_list_content``
|
||||
|
||||
The root table for the listview, accessory components may be
|
||||
generated or added outside this section, this is the list view
|
||||
"proper".
|
||||
|
||||
``.oe_list_buttons``
|
||||
|
||||
The action buttons array for the list view, with its sub-elements
|
||||
|
||||
``.oe_list_add``
|
||||
|
||||
The default "Create"/"Add" button of the list view
|
||||
|
||||
``.oe_alternative``
|
||||
|
||||
The "alternative choice" for the list view, by default text
|
||||
along the lines of "or import" with a link.
|
||||
|
||||
``.oe_list_field_cell``
|
||||
|
||||
The cell (``td``) for a given field of the list view, cells which
|
||||
are *not* fields (e.g. name of a group, or number of items in a
|
||||
group) will not have this class. The field cell can be further
|
||||
specified:
|
||||
|
||||
``.oe_number``
|
||||
|
||||
Numeric cell types (integer and float)
|
||||
|
||||
``.oe_button``
|
||||
|
||||
Action button (``button`` tag in the view) inside the cell
|
||||
|
||||
``.oe_readonly``
|
||||
|
||||
Readonly field cell
|
||||
|
||||
``.oe_list_field_$type``
|
||||
|
||||
Additional class for the precise type of the cell, ``$type``
|
||||
is the field's @widget if there is one, otherwise it's the
|
||||
field's type.
|
||||
|
||||
``.oe_list_record_selector``
|
||||
|
||||
Selector cells
|
||||
|
||||
Editable list view
|
||||
++++++++++++++++++
|
||||
|
||||
The editable list view module adds a few supplementary style hook
|
||||
classes, for edition situations:
|
||||
|
||||
``.oe_editing``
|
||||
|
||||
Added to both ``.oe_list`` and ``.oe_list_button`` (as the
|
||||
buttons may be outside of the list view) when a row of the list is
|
||||
currently being edited.
|
||||
|
||||
``tr.oe_edition``
|
||||
|
||||
Class set on the row being edited itself. Note that the edition
|
||||
form is *not* contained within the row, this allows for styling or
|
||||
modifying the row while it's being edited separately. Mostly for
|
||||
fields which can not be edited (e.g. read-only fields).
|
||||
|
||||
|
||||
Editable list view
|
||||
------------------
|
||||
|
||||
List view edition is an extension to the base listview providing the
|
||||
capability of inline record edition by delegating to an embedded form
|
||||
view.
|
||||
|
||||
Editability status
|
||||
++++++++++++++++++
|
||||
|
||||
The editability status of a list view can be queried through the
|
||||
:js:func:`~openerp.web.ListView.editable` method, will return a falsy
|
||||
value if the listview is not currently editable.
|
||||
|
||||
The editability status is based on three flags:
|
||||
|
||||
``tree/@editable``
|
||||
|
||||
If present, can be either ``"top"`` or ``"bottom"``. Either will
|
||||
make the list view editable, with new records being respectively
|
||||
created at the top or at the bottom of the view.
|
||||
|
||||
``context.set_editable``
|
||||
|
||||
Boolean flag extracted from a search context (during the
|
||||
:js:func:`~openerp.web.ListView.do_search`` handler), ``true``
|
||||
will make the view editable (from the top), ``false`` or the
|
||||
absence of the flag is a noop.
|
||||
|
||||
``defaults.editable``
|
||||
|
||||
Like ``tree/@editable``, one of absent (``null``)), ``"top"`` or
|
||||
``"bottom"``, fallback for the list view if none of the previous
|
||||
two flags are set.
|
||||
|
||||
These three flags can only *make* a listview editable, they can *not*
|
||||
override a previously set flag. To do that, a listview user should
|
||||
instead cancel :ref:`the edit:before event <listview-edit-before>`.
|
||||
|
||||
The editable list view module adds a number of methods to the list
|
||||
view, on top of implementing the :js:class:`EditorDelegate` protocol:
|
||||
|
||||
Interaction Methods
|
||||
+++++++++++++++++++
|
||||
|
||||
.. js:function:: openerp.web.ListView.ensure_saved
|
||||
|
||||
Attempts to resolve the pending edition, if any, by saving the
|
||||
edited row's current state.
|
||||
|
||||
:returns: delegate resolving to all editions having been saved, or
|
||||
rejected if a pending edition could not be saved
|
||||
(e.g. validation failure)
|
||||
|
||||
.. js:function:: openerp.web.ListView.start_edition([record][, options])
|
||||
|
||||
Starts editing the provided record inline, through an overlay form
|
||||
view of editable fields in the record.
|
||||
|
||||
If no record is provided, creates a new one according to the
|
||||
editability configuration of the list view.
|
||||
|
||||
This method resolves any pending edition when invoked, before
|
||||
starting a new edition.
|
||||
|
||||
:param record: record to edit, or null to create a new record
|
||||
:type record: :js:class:`~openerp.web.list.Record`
|
||||
:param EditOptions options:
|
||||
:returns: delegate to the form used for the edition
|
||||
|
||||
.. js:function:: openerp.web.ListView.save_edition
|
||||
|
||||
Resolves the pending edition.
|
||||
|
||||
:returns: delegate to the save being completed, resolves to an
|
||||
object with two attributes ``created`` (flag indicating
|
||||
whether the saved record was just created or was
|
||||
updated) and ``record`` the reloaded record having been
|
||||
edited.
|
||||
|
||||
.. js:function:: openerp.web.ListView.cancel_edition
|
||||
|
||||
Cancels pending edition, cleans up the list view in case of
|
||||
creation (removes the empty record being created).
|
||||
|
||||
Utility Methods
|
||||
+++++++++++++++
|
||||
|
||||
.. js:function:: openerp.web.ListView.get_cells_for(row)
|
||||
|
||||
Extracts the cells from a listview row, and puts them in a
|
||||
{fieldname: cell} mapping for analysis and manipulation.
|
||||
|
||||
:param jQuery row:
|
||||
:rtype: Object
|
||||
|
||||
.. js:function:: openerp.web.ListView.with_event(event_name, event, action[, args][, trigger_params])
|
||||
|
||||
Executes ``action`` in the context of the view's editor,
|
||||
bracketing it with cancellable event signals.
|
||||
|
||||
:param String event_name: base name for the bracketing event, will
|
||||
be postfixed by ``:before`` and
|
||||
``:after`` before being called
|
||||
(respectively before and after
|
||||
``action`` is executed)
|
||||
:param Object event: object passed to the ``:before`` event
|
||||
handlers.
|
||||
:param Function action: function called with the view's editor as
|
||||
its ``this``. May return a deferred.
|
||||
:param Array args: arguments passed to ``action``
|
||||
:param Array trigger_params: arguments passed to the ``:after``
|
||||
event handler alongside the results
|
||||
of ``action``
|
||||
|
||||
Behavioral Customizations
|
||||
+++++++++++++++++++++++++
|
||||
|
||||
.. js:function:: openerp.web.ListView.handle_onwrite(record)
|
||||
|
||||
Implements the handling of the ``onwrite`` listview attribute:
|
||||
calls the RPC methods specified by ``@onwrite``, and if that
|
||||
method returns an array of ids loads or reloads the records
|
||||
corresponding to those ids.
|
||||
|
||||
:param record: record being written having triggered the
|
||||
``onwrite`` callback
|
||||
:type record: openerp.web.list.Record
|
||||
:returns: deferred to all reloadings being done
|
||||
|
||||
Events
|
||||
++++++
|
||||
|
||||
For simpler interactions by/with external users of the listview, the
|
||||
view provides a number of dedicated events to its lifecycle.
|
||||
|
||||
.. note:: if an event is defined as *cancellable*, it means its first
|
||||
parameter is an object on which the ``cancel`` attribute can
|
||||
be set. If the ``cancel`` attribute is set, the view will
|
||||
abort its current behavior as soon as possible, and rollback
|
||||
any state modification.
|
||||
|
||||
Generally speaking, an event should only be cancelled (by
|
||||
setting the ``cancel`` flag to ``true``), uncancelling an
|
||||
event is undefined as event handlers are executed on a
|
||||
first-come-first-serve basis and later handlers may
|
||||
re-cancel an uncancelled event.
|
||||
|
||||
.. _listview-edit-before:
|
||||
|
||||
``edit:before`` *cancellable*
|
||||
|
||||
Invoked before the list view starts editing a record.
|
||||
|
||||
Provided with an event object with a single property ``record``,
|
||||
holding the attributes of the record being edited (``record`` is
|
||||
empty *but not null* for a new record)
|
||||
|
||||
``edit:after``
|
||||
|
||||
Invoked after the list view has gone into an edition state,
|
||||
provided with the attributes of the record being edited (see
|
||||
``edit:before``) as first parameter and the form used for the
|
||||
edition as second parameter.
|
||||
|
||||
``save:before`` *cancellable*
|
||||
|
||||
Invoked right before saving a pending edition, provided with an
|
||||
event object holding the listview's editor (``editor``) and the
|
||||
edition form (``form``)
|
||||
|
||||
``save:after``
|
||||
|
||||
Invoked after a save has been completed
|
||||
|
||||
``cancel:before`` *cancellable*
|
||||
|
||||
Invoked before cancelling a pending edition, provided with the
|
||||
same information as ``save:before``.
|
||||
|
||||
``cancel:after``
|
||||
|
||||
Invoked after a pending edition has been cancelled.
|
||||
|
||||
DOM events
|
||||
++++++++++
|
||||
|
||||
The list view has grown hooks for the ``keyup`` event on its edition
|
||||
form (during edition): any such event bubbling out of the edition form
|
||||
will be forwarded to a method ``keyup_EVENTNAME``, where ``EVENTNAME``
|
||||
is the name of the key in ``$.ui.keyCode``.
|
||||
|
||||
The method will also get the event object (originally passed to the
|
||||
``keyup`` handler) as its sole parameter.
|
||||
|
||||
The base editable list view has handlers for the ``ENTER`` and
|
||||
``ESCAPE`` keys.
|
||||
|
||||
Editor
|
||||
------
|
||||
|
||||
The list-edition modules does not generally interact with the embedded
|
||||
formview, delegating instead to its
|
||||
:js:class:`~openerp.web.list.Editor`.
|
||||
|
||||
.. js:class:: openerp.web.list.Editor(parent[, options])
|
||||
|
||||
The editor object provides a more convenient interface to form
|
||||
views, and simplifies the usage of form views for semi-arbitrary
|
||||
edition of stuff.
|
||||
|
||||
However, the editor does *not* task itself with being internally
|
||||
consistent at this point: calling
|
||||
e.g. :js:func:`~openerp.web.list.Editor.edit` multiple times in a
|
||||
row without saving or cancelling each edit is undefined.
|
||||
|
||||
:param parent:
|
||||
:type parent: :js:class:`~openerp.web.Widget`
|
||||
:param EditorOptions options:
|
||||
|
||||
.. js:function:: openerp.web.list.Editor.is_editing([record_state])
|
||||
|
||||
Indicates whether the editor is currently in the process of
|
||||
providing edition for a record.
|
||||
|
||||
Can be filtered by the state of the record being edited
|
||||
(whether it's a record being *created* or a record being
|
||||
*altered*), in which case it asserts both that an edition is
|
||||
underway and that the record being edited respectively does
|
||||
not yet exist in the database or already exists there.
|
||||
|
||||
:param record_state: state of the record being edited.
|
||||
Either ``"new"`` or ``"edit"``.
|
||||
:type record_state: String
|
||||
:rtype: Boolean
|
||||
|
||||
.. js:function:: openerp.web.list.Editor.edit(record, configureField[, options])
|
||||
|
||||
Loads the provided record into the internal form view and
|
||||
displays the form view.
|
||||
|
||||
Will also attempt to focus the first visible field of the form
|
||||
view.
|
||||
|
||||
:param Object record: record to load into the form view
|
||||
(key:value mapping similar to the result
|
||||
of a ``read``)
|
||||
:param configureField: function called with each field of the
|
||||
form view right after the form is
|
||||
displayed, lets whoever called this
|
||||
method do some last-minute
|
||||
configuration of form fields.
|
||||
:type configureField: Function<String, openerp.web.form.Field>
|
||||
:param EditOptions options:
|
||||
:returns: jQuery delegate to the form object
|
||||
|
||||
.. js:function:: openerp.web.list.Editor.save
|
||||
|
||||
Attempts to save the internal form, then hide it
|
||||
|
||||
:returns: delegate to the record under edition (with ``id``
|
||||
added for a creation). The record is not updated
|
||||
from when it was passed in, aside from the ``id``
|
||||
attribute.
|
||||
|
||||
.. js:function:: openerp.web.list.Editor.cancel
|
||||
|
||||
Attemps to cancel the edition of the internal form, then hide
|
||||
the form
|
||||
|
||||
:returns: delegate to the record under edition
|
||||
|
||||
.. js:class:: EditorOptions
|
||||
|
||||
.. js:attribute:: EditorOptions.formView
|
||||
|
||||
Form view (sub)-class to instantiate and delegate edition to.
|
||||
|
||||
By default, :js:class:`~openerp.web.FormView`
|
||||
|
||||
.. js:attribute:: EditorOptions.delegate
|
||||
|
||||
Object used to get various bits of information about how to
|
||||
display stuff.
|
||||
|
||||
By default, uses the editor's parent widget. See
|
||||
:js:class:`EditorDelegate` for the methods and attributes to
|
||||
provide.
|
||||
|
||||
.. js:class:: EditorDelegate
|
||||
|
||||
Informal protocol defining the methods and attributes expected of
|
||||
the :js:class:`~openerp.web.list.Editor`'s delegate.
|
||||
|
||||
.. js:attribute:: EditorDelegate.dataset
|
||||
|
||||
The dataset passed to the form view to synchronize the form
|
||||
view and the outer widget.
|
||||
|
||||
.. js:function:: EditorDelegate.edition_view(editor)
|
||||
|
||||
Called by the :js:class:`~openerp.web.list.Editor` object to
|
||||
get a form view (JSON) to pass along to the form view it
|
||||
created.
|
||||
|
||||
The result should be a valid form view, see :doc:`Form Notes
|
||||
<form-notes>` for various peculiarities of the form view
|
||||
format.
|
||||
|
||||
:param editor: editor object asking for the view
|
||||
:type editor: :js:class:`~openerp.web.list.Editor`
|
||||
:returns: form view
|
||||
:rtype: Object
|
||||
|
||||
.. js:function:: EditorDelegate.prepends_on_create
|
||||
|
||||
By default, the :js:class:`~openerp.web.list.Editor` will
|
||||
append the ids of newly created records to the
|
||||
:js:attr:`EditorDelegate.dataset`. If this method returns
|
||||
``true``, it will prepend these ids instead.
|
||||
|
||||
:returns: whether new records should be prepended to the
|
||||
dataset (instead of appended)
|
||||
:rtype: Boolean
|
||||
|
||||
|
||||
.. js:class:: EditOptions
|
||||
|
||||
Options object optionally passed into a method starting an edition
|
||||
to configure its setup and behavior
|
||||
|
||||
.. js:attribute:: focus_field
|
||||
|
||||
Name of the field to set focus on after setting up the edition
|
||||
of the record.
|
||||
|
||||
If this option is not provided, or the requested field can not
|
||||
be focused (invisible, readonly or not in the view), the first
|
||||
visible non-readonly field is focused.
|
||||
|
||||
Changes from 6.1
|
||||
----------------
|
||||
|
||||
* The editable listview behavior has been rewritten pretty much from
|
||||
scratch, any code touching on editability will have to be modified
|
||||
|
||||
* The overloading of :js:class:`~openerp.web.ListView.Groups` and
|
||||
:js:class:`~openerp.web.ListView.List` for editability has been
|
||||
drastically simplified, and most of the behavior has been moved to
|
||||
the list view itself. Only
|
||||
:js:func:`~openerp.web.ListView.List.row_clicked` is still
|
||||
overridden.
|
||||
|
||||
* A new method ``get_row_for(record) -> jQuery(tr) | null`` has been
|
||||
added to both ListView.List and ListView.Group, it can be called
|
||||
from the list view to get the table row matching a record (if such
|
||||
a row exists).
|
||||
|
||||
* :js:func:`~openerp.web.ListView.do_button_action`'s core behavior
|
||||
has been split away to
|
||||
:js:func:`~openerp.web.ListView.handle_button`. This allows bypassing
|
||||
overrides of :js:func:`~openerp.web.ListView.do_button_action` in a
|
||||
parent class.
|
||||
|
||||
Ideally, :js:func:`~openerp.web.ListView.handle_button` should not be
|
||||
overridden.
|
||||
|
||||
* Modifiers handling has been improved (all modifiers information
|
||||
should now be available through :js:func:`~Column.modifiers_for`,
|
||||
not just ``invisible``)
|
||||
|
||||
* Changed some handling of the list view's record: a record may now
|
||||
have no id, and the listview will handle that correctly (for new
|
||||
records being created) as well as correctly handle the ``id`` being
|
||||
set.
|
||||
|
||||
* Extended the internal collections structure of the list view with
|
||||
`#find`_, `#succ`_ and `#pred`_.
|
||||
|
||||
.. _#find: http://underscorejs.org/#find
|
||||
|
||||
.. _#succ: http://hackage.haskell.org/packages/archive/base/latest/doc/html/Prelude.html#v:succ
|
||||
|
||||
.. _#pred: http://hackage.haskell.org/packages/archive/base/latest/doc/html/Prelude.html#v:pred
|
Loading…
Reference in New Issue