[MERGE]merge with trunk

bzr revid: sgo@tinyerp.com-20120727050154-148msw0jzppgc66w
This commit is contained in:
Sanjay Gohel (Open ERP)
2012-07-27 10:31:54 +05:30
26 changed files with 2859 additions and 508 deletions
+1
View File
@@ -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",
+2 -2
View File
@@ -425,8 +425,8 @@ class DisableCacheMiddleware(object):
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'))]
debug = parsed.query.count('debug') >= 1
filtered_headers = [(k,v) for k,v in headers if not (k=='Last-Modified' or (debug and (k=='Cache-Control' or k=='Expires')))]
if debug:
filtered_headers.append(('Cache-Control', 'no-cache'))
start_response(status, filtered_headers)
+6 -3
View File
@@ -194,9 +194,12 @@ class WebClient(openerpweb.Controller):
if mods is not None:
path += '?mods=' + mods
return [path]
# old code to force cache reloading
#return ['%s?debug=%s' % (wp, os.path.getmtime(fp)) for fp, wp in self.manifest_glob(req, mods, extension)]
return [el[1] for el in self.manifest_glob(req, mods, extension)]
no_sugar = req.httprequest.environ["QUERY_STRING"].count("no_sugar") >= 1
no_sugar = no_sugar or req.httprequest.environ.get('HTTP_REFERER', '').count("no_sugar") >= 1
if not no_sugar:
return ['%s?debug=%s' % (wp, os.path.getmtime(fp)) for fp, wp in self.manifest_glob(req, mods, extension)]
else:
return [el[1] for el in self.manifest_glob(req, mods, extension)]
@openerpweb.jsonrequest
def csslist(self, req, mods=None):
File diff suppressed because it is too large Load Diff
+306
View File
@@ -0,0 +1,306 @@
//fgnass.github.com/spin.js#v1.2.5
(function(window, document, undefined) {
/**
* Copyright (c) 2011 Felix Gnass [fgnass at neteye dot de]
* Licensed under the MIT license
*/
var prefixes = ['webkit', 'Moz', 'ms', 'O']; /* Vendor prefixes */
var animations = {}; /* Animation rules keyed by their name */
var useCssAnimations;
/**
* Utility function to create elements. If no tag name is given,
* a DIV is created. Optionally properties can be passed.
*/
function createEl(tag, prop) {
var el = document.createElement(tag || 'div');
var n;
for(n in prop) {
el[n] = prop[n];
}
return el;
}
/**
* Appends children and returns the parent.
*/
function ins(parent /* child1, child2, ...*/) {
for (var i=1, n=arguments.length; i<n; i++) {
parent.appendChild(arguments[i]);
}
return parent;
}
/**
* Insert a new stylesheet to hold the @keyframe or VML rules.
*/
var sheet = function() {
var el = createEl('style');
ins(document.getElementsByTagName('head')[0], el);
return el.sheet || el.styleSheet;
}();
/**
* Creates an opacity keyframe animation rule and returns its name.
* Since most mobile Webkits have timing issues with animation-delay,
* we create separate rules for each line/segment.
*/
function addAnimation(alpha, trail, i, lines) {
var name = ['opacity', trail, ~~(alpha*100), i, lines].join('-');
var start = 0.01 + i/lines*100;
var z = Math.max(1-(1-alpha)/trail*(100-start) , alpha);
var prefix = useCssAnimations.substring(0, useCssAnimations.indexOf('Animation')).toLowerCase();
var pre = prefix && '-'+prefix+'-' || '';
if (!animations[name]) {
sheet.insertRule(
'@' + pre + 'keyframes ' + name + '{' +
'0%{opacity:'+z+'}' +
start + '%{opacity:'+ alpha + '}' +
(start+0.01) + '%{opacity:1}' +
(start+trail)%100 + '%{opacity:'+ alpha + '}' +
'100%{opacity:'+ z + '}' +
'}', 0);
animations[name] = 1;
}
return name;
}
/**
* Tries various vendor prefixes and returns the first supported property.
**/
function vendor(el, prop) {
var s = el.style;
var pp;
var i;
if(s[prop] !== undefined) return prop;
prop = prop.charAt(0).toUpperCase() + prop.slice(1);
for(i=0; i<prefixes.length; i++) {
pp = prefixes[i]+prop;
if(s[pp] !== undefined) return pp;
}
}
/**
* Sets multiple style properties at once.
*/
function css(el, prop) {
for (var n in prop) {
el.style[vendor(el, n)||n] = prop[n];
}
return el;
}
/**
* Fills in default values.
*/
function merge(obj) {
for (var i=1; i < arguments.length; i++) {
var def = arguments[i];
for (var n in def) {
if (obj[n] === undefined) obj[n] = def[n];
}
}
return obj;
}
/**
* Returns the absolute page-offset of the given element.
*/
function pos(el) {
var o = {x:el.offsetLeft, y:el.offsetTop};
while((el = el.offsetParent)) {
o.x+=el.offsetLeft;
o.y+=el.offsetTop;
}
return o;
}
var defaults = {
lines: 12, // The number of lines to draw
length: 7, // The length of each line
width: 5, // The line thickness
radius: 10, // The radius of the inner circle
rotate: 0, // rotation offset
color: '#000', // #rgb or #rrggbb
speed: 1, // Rounds per second
trail: 100, // Afterglow percentage
opacity: 1/4, // Opacity of the lines
fps: 20, // Frames per second when using setTimeout()
zIndex: 2e9, // Use a high z-index by default
className: 'spinner', // CSS class to assign to the element
top: 'auto', // center vertically
left: 'auto' // center horizontally
};
/** The constructor */
var Spinner = function Spinner(o) {
if (!this.spin) return new Spinner(o);
this.opts = merge(o || {}, Spinner.defaults, defaults);
};
Spinner.defaults = {};
merge(Spinner.prototype, {
spin: function(target) {
this.stop();
var self = this;
var o = self.opts;
var el = self.el = css(createEl(0, {className: o.className}), {position: 'relative', zIndex: o.zIndex});
var mid = o.radius+o.length+o.width;
var ep; // element position
var tp; // target position
if (target) {
target.insertBefore(el, target.firstChild||null);
tp = pos(target);
ep = pos(el);
css(el, {
left: (o.left == 'auto' ? tp.x-ep.x + (target.offsetWidth >> 1) : o.left+mid) + 'px',
top: (o.top == 'auto' ? tp.y-ep.y + (target.offsetHeight >> 1) : o.top+mid) + 'px'
});
}
el.setAttribute('aria-role', 'progressbar');
self.lines(el, self.opts);
if (!useCssAnimations) {
// No CSS animation support, use setTimeout() instead
var i = 0;
var fps = o.fps;
var f = fps/o.speed;
var ostep = (1-o.opacity)/(f*o.trail / 100);
var astep = f/o.lines;
!function anim() {
i++;
for (var s=o.lines; s; s--) {
var alpha = Math.max(1-(i+s*astep)%f * ostep, o.opacity);
self.opacity(el, o.lines-s, alpha, o);
}
self.timeout = self.el && setTimeout(anim, ~~(1000/fps));
}();
}
return self;
},
stop: function() {
var el = this.el;
if (el) {
clearTimeout(this.timeout);
if (el.parentNode) el.parentNode.removeChild(el);
this.el = undefined;
}
return this;
},
lines: function(el, o) {
var i = 0;
var seg;
function fill(color, shadow) {
return css(createEl(), {
position: 'absolute',
width: (o.length+o.width) + 'px',
height: o.width + 'px',
background: color,
boxShadow: shadow,
transformOrigin: 'left',
transform: 'rotate(' + ~~(360/o.lines*i+o.rotate) + 'deg) translate(' + o.radius+'px' +',0)',
borderRadius: (o.width>>1) + 'px'
});
}
for (; i < o.lines; i++) {
seg = css(createEl(), {
position: 'absolute',
top: 1+~(o.width/2) + 'px',
transform: o.hwaccel ? 'translate3d(0,0,0)' : '',
opacity: o.opacity,
animation: useCssAnimations && addAnimation(o.opacity, o.trail, i, o.lines) + ' ' + 1/o.speed + 's linear infinite'
});
if (o.shadow) ins(seg, css(fill('#000', '0 0 4px ' + '#000'), {top: 2+'px'}));
ins(el, ins(seg, fill(o.color, '0 0 1px rgba(0,0,0,.1)')));
}
return el;
},
opacity: function(el, i, val) {
if (i < el.childNodes.length) el.childNodes[i].style.opacity = val;
}
});
/////////////////////////////////////////////////////////////////////////
// VML rendering for IE
/////////////////////////////////////////////////////////////////////////
/**
* Check and init VML support
*/
!function() {
function vml(tag, attr) {
return createEl('<' + tag + ' xmlns="urn:schemas-microsoft.com:vml" class="spin-vml">', attr);
}
var s = css(createEl('group'), {behavior: 'url(#default#VML)'});
if (!vendor(s, 'transform') && s.adj) {
// VML support detected. Insert CSS rule ...
sheet.addRule('.spin-vml', 'behavior:url(#default#VML)');
Spinner.prototype.lines = function(el, o) {
var r = o.length+o.width;
var s = 2*r;
function grp() {
return css(vml('group', {coordsize: s +' '+s, coordorigin: -r +' '+-r}), {width: s, height: s});
}
var margin = -(o.width+o.length)*2+'px';
var g = css(grp(), {position: 'absolute', top: margin, left: margin});
var i;
function seg(i, dx, filter) {
ins(g,
ins(css(grp(), {rotation: 360 / o.lines * i + 'deg', left: ~~dx}),
ins(css(vml('roundrect', {arcsize: 1}), {
width: r,
height: o.width,
left: o.radius,
top: -o.width>>1,
filter: filter
}),
vml('fill', {color: o.color, opacity: o.opacity}),
vml('stroke', {opacity: 0}) // transparent stroke to fix color bleeding upon opacity change
)
)
);
}
if (o.shadow) {
for (i = 1; i <= o.lines; i++) {
seg(i, -2, 'progid:DXImageTransform.Microsoft.Blur(pixelradius=2,makeshadow=1,shadowopacity=.3)');
}
}
for (i = 1; i <= o.lines; i++) seg(i);
return ins(el, g);
};
Spinner.prototype.opacity = function(el, i, val, o) {
var c = el.firstChild;
o = o.shadow && o.lines || 0;
if (c && i+o < c.childNodes.length) {
c = c.childNodes[i+o]; c = c && c.firstChild; c = c && c.firstChild;
if (c) c.opacity = val;
}
};
}
else {
useCssAnimations = vendor(s, 'animation');
}
}();
window.Spinner = Spinner;
})(window, document);
+181 -97
View File
@@ -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");
@@ -20,6 +20,50 @@
font-style: normal;
}
@-moz-keyframes bounce {
0% {
-moz-transform: scale(0);
opacity: 0;
}
50% {
-moz-transform: scale(1.3);
opacity: 0.4;
}
75% {
-moz-transform: scale(0.9);
opacity: 0.7;
}
100% {
-moz-transform: scale(1);
opacity: 1;
}
}
@-webkit-keyframes bounce {
0% {
-webkit-transform: scale(0);
opacity: 0;
}
50% {
-webkit-transform: scale(1.3);
opacity: 0.4;
}
75% {
-webkit-transform: scale(0.9);
opacity: 0.7;
}
100% {
-webkit-transform: scale(1);
opacity: 1;
}
}
.openerp.openerp_webclient_container {
height: 100%;
position: relative;
@@ -186,6 +230,11 @@
.openerp .ui-menu .ui-menu-item a.ui-state-active {
background: #f0f0fa;
}
.openerp div.ui-widget-overlay {
background: black;
filter: alpha(opacity=30);
opacity: 0.3;
}
.openerp.ui-dialog {
display: none;
padding: 6px;
@@ -267,6 +316,45 @@
color: black;
text-decoration: none;
}
.openerp.ui-dialog .oe_about {
background-color: white;
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAGCAYAAADgzO9IAAAAKUlEQVQIHWO8e/fufwYsgAUkJigoiCIF5DMyoYggcUiXgNnBiGQKmAkARpcEQeriln4AAAAASUVORK5CYII=);
-moz-border-radius: 0 0 2px 2px;
-webkit-border-radius: 0 0 2px 2px;
border-radius: 0 0 2px 2px;
}
.openerp.ui-dialog .oe_about a {
color: #8a89ba;
}
.openerp.ui-dialog .oe_about a:hover {
text-decoration: underline;
}
.openerp.ui-dialog .oe_about .oe_logo {
margin-left: -6px;
}
.openerp.ui-dialog .oe_about .oe_bottom {
position: absolute;
top: 50%;
left: 0;
right: 0;
bottom: 0;
text-shadow: 0 1px 1px #999999;
background-color: #b41616;
background-image: -webkit-gradient(linear, left top, left bottom, from(#b41616), to(#600606));
background-image: -webkit-linear-gradient(top, #b41616, #600606);
background-image: -moz-linear-gradient(top, #b41616, #600606);
background-image: -ms-linear-gradient(top, #b41616, #600606);
background-image: -o-linear-gradient(top, #b41616, #600606);
background-image: linear-gradient(to bottom, #b41616, #600606);
color: #eeeeee;
padding: 0 16px;
-moz-border-radius: 0 0 2px 2px;
-webkit-border-radius: 0 0 2px 2px;
border-radius: 0 0 2px 2px;
}
.openerp.ui-dialog .oe_about .oe_bottom a {
color: #eeeeee;
}
.openerp.ui-dialog.oe_act_window .ui-dialog-content {
padding: 0px;
}
@@ -458,6 +546,10 @@
.openerp .oe_webclient .oe_star_on {
color: gold;
}
.openerp .oe_bounce {
-moz-animation: bounce 0.4s linear;
-webkit-animation: bounce 0.4s linear;
}
.openerp .oe_tag {
border-radius: 2px;
-webkit-box-sizing: border-box;
@@ -584,7 +676,7 @@
z-index: 1;
border: 1px solid #afafb6;
background: white;
padding: 6px 0;
padding: 4px 0;
min-width: 140px;
text-align: left;
-moz-border-radius: 3px;
@@ -599,6 +691,7 @@
float: none;
display: block;
position: relative;
padding: 2px 8px;
}
.openerp .oe_dropdown_menu > li:hover {
background-color: #f0f0fa;
@@ -615,7 +708,6 @@
.openerp .oe_dropdown_menu > li > a {
white-space: nowrap;
display: block;
padding: 4px 15px;
color: #4c4c4c;
text-decoration: none;
}
@@ -711,7 +803,7 @@
z-index: 1050;
}
.openerp .oe_login {
background: url("/web/static/src/img/pattern.png") repeat;
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAGCAYAAADgzO9IAAAAKUlEQVQIHWO8e/fufwYsgAUkJigoiCIF5DMyoYggcUiXgNnBiGQKmAkARpcEQeriln4AAAAASUVORK5CYII=);
text-align: center;
font-size: 14px;
height: 100%;
@@ -945,11 +1037,12 @@
}
.openerp .oe_topbar .oe_dropdown_menu li {
float: none;
padding: 3px 12px;
}
.openerp .oe_topbar .oe_dropdown_menu li a {
color: #eeeeee;
}
.openerp .oe_topbar .oe_dropdown_menu li a:hover {
.openerp .oe_topbar .oe_dropdown_menu li:hover {
background-color: #292929;
background-image: -webkit-gradient(linear, left top, left bottom, from(#292929), to(#191919));
background-image: -webkit-linear-gradient(top, #292929, #191919);
@@ -1229,6 +1322,9 @@
.openerp .oe_view_manager .oe_view_manager_pager {
line-height: 26px;
}
.openerp .oe_view_manager .oe_view_manager_pager .oe_list_pager_single_page .oe_pager_group {
display: none;
}
.openerp .oe_view_manager .oe_pager_value {
float: left;
margin-right: 8px;
@@ -1408,20 +1504,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;
@@ -1437,7 +1544,7 @@
outline: none;
}
.openerp .oe_searchview .oe_searchview_facets .oe_searchview_input {
padding: 0 3px;
padding: 0 0 0 6px;
}
.openerp .oe_searchview .oe_searchview_facets .oe_searchview_facet {
position: relative;
@@ -1600,14 +1707,14 @@
.openerp .oe_searchview .oe_searchview_drawer .oe_searchview_section li:hover {
background-color: #f0f0fa;
}
.openerp .oe_searchview .oe_searchview_drawer .oe_searchview_section form {
.openerp .oe_searchview .oe_searchview_drawer form {
margin-left: 12px;
}
.openerp .oe_searchview .oe_searchview_drawer .oe_searchview_section form p {
.openerp .oe_searchview .oe_searchview_drawer form p {
margin: 4px 0;
line-height: 18px;
}
.openerp .oe_searchview .oe_searchview_drawer .oe_searchview_section form button {
.openerp .oe_searchview .oe_searchview_drawer form button {
margin: 0 0 8px 0;
}
.openerp .oe_searchview .oe_searchview_drawer .oe_searchview_custom {
@@ -2180,7 +2287,7 @@
height: auto;
line-height: 16px;
}
.openerp .oe_form_field_one2many .oe_list_buttons.oe_editing .oe_list_save {
.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 {
@@ -2266,9 +2373,6 @@
padding: 3px 6px;
white-space: pre-line;
}
.openerp .oe_list_content > tbody > tr > td.oe_list_field_cell progress {
width: 100%;
}
.openerp .oe_list_content > tbody > tr > td > button, .openerp .oe_list_content > tbody > tr > th > button {
border: none;
background: transparent;
@@ -2315,6 +2419,58 @@
.openerp .oe_list_content .numeric input {
text-align: right;
}
.openerp .tree_header {
background-color: #f0f0f0;
border-bottom: 1px solid #cacaca;
color: #4c4c4c;
padding: 5px;
height: 25px;
}
.openerp .tree_header button {
float: right;
height: 27px;
margin-right: 5px;
}
.openerp .oe-treeview-table {
width: 100%;
background-color: white;
border-spacing: 0;
}
.openerp .oe-treeview-table th {
padding: 10px;
color: #4c4c4c;
font-weight: bold;
background-color: #f0f0f0;
border-bottom: 2px solid #cacaca;
}
.openerp .oe-treeview-table .treeview-tr, .openerp .oe-treeview-table .treeview-td {
cursor: pointer;
border-right: 1px dotted #afafb6;
vertical-align: top;
text-align: left;
border-bottom: 1px solid #cfcccc;
}
.openerp .oe-treeview-table tr:hover {
background-color: #e0e0f8;
}
.openerp .oe-treeview-table .oe-number {
text-align: right !important;
}
.openerp .oe-treeview-table span {
font-size: 90%;
font-weight: normal;
white-space: nowrap;
display: block;
}
.openerp .oe-treeview-table .treeview-tr.oe-treeview-first {
background: transparent url(/web/static/src/img/expand.gif) 0 50% no-repeat;
}
.openerp .oe-treeview-table .oe_open .treeview-tr.oe-treeview-first {
background-image: url(/web/static/src/img/collapse.gif);
}
.openerp .oe-treeview-table .treeview-tr.oe-treeview-first span, .openerp .oe-treeview-table .treeview-td.oe-treeview-first span {
margin-left: 16px;
}
.openerp .oe_trad_field.touched {
border: 1px solid green !important;
}
@@ -2380,59 +2536,6 @@
color: #333333;
}
.openerp .tree_header {
background-color: #f0f0f0;
border-bottom: 1px solid #cacaca;
color: #4c4c4c;
padding: 5px;
height: 25px;
}
.openerp .tree_header button {
float: right;
height: 27px;
margin-right: 5px;
}
.openerp .oe-treeview-table {
width: 100%;
background-color: white;
border-spacing: 0;
}
.openerp .oe-treeview-table th {
padding: 10px;
color: #4c4c4c;
font-weight: bold;
background-color: #f0f0f0;
border-bottom: 2px solid #cacaca;
}
.openerp .oe-treeview-table .treeview-tr, .openerp .oe-treeview-table .treeview-td {
cursor: pointer;
border-right: 1px dotted #afafb6;
vertical-align: top;
text-align: left;
border-bottom: 1px solid #cfcccc;
}
.openerp .oe-treeview-table tr:hover {
background-color: #e0e0f8;
}
.openerp .oe-treeview-table .oe-number {
text-align: right !important;
}
.openerp .oe-treeview-table span {
font-size: 90%;
font-weight: normal;
white-space: nowrap;
display: block;
}
.openerp .oe-treeview-table .treeview-tr.oe-treeview-first {
background: transparent url(/web/static/src/img/expand.gif) 0 50% no-repeat;
}
.openerp .oe-treeview-table .oe_open .treeview-tr.oe-treeview-first {
background-image: url(/web/static/src/img/collapse.gif);
}
.openerp .oe-treeview-table .treeview-tr.oe-treeview-first span, .openerp .oe-treeview-table .treeview-td.oe-treeview-first span {
margin-left: 16px;
}
.kitten-mode-activated {
background-image: url(http://placekitten.com/g/1365/769);
background-size: cover;
@@ -2441,22 +2544,3 @@
.kitten-mode-activated > * {
opacity: 0.7;
}
.kitten-mode-activated .oe_footer a {
background-image: url(http://www.risacher.com/la-rache/zfiles/la-rache.png);
font-size: 1px;
letter-spacing: -1px;
color: transparent;
display: inline-block;
height: 15px;
width: 80px;
vertical-align: top;
}
.kitten-mode-activated .oe_footer a span {
display: none;
}
div.ui-widget-overlay {
background: black;
filter: alpha(opacity=30);
opacity: 0.3;
}
+131 -72
View File
@@ -97,6 +97,35 @@ $sheet-max-width: 860px
color: $color
// }}}
// CSS animation bounces {{{
@-moz-keyframes bounce
0%
-moz-transform: scale(0)
opacity: 0
50%
-moz-transform: scale(1.3)
opacity: 0.4
75%
-moz-transform: scale(0.9)
opacity: 0.7
100%
-moz-transform: scale(1)
opacity: 1
@-webkit-keyframes bounce
0%
-webkit-transform: scale(0)
opacity: 0
50%
-webkit-transform: scale(1.3)
opacity: 0.4
75%
-webkit-transform: scale(0.9)
opacity: 0.7
100%
-webkit-transform: scale(1)
opacity: 1
// }}}
.openerp.openerp_webclient_container
height: 100%
@@ -200,7 +229,9 @@ $sheet-max-width: 860px
width: auto
a.ui-state-active
background: #f0f0fa
div.ui-widget-overlay
background: black
@include opacity(0.3)
// Modal box
&.ui-dialog
display: none
@@ -255,6 +286,29 @@ $sheet-max-width: 860px
&:hover
color: black
text-decoration: none
.oe_about
background-color: white
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAGCAYAAADgzO9IAAAAKUlEQVQIHWO8e/fufwYsgAUkJigoiCIF5DMyoYggcUiXgNnBiGQKmAkARpcEQeriln4AAAAASUVORK5CYII=)
@include radius(0 0 2px 2px)
a
color: #8A89BA
&:hover
text-decoration: underline
.oe_logo
margin-left: -6px
.oe_bottom
position: absolute
top: 50%
left: 0
right: 0
bottom: 0
text-shadow: 0 1px 1px #999999
@include vertical-gradient(#b41616, #600606)
color: #eee
padding: 0 16px
@include radius(0 0 2px 2px)
a
color: #eee
&.ui-dialog.oe_act_window
.ui-dialog-content
@@ -367,6 +421,9 @@ $sheet-max-width: 860px
text-decoration: none
.oe_star_on
color: gold
.oe_bounce
-moz-animation: bounce .40s linear
-webkit-animation: bounce .40s linear
// }}}
// Tags (for many2many tags, among others) {{{
.oe_tag
@@ -469,7 +526,7 @@ $sheet-max-width: 860px
z-index: 1
border: 1px solid #afafb6
background: white
padding: 6px 0
padding: 4px 0
min-width: 140px
text-align: left
@include radius(3px)
@@ -482,10 +539,10 @@ $sheet-max-width: 860px
float: none
display: block
position: relative
padding: 2px 8px
> a
white-space: nowrap
display: block
padding: 4px 15px
color: #4c4c4c
text-decoration: none
&:hover
@@ -566,7 +623,7 @@ $sheet-max-width: 860px
// }}}
// Login {{{
.oe_login
background: url("/web/static/src/img/pattern.png") repeat
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAGCAYAAADgzO9IAAAAKUlEQVQIHWO8e/fufwYsgAUkJigoiCIF5DMyoYggcUiXgNnBiGQKmAkARpcEQeriln4AAAAASUVORK5CYII=)
text-align: center
font-size: 14px
height: 100%
@@ -734,11 +791,12 @@ $sheet-max-width: 860px
@include background-clip()
li
float: none
padding: 3px 12px
a
color: #eee
&:hover
@include vertical-gradient(#292929, #191919)
@include box-shadow(none)
&:hover
@include vertical-gradient(#292929, #191919)
@include box-shadow(none)
// }}}
// Webclient.leftbar {{{
@@ -958,6 +1016,8 @@ $sheet-max-width: 860px
// ViewManager.pager {{{
.oe_view_manager_pager
line-height: 26px
.oe_list_pager_single_page .oe_pager_group
display: none
.oe_pager_value
float: left
margin-right: 8px
@@ -1101,19 +1161,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
@@ -1125,7 +1186,7 @@ $sheet-max-width: 860px
&:focus
outline: none
.oe_searchview_input
padding: 0 3px
padding: 0 0 0 6px
.oe_searchview_facet
position: relative
cursor: pointer
@@ -1247,13 +1308,13 @@ $sheet-max-width: 860px
// after oe_selected so background color is not overridden
&:hover
background-color: $hover-background
form
margin-left: 12px
p
margin: 4px 0
line-height: 18px
button
margin: 0 0 8px 0
form
margin-left: 12px
p
margin: 4px 0
line-height: 18px
button
margin: 0 0 8px 0
.oe_searchview_custom
padding: 0 8px 8px 8px
form
@@ -1821,6 +1882,49 @@ $sheet-max-width: 860px
input
text-align: right
// }}}
// Tree view {{{
.tree_header
background-color: #f0f0f0
border-bottom: 1px solid #cacaca
color: #4c4c4c
padding: 5px
height: 25px
button
float: right
height: 27px
margin-right: 5px
.oe-treeview-table
width: 100%
background-color: white
border-spacing: 0
th
padding: 10px
color: #4c4c4c
font-weight: bold
background-color: #f0f0f0
border-bottom: 2px solid #cacaca
.treeview-tr, .treeview-td
cursor: pointer
border-right: 1px dotted #afafb6
vertical-align: top
text-align: left
border-bottom: 1px solid #cfcccc
tr:hover
background-color: #e0e0f8
.oe-number
text-align: right !important
span
font-size: 90%
font-weight: normal
white-space: nowrap
display: block
.treeview-tr.oe-treeview-first
background: transparent url(/web/static/src/img/expand.gif) 0 50% no-repeat
.oe_open .treeview-tr.oe-treeview-first
background-image: url(/web/static/src/img/collapse.gif)
.treeview-tr.oe-treeview-first span, .treeview-td.oe-treeview-first span
margin-left: 16px
// }}}
// Translation {{{
.oe_trad_field.touched
border: 1px solid green !important
@@ -1878,49 +1982,6 @@ $sheet-max-width: 860px
float: right
color: #333
// }}}
//Tree view
.openerp
.tree_header
background-color: #f0f0f0
border-bottom: 1px solid #cacaca
color: #4c4c4c
padding: 5px
height: 25px
button
float: right
height: 27px
margin-right: 5px
.oe-treeview-table
width: 100%
background-color: white
border-spacing: 0
th
padding: 10px
color: #4c4c4c
font-weight: bold
background-color: #f0f0f0
border-bottom: 2px solid #cacaca
.treeview-tr, .treeview-td
cursor: pointer
border-right: 1px dotted #afafb6
vertical-align: top
text-align: left
border-bottom: 1px solid #cfcccc
tr:hover
background-color: #e0e0f8
.oe-number
text-align: right !important
span
font-size: 90%
font-weight: normal
white-space: nowrap
display: block
.treeview-tr.oe-treeview-first
background: transparent url(/web/static/src/img/expand.gif) 0 50% no-repeat
.oe_open .treeview-tr.oe-treeview-first
background-image: url(/web/static/src/img/collapse.gif)
.treeview-tr.oe-treeview-first span, .treeview-td.oe-treeview-first span
margin-left: 16px
// Kitten Mode {{{
.kitten-mode-activated
background-image: url(http://placekitten.com/g/1365/769)
@@ -1931,8 +1992,6 @@ $sheet-max-width: 860px
// }}}
div.ui-widget-overlay
background: black
@include opacity(0.3)
// au BufWritePost,FileWritePost *.sass :!sass --style expanded --line-numbers <afile> > "%:p:r.css"
// vim:tabstop=4:shiftwidth=4:softtabstop=4:fdm=marker:
Binary file not shown.

Before

Width:  |  Height:  |  Size: 98 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.0 KiB

+42 -39
View File
@@ -257,7 +257,7 @@ 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);
}
@@ -276,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');
@@ -287,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"));
@@ -354,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
@@ -387,8 +387,16 @@ instance.web.DatabaseManager = instance.web.Widget.extend({
var fields = $(form).serializeArray();
self.rpc("/web/database/create", {'fields': fields}, function(result) {
var form_obj = self.to_object(fields);
self.getParent().do_login( form_obj['db_name'], 'admin', form_obj['create_admin_pwd']);
self.destroy();
var client_action = {
type: 'ir.actions.client',
tag: 'login',
params: {
'db': form_obj['db_name'],
'login': 'admin',
'password': form_obj['create_admin_pwd'],
},
};
self.do_action(client_action);
});
},
@@ -473,19 +481,22 @@ instance.web.DatabaseManager = instance.web.Widget.extend({
});
},
do_exit: function () {
this.do_action("login");
}
});
instance.web.client_actions.add("database_manager", "instance.web.DatabaseManager");
instance.web.Login = instance.web.Widget.extend({
template: "Login",
remember_credentials: true,
_db_list: null,
init: function(parent) {
init: function(parent, params) {
this._super(parent);
this.has_local_storage = typeof(localStorage) != 'undefined';
this.selected_db = null;
this.selected_login = null;
this.params = params;
if (this.has_local_storage && this.remember_credentials) {
this.selected_db = localStorage.getItem('last_db_login_success');
@@ -495,26 +506,17 @@ instance.web.Login = instance.web.Widget.extend({
}
}
},
open_db_manager: function(){
var self = this;
self.$element.find('.oe_login_bottom').hide();
self.$element.find('.oe_login_pane').hide();
self.databasemanager = new instance.web.DatabaseManager(self);
self.databasemanager.appendTo(self.$element);
self.databasemanager.do_exit.add_last(function() {
self.databasemanager.destroy();
self.$element.find('.oe_login_bottom').show();
self.$element.find('.oe_login_pane').show();
self.load_db_list(true).then(self.on_db_list_loaded);
});
},
start: function() {
var self = this;
self.$element.find("form").submit(self.on_submit);
self.$element.find('.oe_login_manage_db').click(function() {
self.open_db_manager();
self.do_action("database_manager");
});
return self.load_db_list().then(self.on_db_list_loaded).then(function() {
if(self.params) {
self.do_login(self.params.db, self.params.login, self.params.password);
}
});
return self.load_db_list().then(self.on_db_list_loaded);
},
load_db_list: function (force) {
var d = $.when(), self = this;
@@ -535,7 +537,7 @@ instance.web.Login = instance.web.Widget.extend({
var dbdiv = this.$element.find('div.oe_login_dbpane');
this.$element.find("[name=db]").replaceWith(instance.web.qweb.render('Login.dblist', { db_list: list, selected_db: this.selected_db}));
if(list.length === 0) {
self.open_db_manager();
this.do_action("database_manager");
} else if(list && list.length === 1) {
dbdiv.hide();
} else {
@@ -582,13 +584,14 @@ instance.web.Login = instance.web.Widget.extend({
localStorage.setItem('last_password_login_success', '');
}
}
self.trigger("login");
self.trigger('login_successful');
},function () {
self.$(".oe_login_pane").fadeIn("fast");
self.$element.addClass("oe_login_invalid");
});
}
});
instance.web.client_actions.add("login", "instance.web.Login");
instance.web.Menu = instance.web.Widget.extend({
template: 'Menu',
@@ -864,7 +867,7 @@ instance.web.UserMenu = instance.web.Widget.extend({
window.location.href, 'debug');
});
instance.web.dialog($help, {autoOpen: true,
modal: true, width: 960, title: _t("About")});
modal: true, width: 580, height: 290, resizable: false, title: _t("About")});
});
},
});
@@ -893,7 +896,7 @@ instance.web.Client = instance.web.Widget.extend({
this.$element.on('click', '.oe_dropdown_toggle', function(ev) {
ev.preventDefault();
var $toggle = $(this);
var $menu = $toggle.find('.oe_dropdown_menu');
var $menu = $toggle.parent().find('.oe_dropdown_menu');
var state = $menu.is('.oe_opened');
setTimeout(function() {
// Do not alter propagation
@@ -903,7 +906,7 @@ instance.web.Client = instance.web.Widget.extend({
var doc_width = $(document).width();
var offset = $menu.offset();
var menu_width = $menu.width();
var x = doc_width - offset.left - menu_width - 15;
var x = doc_width - offset.left - menu_width - 2;
if (x < 0) {
$menu.offset({ left: offset.left + x }).width(menu_width);
}
@@ -964,19 +967,15 @@ instance.web.WebClient = instance.web.Client.extend({
data: {debug: file + ':' + line}
});
};
// TODO: deprecate and use login client action
self.login = new instance.web.Login(self);
self.login.on("login",self,self.show_application);
},
show_login: function() {
var self = this;
self.$('.oe_topbar').hide();
self.login.appendTo(self.$element);
this.$('.oe_topbar').hide();
this.action_manager.do_action("login");
this.action_manager.inner_widget.on('login_successful', this, this.show_application);
},
show_application: function() {
var self = this;
self.$('.oe_topbar').show();
self.login.$element.hide();
self.menu = new instance.web.Menu(self);
self.menu.replace(this.$element.find('.oe_menu_placeholder'));
self.menu.on('menu_click', this, this.on_menu_action);
@@ -1057,6 +1056,7 @@ instance.web.WebClient = instance.web.Client.extend({
},
do_push_state: function(state) {
this.set_title(state.title);
delete state.title;
var url = '#' + $.param(state);
this._current_state = _.clone(state);
$.bbq.pushState(url);
@@ -1083,10 +1083,13 @@ instance.web.WebClient = instance.web.Client.extend({
}
},
set_content_full_screen: function(fullscreen) {
if (fullscreen)
if (fullscreen) {
$(".oe_webclient", this.$element).addClass("oe_content_full_screen");
else
$("body").css({'overflow-y':'hidden'});
} else {
$(".oe_webclient", this.$element).removeClass("oe_content_full_screen");
$("body").css({'overflow-y':'scroll'});
}
}
});
+7 -5
View File
@@ -378,7 +378,8 @@ instance.web.PropertiesMixin = _.extend({}, instance.web.EventDispatcherMixin, {
instance.web.EventDispatcherMixin.init.call(this);
this.__getterSetterInternalMap = {};
},
set: function(map) {
set: function(map, options) {
options = options || {};
var self = this;
var changed = false;
_.each(map, function(val, key) {
@@ -387,10 +388,11 @@ instance.web.PropertiesMixin = _.extend({}, instance.web.EventDispatcherMixin, {
return;
changed = true;
self.__getterSetterInternalMap[key] = val;
self.trigger("change:" + key, self, {
oldValue: tmp,
newValue: val
});
if (! options.silent)
self.trigger("change:" + key, self, {
oldValue: tmp,
newValue: val
});
});
if (changed)
self.trigger("change", self);
+33 -1
View File
@@ -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 */
+2 -2
View File
@@ -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() {
+27 -2
View File
@@ -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) {
@@ -510,7 +516,16 @@ instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.Sea
this.$element.addClass('oe_focused');
},
childBlurred: function () {
this.$element.removeClass('oe_focused');
var val = this.$element.val();
this.$element.val('');
var complete = this.$element.data('autocomplete');
if ((val && complete.term === undefined) || complete.previous !== undefined) {
throw new Error("new jquery.ui version altering implementation" +
" details relied on");
}
delete complete.term;
this.$element.removeClass('oe_focused')
.trigger('blur');
},
/**
*
@@ -1475,7 +1490,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; }
+129 -39
View File
@@ -33,6 +33,11 @@ instance.web.form.FieldManagerMixin = {
};
instance.web.views.add('form', 'instance.web.FormView');
/**
* Properties:
* - actual_mode: always "view", "edit" or "create". Read-only property. Determines
* the mode used by the view.
*/
instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerMixin, {
/**
* Indicates that this view is not searchable, and thus that no search
@@ -55,6 +60,7 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
* @property {instance.web.Registry} registry=instance.web.form.widgets widgets registry for this form view instance
*/
init: function(parent, dataset, view_id, options) {
var self = this;
this._super(parent);
this.set_default_options(options);
this.dataset = dataset;
@@ -82,6 +88,13 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
this.__blur_timeout = null;
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
self.set({actual_mode: self.options.initial_mode});
this.has_been_loaded.then(function() {
self.on("change:actual_mode", self, self.check_actual_mode);
self.check_actual_mode();
self.on("change:actual_mode", self, self.init_pager);
self.init_pager();
});
},
destroy: function() {
_.each(this.get_widgets(), function(w) {
@@ -125,17 +138,6 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
this.$buttons.on('click','.oe_form_button_save',this.on_button_save);
this.$buttons.on('click','.oe_form_button_cancel',this.on_button_cancel);
this.$pager = $(QWeb.render("FormView.pager", {'widget':self}));
if (this.options.$pager) {
this.$pager.appendTo(this.options.$pager);
} else {
this.$element.find('.oe_form_pager').replaceWith(this.$pager);
}
this.$pager.on('click','a[data-pager-action]',function() {
var action = $(this).data('pager-action');
self.on_pager_action(action);
});
this.$sidebar = this.options.$sidebar || this.$element.find('.oe_form_sidebar');
if (!this.sidebar && this.options.$sidebar) {
this.sidebar = new instance.web.Sidebar(this);
@@ -149,8 +151,15 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
{ label: _t('Set Default'), callback: function (item) { self.open_defaults_dialog(); } },
]);
}
this.on("change:mode", this, this.switch_mode);
this.set({mode: this.options.initial_mode});
// Add bounce effect on button 'Edit' when click on readonly page view.
this.$element.find(".oe_form_field, .oe_form_group_cell").on('click', function (e) {
if(self.get("actual_mode") == "view") {
var $button = self.options.$buttons.find(".oe_form_button_edit");
$button.wrap('<div>').css('margin-right','4px').addClass('oe_left oe_bounce');
}
});
this.has_been_loaded.resolve();
return $.when();
},
@@ -275,7 +284,7 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
}
return shown.pipe(function() {
if (options.editable) {
self.set({mode: "edit"});
self.to_edit_mode();
}
self.$element.css('visibility', 'visible');
});
@@ -300,6 +309,7 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
return $.Deferred().reject();
}
this.datarecord = record;
this._actualize_mode();
this.set({ 'title' : record.id ? record.name : "New record" });
if (this.qweb) {
@@ -377,6 +387,24 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
this.reload();
}
},
init_pager: function() {
var self = this;
if (this.$pager)
this.$pager.remove();
if (this.get("actual_mode") === "create")
return;
this.$pager = $(QWeb.render("FormView.pager", {'widget':self}));
if (this.options.$pager) {
this.$pager.appendTo(this.options.$pager);
} else {
this.$element.find('.oe_form_pager').replaceWith(this.$pager);
}
this.$pager.on('click','a[data-pager-action]',function() {
var action = $(this).data('pager-action');
self.on_pager_action(action);
});
this.do_update_pager();
},
do_update_pager: function(hide_index) {
var index = hide_index ? '-' : this.dataset.index + 1;
this.$pager.find('button').prop('disabled', this.dataset.ids.length < 2).end()
@@ -576,9 +604,32 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
return $.Deferred().reject();
}
},
switch_mode: function() {
/**
* Ask the view to switch to view mode if possible. The view may not do it
* if the current record is not yet saved. It will then stay in create mode.
*/
to_view_mode: function() {
this._actualize_mode("view");
},
/**
* Ask the view to switch to edit mode if possible. The view may not do it
* if the current record is not yet saved. It will then stay in create mode.
*/
to_edit_mode: function() {
this._actualize_mode("edit");
},
/**
* Reactualize actual_mode.
*/
_actualize_mode: function(switch_to) {
var mode = switch_to || this.get("actual_mode");
if (! this.datarecord.id)
mode = "create";
this.set({actual_mode: mode});
},
check_actual_mode: function(source, options) {
var self = this;
if(this.get("mode") == "view") {
if(this.get("actual_mode") === "view") {
self.$element.removeClass('oe_form_editable').addClass('oe_form_readonly');
self.$buttons.find('.oe_form_buttons_edit').hide();
self.$buttons.find('.oe_form_buttons_view').show();
@@ -596,11 +647,12 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
});
var fields_order = self.fields_order.slice(0);
if (self.default_focus_field) {
fields_order.unshift(self.default_focus_field);
fields_order.unshift(self.default_focus_field.name);
}
for (var i = 0; i < fields_order.length; i += 1) {
var field = self.fields[fields_order[i]];
if (!field.get('effective_invisible') && !field.get('effective_readonly') && field.focus() !== false) {
if (!field.get('effective_invisible') && !field.get('effective_readonly')) {
field.focus();
break;
}
}
@@ -609,19 +661,19 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
on_button_save: function() {
var self = this;
return this.do_save().then(function(result) {
self.set({mode: "view"});
self.to_view_mode();
});
},
on_button_cancel: function(event) {
if (this.can_be_discarded()) {
this.set({mode: "view"});
this.to_view_mode();
this.on_record_loaded(this.datarecord);
}
return false;
},
on_button_new: function() {
var self = this;
this.set({mode: "edit"});
this.to_edit_mode();
return $.when(this.has_been_loaded).pipe(function() {
if (self.can_be_discarded()) {
return self.load_defaults();
@@ -629,7 +681,7 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
});
},
on_button_edit: function() {
return this.set({mode: "edit"});
return this.to_edit_mode();
},
on_button_create: function() {
this.dataset.index = null;
@@ -642,7 +694,7 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
self.dataset.call('copy', [self.datarecord.id, {}, self.dataset.context]).then(function(new_id) {
return self.on_created({ result : new_id });
}).then(function() {
return self.set({mode: "edit"});
return self.to_edit_mode();
}).then(function() {
def.resolve();
});
@@ -935,7 +987,7 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
register_field: function(field, name) {
this.fields[name] = field;
this.fields_order.push(name);
if (field.node.attrs.default_focus == '1') {
if (JSON.parse(field.node.attrs.default_focus || "0")) {
this.default_focus_field = field;
}
@@ -957,7 +1009,7 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
return this.fields_view.fields[field_name];
},
is_create_mode: function() {
return !this.datarecord.id;
return this.get("actual_mode") === "create";
},
open_translate_dialog: function(field) {
return this._super(field);
@@ -1641,10 +1693,13 @@ instance.web.form.WidgetButton = instance.web.form.FormWidget.extend({
this._super(view, node);
this.force_disabled = false;
this.string = (this.node.attrs.string || '').replace(/_/g, '');
if (this.node.attrs.default_focus == '1') {
if (JSON.parse(this.node.attrs.default_focus || "0")) {
// TODO fme: provide enter key binding to widgets
this.view.default_focus_button = this;
}
if (this.node.attrs.icon && (! /\//.test(this.node.attrs.icon))) {
this.node.attrs.icon = '/web/static/src/img/icons/' + this.node.attrs.icon + '.png';
}
this.view.on('view_content_has_changed', this, this.check_disable);
},
start: function() {
@@ -2818,10 +2873,11 @@ instance.web.form.FieldMany2One = instance.web.form.AbstractField.extend(instanc
if (follow)
link += "<br />";
}
this.$element.find('a')
var $link = this.$element.find('.oe_form_uri')
.unbind('click')
.html(link)
.click(function () {
.html(link);
if (! this.get_definition_options().no_open)
$link.click(function () {
self.do_action({
type: 'ir.actions.act_window',
res_model: self.field.relation,
@@ -2979,6 +3035,7 @@ instance.web.form.FieldOne2Many = instance.web.form.AbstractField.extend({
}
if(view.view_type === "list") {
_.extend(view.options, {
addable: null,
selectable: self.multi_selection,
sortable: false,
import_enabled: false,
@@ -2986,7 +3043,6 @@ instance.web.form.FieldOne2Many = instance.web.form.AbstractField.extend({
});
if (self.get("effective_readonly")) {
_.extend(view.options, {
addable: null,
deletable: null,
reorderable: false,
});
@@ -3027,8 +3083,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();
@@ -3301,7 +3360,7 @@ instance.web.form.One2ManyListView = instance.web.ListView.extend({
.value();
},
do_add_record: function () {
if (this.options.editable) {
if (this.editable()) {
this._super.apply(this, arguments);
} else {
var self = this;
@@ -3408,6 +3467,34 @@ instance.web.form.One2ManyListView = instance.web.ListView.extend({
this._super.apply(this, arguments);
}
});
instance.web.form.One2ManyList = instance.web.ListView.List.extend({
pad_table_to: function (count) {
this._super(count > 0 ? count - 1 : 0);
// magical invocation of wtf does that do
if (this.view.o2m.get('effective_readonly')) {
return;
}
var self = this;
var columns = _(this.columns).filter(function (column) {
return column.invisible !== '1';
}).length;
if (this.options.selectable) { columns++; }
if (this.options.deletable) { columns++; }
var $cell = $('<td>', {
colspan: columns,
'class': 'oe_form_field_one2many_list_row_add'
}).text(_t("Add a row"))
.click(function (e) {
e.preventDefault();
e.stopPropagation();
self.view.do_add_record();
});
this.$current.append(
$('<tr>').append($cell))
}
});
instance.web.form.One2ManyFormView = instance.web.FormView.extend({
form_template: 'One2Many.formview',
@@ -3535,12 +3622,13 @@ instance.web.form.FieldMany2ManyTags = instance.web.form.AbstractField.extend(in
render_value: function() {
var self = this;
var dataset = new instance.web.DataSetStatic(this, this.field.relation, self.view.dataset.get_context());
var values = self.get("value")
var handle_names = function(data) {
var indexed = {};
_.each(data, function(el) {
indexed[el[0]] = el;
});
data = _.map(self.get("value"), function(el) { return indexed[el]; });
data = _.map(values, function(el) { return indexed[el]; });
if (! self.get("effective_readonly")) {
self.tags.containerElement().children().remove();
$("textarea", self.$element).css("padding-left", "3px");
@@ -3549,8 +3637,8 @@ instance.web.form.FieldMany2ManyTags = instance.web.form.AbstractField.extend(in
self.$element.html(QWeb.render("FieldMany2ManyTag", {elements: data}));
}
};
if (! self.get('values') || self.get('values').length > 0) {
this._display_orderer.add(dataset.name_get(self.get("value"))).then(handle_names);
if (! values || values.length > 0) {
this._display_orderer.add(dataset.name_get(values)).then(handle_names);
} else {
handle_names([]);
}
@@ -4108,10 +4196,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();
@@ -4343,7 +4433,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({
@@ -4353,7 +4443,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();
+2 -31
View File
@@ -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,
},
@@ -360,6 +357,7 @@ instance.web.ListView = instance.web.View.extend( /** @lends instance.web.ListVi
{ label: _t('Delete'), callback: this.do_delete_selected },
]);
this.sidebar.add_toolbar(this.fields_view.toolbar);
this.sidebar.$element.hide();
}
},
/**
@@ -378,6 +376,7 @@ instance.web.ListView = instance.web.View.extend( /** @lends instance.web.ListVi
var total = dataset.size();
var limit = this.limit() || total;
this.$pager.toggle(total !== 0);
this.$pager.toggleClass('oe_list_pager_single_page', (total <= limit));
var spager = '-';
if (total) {
@@ -496,9 +495,6 @@ instance.web.ListView = instance.web.View.extend( /** @lends instance.web.ListVi
},
do_show: function () {
this._super();
if (this.sidebar) {
this.sidebar.$element.show();
}
if (this.$buttons) {
this.$buttons.show();
}
@@ -937,7 +933,6 @@ instance.web.ListView.List = instance.web.Class.extend( /** @lends instance.web.
'[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, attribute, value, old_value) {
@@ -972,8 +967,6 @@ instance.web.ListView.List = instance.web.Class.extend( /** @lends instance.web.
'[data-id=' + previous_record.get('id') + ']');
$new_row.insertAfter($previous_sibling);
}
self.refresh_zebra(index, 1);
}
};
_(this.record_callbacks).each(function (callback, event) {
@@ -1113,7 +1106,6 @@ instance.web.ListView.List = instance.web.Class.extend( /** @lends instance.web.
this.$current
.children('tr:not([data-id])').remove().end()
.append(new Array(count - this.records.length + 1).join(row));
this.refresh_zebra(this.records.length);
},
/**
* Gets the ids of all currently selected records, if any
@@ -1187,25 +1179,6 @@ instance.web.ListView.List = instance.web.Class.extend( /** @lends instance.web.
render_cell: function () {
return self.render_cell.apply(self, arguments); }
});
},
/**
* Fixes fixes the even/odd classes
*
* @param {Number} [from_index] index from which to resequence
* @param {Number} [offset = 0] selection offset for DOM, in case there are rows to ignore in the table
*/
refresh_zebra: function (from_index, offset) {
offset = offset || 0;
from_index = from_index || 0;
var dom_offset = offset + from_index;
var sel = dom_offset ? ':gt(' + (dom_offset - 1) + ')' : null;
this.$current.children(sel).each(function (i, e) {
var index = from_index + i;
// reset record-index accelerators on rows and even/odd
var even = index%2 === 0;
$(e).toggleClass('even', even)
.toggleClass('odd', !even);
});
}
});
instance.web.ListView.Groups = instance.web.Class.extend( /** @lends instance.web.ListView.Groups# */{
@@ -1538,8 +1511,6 @@ instance.web.ListView.Groups = instance.web.Class.extend( /** @lends instance.we
}(dataset, record.get('id'), seq));
record.set('sequence', seq);
}
list.refresh_zebra();
}
});
},
+146 -44
View File
@@ -12,6 +12,8 @@ openerp.web.list_editable = function (instance) {
var self = this;
this._super.apply(this, arguments);
this._force_editability = null;
this._context_editable = false;
this.editor = this.make_editor();
// Stores records of {field, cell}, allows for re-rendering fields
// depending on cell state during and after resize events
@@ -37,6 +39,11 @@ openerp.web.list_editable = function (instance) {
}
});
this.on('edit:before', this, function (event) {
if (!self.editable() || self.editor.is_editing()) {
event.cancel = true;
}
});
this.on('edit:after', this, function () {
self.$element.add(self.$buttons).addClass('oe_editing');
});
@@ -62,26 +69,16 @@ openerp.web.list_editable = function (instance) {
do_edit: function (index, id, dataset) {
_.extend(this.dataset, dataset);
},
/**
* Sets editability status for the list, based on defaults, view
* architecture and the provided flag, if any.
*
* @param {Boolean} [force] forces the list to editability. Sets new row edition status to "bottom".
*/
set_editable: function (force) {
// TODO: fix handling of editability status to be simpler & clearer & more coherent
// If ``force``, set editability to bottom
// otherwise rely on view default
// view' @editable is handled separately as we have not yet
// fetched and processed the view at this point.
this.options.editable = (
! this.options.read_only && ((force && "bottom") || this.defaults.editable));
editable: function () {
return this.fields_view.arch.attrs.editable
|| this._context_editable
|| this.options.editable;
},
/**
* Replace do_search to handle editability process
*/
do_search: function(domain, context, group_by) {
this.set_editable(context['set_editable']);
this._context_editable = !!context.set_editable;
this._super.apply(this, arguments);
},
/**
@@ -89,7 +86,7 @@ openerp.web.list_editable = function (instance) {
* as an editable row at the top or bottom of the list)
*/
do_add_record: function () {
if (this.options.editable) {
if (this.editable()) {
this.$element.find('table:first').show();
this.$element.find('.oe_view_nocontent').remove();
this.start_edition();
@@ -103,9 +100,8 @@ openerp.web.list_editable = function (instance) {
this.editor.destroy();
}
// tree/@editable takes priority on everything else if present.
this.options.editable = ! this.options.read_only && (data.arch.attrs.editable || this.options.editable);
var result = this._super(data, grouped);
if (this.options.editable) {
if (this.editable()) {
// FIXME: any hook available to ensure this is only done once?
this.$buttons
.off('click', '.oe_list_save')
@@ -202,12 +198,20 @@ openerp.web.list_editable = function (instance) {
return;
}
// FIXME: need better way to get the field back from bubbling (delegated) DOM events somehow
field.$element.attr('data-fieldname', field_name);
self.fields_for_resize.push({field: field, cell: cell});
}, options).pipe(function () {
$recordRow.addClass('oe_edition');
self.resize_fields();
return record.attributes;
});
}).fail(function () {
// if the start_edition event is cancelled and it was a
// creation, remove the newly-created empty record
if (!record.get('id')) {
self.records.remove(record);
}
});
});
},
@@ -377,7 +381,7 @@ openerp.web.list_editable = function (instance) {
return this.reload_record(record);
},
prepends_on_create: function () {
return this.options.editable === 'top';
return this.editable() === 'top';
},
setup_events: function () {
var self = this;
@@ -399,18 +403,20 @@ openerp.web.list_editable = function (instance) {
*
* @private
* @param {String} [next_record='succ'] method to call on the records collection to get the next record to edit
* @param {Object} [options]
* @param {String} [options.focus_field]
* @return {*}
*/
_next: function (next_record) {
_next: function (next_record, options) {
next_record = next_record || 'succ';
var self = this;
return this.save_edition().pipe(function (saveInfo) {
if (saveInfo.created) {
return self.start_edition();
}
return self.start_edition(
self.records[next_record](
saveInfo.record, {wraparound: true}));
var record = self.records[next_record](
saveInfo.record, {wraparound: true});
return self.start_edition(record, options);
});
},
keyup_ENTER: function () {
@@ -419,46 +425,142 @@ openerp.web.list_editable = function (instance) {
keyup_ESCAPE: function () {
return this.cancel_edition();
},
/**
* Gets the selection range (start, end) for the provided element,
* returns ``null`` if it can't get a range.
*
* @private
*/
_text_selection_range: function (el) {
if (el.selectionStart !== undefined) {
var selectionStart;
try {
selectionStart = el.selectionStart;
} catch (e) {
// radio or checkbox throw on selectionStart access
return null;
}
if (selectionStart !== undefined) {
return {
start: el.selectionStart,
start: selectionStart,
end: el.selectionEnd
};
} else if(document.body.createTextRange) {
} else if (document.body.createTextRange) {
throw new Error("Implement text range handling for MSIE");
var sel = document.body.createTextRange();
if (sel.parentElement() === el) {
}
}
// Element without selection ranges (select, div/@contenteditable)
return null;
},
_text_cursor: function (el) {
var selection = this._text_selection_range(el);
if (selection.start !== selection.end) {
if (!selection) {
return null;
}
return selection.start;
if (selection.start !== selection.end) {
return {position: null, collapsed: false};
}
return {position: selection.start, collapsed: true};
},
/**
* Checks if the cursor is at the start of the provided el
*
* @param {HTMLInputElement | HTMLTextAreaElement}
* @returns {Boolean}
* @private
*/
_at_start: function (cursor, el) {
return cursor.collapsed && (cursor.position === 0);
},
/**
* Checks if the cursor is at the end of the provided el
*
* @param {HTMLInputElement | HTMLTextAreaElement}
* @returns {Boolean}
* @private
*/
_at_end: function (cursor, el) {
return cursor.collapsed && (cursor.position === el.value.length);
},
/**
* @param DOMEvent event
* @param {String} record_direction direction to move into to get the next record (pred | succ)
* @param {Function} is_valid_move whether the edition should be moved to the next record
* @private
*/
_key_move_record: function (event, record_direction, is_valid_move) {
if (!this.editor.is_editing('edit')) { return $.when(); }
var cursor = this._text_cursor(event.target);
// if text-based input (has a cursor)
// and selecting (not collapsed) or not at a field boundary
// don't move to the next record
if (cursor && !is_valid_move(event.target, cursor)) { return $.when(); }
event.preventDefault();
var source_field = $(event.target).closest('[data-fieldname]')
.attr('data-fieldname');
return this._next(record_direction, {focus_field: source_field});
},
keydown_UP: function (e) {
if (!this.editor.is_editing('edit')) { return $.when(); }
// FIXME: assumes editable widgets are input-type elements
var index = this._text_cursor(e.target);
// If selecting or not at the start of the input
if (index === null || index !== 0) { return $.when(); }
e.preventDefault();
return this._next('pred');
var self = this;
return this._key_move_record(e, 'pred', function (el, cursor) {
return self._at_start(cursor, el);
});
},
keydown_DOWN: function (e) {
if (!this.editor.is_editing('edit')) { return $.when(); }
// FIXME: assumes editable widgets are input-type elements
var index = this._text_cursor(e.target);
// If selecting or not at the end of the input
if (index === null || index !== e.target.value.length) { return $.when(); }
var self = this;
return this._key_move_record(e, 'succ', function (el, cursor) {
return self._at_end(cursor, el);
});
},
e.preventDefault();
return this._next();
keydown_LEFT: function (e) {
// If the cursor is at the beginning of the field
var source_field = $(e.target).closest('[data-fieldname]')
.attr('data-fieldname');
var cursor = this._text_cursor(e.target);
if (cursor && !this._at_start(cursor, e.target)) { return $.when(); }
var fields_order = this.editor.form.fields_order;
var field_index = _(fields_order).indexOf(source_field);
// Look for the closest visible form field to the left
var fields = this.editor.form.fields;
var field;
do {
if (--field_index < 0) { return $.when(); }
field = fields[fields_order[field_index]];
} while (!field.$element.is(':visible'));
// and focus it
field.focus();
return $.when();
},
keydown_RIGHT: function (e) {
// same as above, but with cursor at the end of the field and
// looking for new fields at the right
var source_field = $(e.target).closest('[data-fieldname]')
.attr('data-fieldname');
var cursor = this._text_cursor(e.target);
if (cursor && !this._at_end(cursor, e.target)) { return $.when(); }
var fields_order = this.editor.form.fields_order;
var field_index = _(fields_order).indexOf(source_field);
var fields = this.editor.form.fields;
var field;
do {
if (++field_index >= fields_order.length) { return $.when(); }
field = fields[fields_order[field_index]];
} while (!field.$element.is(':visible'));
field.focus();
return $.when();
},
keydown_TAB: function (e) {
var form = this.editor.form;
@@ -642,7 +744,7 @@ openerp.web.list_editable = function (instance) {
instance.web.ListView.List.include(/** @lends instance.web.ListView.List# */{
row_clicked: function (event) {
if (!this.options.editable) {
if (!this.view.editable()) {
return this._super.apply(this, arguments);
}
var record_id = $(event.currentTarget).data('id');
+55 -28
View File
@@ -120,7 +120,9 @@ instance.web.ActionManager = instance.web.Widget.extend({
if (this.getParent() && this.getParent().do_push_state) {
if (this.inner_action) {
state['title'] = this.inner_action.name;
state['model'] = this.inner_action.res_model;
if(this.inner_action.type == 'ir.actions.act_window') {
state['model'] = this.inner_action.res_model;
}
if (this.inner_action.id) {
state['action_id'] = this.inner_action.id;
}
@@ -178,7 +180,10 @@ instance.web.ActionManager = instance.web.Widget.extend({
});
},
do_action: function(action, on_close) {
if (_.isNumber(action) || _.isString(action)) {
if (_.isString(action) && instance.web.client_actions.contains(action)) {
var action_client = { type: "ir.actions.client", tag: action };
return this.do_action(action_client);
} else if (_.isNumber(action) || _.isString(action)) {
var self = this;
return self.rpc("/web/action/load", { action_id: action }, function(result) {
self.do_action(result.result, on_close);
@@ -209,21 +214,30 @@ instance.web.ActionManager = instance.web.Widget.extend({
this.dialog_stop();
this.clear_breadcrumbs();
},
ir_actions_act_window: function (action, on_close) {
var self = this;
if (_(['base.module.upgrade', 'base.setup.installer'])
.contains(action.res_model)) {
var old_close = on_close;
on_close = function () {
instance.webclient.do_reload().then(old_close);
};
do_ir_actions_common: function(action, on_close) {
var self = this, klass, widget, add_breadcrumb;
if (action.type === 'ir.actions.client') {
var ClientWidget = instance.web.client_actions.get_object(action.tag);
widget = new ClientWidget(this, action.params);
klass = 'oe_act_client';
add_breadcrumb = function() {
self.push_breadcrumb({
widget: widget,
title: action.name
});
}
} else {
widget = new instance.web.ViewManagerAction(this, action);
klass = 'oe_act_window';
add_breadcrumb = widget.add_breadcrumb
}
if (action.target === 'new') {
if (this.dialog === null) {
// These buttons will be overwrited by <footer> if any
this.dialog = new instance.web.Dialog(this, {
buttons: { "Close": function() { $(this).dialog("close"); }},
dialogClass: 'oe_act_window'
dialogClass: klass
});
if(on_close)
this.dialog.on_close.add(on_close);
@@ -231,7 +245,7 @@ instance.web.ActionManager = instance.web.Widget.extend({
this.dialog_widget.destroy();
}
this.dialog.dialog_title = action.name;
this.dialog_widget = new instance.web.ViewManagerAction(this, action);
this.dialog_widget = widget;
this.dialog_widget.appendTo(this.dialog.$element);
this.dialog.open();
} else {
@@ -242,11 +256,34 @@ instance.web.ActionManager = instance.web.Widget.extend({
});
}
this.inner_action = action;
var inner_widget = this.inner_widget = new instance.web.ViewManagerAction(this, action);
inner_widget.add_breadcrumb();
this.inner_widget = widget;
add_breadcrumb();
this.inner_widget.appendTo(this.$element);
}
},
ir_actions_act_window: function (action, on_close) {
var self = this;
if (_(['base.module.upgrade', 'base.setup.installer'])
.contains(action.res_model)) {
var old_close = on_close;
on_close = function () {
instance.webclient.do_reload().then(old_close);
};
}
if (action.target !== 'new') {
if(action.menu_id) {
this.dialog_stop();
return this.getParent().do_action(action, function () {
instance.webclient.menu.open_menu(action.menu_id);
});
}
}
return this.do_ir_actions_common(action, on_close);
},
ir_actions_client: function (action, on_close) {
return this.do_ir_actions_common(action, on_close);
},
ir_actions_act_window_close: function (action, on_closed) {
if (!this.dialog && on_closed) {
on_closed();
@@ -262,19 +299,9 @@ instance.web.ActionManager = instance.web.Widget.extend({
self.do_action(action, on_closed)
});
},
ir_actions_client: function (action) {
this.dialog_stop();
var ClientWidget = instance.web.client_actions.get_object(action.tag);
this.inner_widget = new ClientWidget(this, action.params);
this.push_breadcrumb({
widget: this.inner_widget,
title: action.name
});
this.inner_widget.appendTo(this.$element);
},
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 +311,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();
@@ -841,7 +868,7 @@ instance.web.Sidebar = instance.web.Widget.extend({
} else {
self.do_attachement_update(self.dataset, self.model_id);
}
$.unblockUI();
instance.web.unblockUI();
});
},
start: function() {
@@ -980,7 +1007,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) {
+87 -90
View File
@@ -329,21 +329,20 @@
</span>
</t>
<t t-name="UserMenu.about">
<div>
<a class="oe_activate_debug_mode" href="?debug" style="float:right; font-size: 80%;">Activate the developer mode</a>
<h1 style="margin:0;">OpenERP</h1>
<h3 style="margin:15px 0;padding:0;">Version <t t-esc="version_info.version"/></h3>
<p>
Copyright © 2004-TODAY OpenERP SA. All Rights Reserved.<br />
OpenERP is a trademark of the <a target="_blank" href="http://openerp.com/" style="text-decoration: underline;">OpenERP SA Company</a>.
</p>
<p>
Licenced under the terms of <a target="_blank" href="http://www.gnu.org/licenses/agpl.html" style="text-decoration: underline;">GNU Affero General Public License</a>
</p>
<p>
For more information visit <a target="_blank" href="http://openerp.com/" style="text-decoration: underline;">OpenERP.com</a>
</p>
<div class="oe_about">
<a class="oe_activate_debug_mode oe_right" href="?debug">Activate the developer mode</a>
<img class="oe_logo" src="/web/static/src/img/logo2.png"/>
<h3>Version <t t-esc="version_info.version"/></h3>
<div class="oe_bottom">
<p>Copyright © 2004-TODAY OpenERP SA. All Rights Reserved.<br />
OpenERP is a trademark of the <a target="_blank" href="http://openerp.com/" style="text-decoration: underline;">OpenERP SA Company</a>.</p>
<p>Licenced under the terms of <a target="_blank" href="http://www.gnu.org/licenses/agpl.html" style="text-decoration: underline;">GNU Affero General Public License</a></p>
<p>For more information visit <a target="_blank" href="http://openerp.com/" style="text-decoration: underline;">OpenERP.com</a></p>
</div>
</div>
</t>
<t t-name="UserMenu.password">
<form name="change_password_form" method="POST">
@@ -519,25 +518,25 @@
<div class="oe_form_dropdown_section">
<button class="oe_dropdown_toggle oe_dropdown_arrow">
<t t-esc="section.label"/>
<ul class="oe_dropdown_menu">
<li t-foreach="widget.items[section.name]" t-as="item" t-att-class="item.classname">
<a class="oe_sidebar_action_a" t-att-title="item.title" t-att-data-section="section.name" t-att-data-index="item_index" t-att-href="item.url" target="_blank">
<t t-raw="item.label"/>
</a>
<a t-if="section.name == 'files'" class="oe_sidebar_delete_item" t-att-data-id="item.id" title="Delete this attachment">x</a>
</li>
<li t-if="section.name == 'files'" class="oe_sidebar_add_attachment">
<t t-call="HiddenInputFile">
<t t-set="fileupload_id" t-value="widget.fileupload_id"/>
<t t-set="fileupload_action">/web/binary/upload_attachment</t>
<input type="hidden" name="model" t-att-value="widget.dataset and widget.dataset.model"/>
<input type="hidden" name="id" t-att-value="widget.model_id"/>
<input type="hidden" name="session_id" t-att-value="widget.session.session_id"/>
<span>Add...</span>
</t>
</li>
</ul>
</button>
<ul class="oe_dropdown_menu">
<li t-foreach="widget.items[section.name]" t-as="item" t-att-class="item.classname">
<a class="oe_sidebar_action_a" t-att-title="item.title" t-att-data-section="section.name" t-att-data-index="item_index" t-att-href="item.url" target="_blank">
<t t-raw="item.label"/>
</a>
<a t-if="section.name == 'files'" class="oe_sidebar_delete_item" t-att-data-id="item.id" title="Delete this attachment">x</a>
</li>
<li t-if="section.name == 'files'" class="oe_sidebar_add_attachment">
<t t-call="HiddenInputFile">
<t t-set="fileupload_id" t-value="widget.fileupload_id"/>
<t t-set="fileupload_action">/web/binary/upload_attachment</t>
<input type="hidden" name="model" t-att-value="widget.dataset and widget.dataset.model"/>
<input type="hidden" name="id" t-att-value="widget.model_id"/>
<input type="hidden" name="session_id" t-att-value="widget.session.session_id"/>
<span>Add...</span>
</t>
</li>
</ul>
</div>
</t>
</div>
@@ -646,17 +645,14 @@
<t t-name="ListView.rows" t-foreach="records.length" t-as="index">
<t t-call="ListView.row">
<t t-set="record" t-value="records.at(index)"/>
<t t-set="row_parity" t-value="index_parity"/>
</t>
</t>
<tr t-name="ListView.row" t-att-class="row_parity"
<tr t-name="ListView.row"
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">
</td>
<td t-if="column.meta"> </td>
</t>
<th t-if="options.selectable" class="oe_list_record_selector" width="1">
<t t-set="checked" t-value="options.select_view_id == record.get('id') ? 'checked' : null"/>
@@ -675,7 +671,6 @@
<button type="button" name="delete" class="oe_i">d</button>
</td>
</tr>
<t t-extend="ListView.buttons">
<t t-jquery="button.oe_list_add" t-operation="after">
<button class="oe_button oe_list_save oe_highlight"
@@ -685,6 +680,15 @@
<a href="#" class="oe_bold oe_list_discard">discard</a>
</t>
</t>
<t t-extend="ListView.row">
<!-- adds back padding to row being rendered after edition, if necessary
(if not deletable add back padding), otherwise the row being added is
missing columns
-->
<t t-jquery="&gt; :last" t-operation="after">
<td t-if="edited and !options.deletable" class="oe-listview-padding"/>
</t>
</t>
<t t-name="FormView">
<div class="oe_formview">
@@ -956,11 +960,13 @@
<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">
<t t-if="widget.get('effective_readonly')">
<a href="#" class="oe_form_uri"/>
<a t-if="! widget.get_definition_options().no_open" href="#" class="oe_form_uri"/>
<span t-if="widget.get_definition_options().no_open" href="#" class="oe_form_uri"/>
<span class="oe_form_m2o_follow"/>
</t>
<t t-if="!widget.get('effective_readonly')">
<a href="#" tabindex="-1" class="oe_m2o_cm_button oe_e oe_right">/</a>
<a t-if="! widget.get_definition_options().no_open" href="#" tabindex="-1"
class="oe_m2o_cm_button oe_e oe_right">/</a>
<div>
<input type="text"
t-att-id="widget.id_for_label"
@@ -975,7 +981,6 @@
</t>
</span>
</t>
<!-- Collection of m2m tags -->
<t t-name="FieldMany2ManyTags">
<div class="oe_form_field oe_tags" t-att-style="widget.node.attrs.style">
<t t-if="! widget.get('effective_readonly')">
@@ -984,7 +989,6 @@
</t>
</div>
</t>
<!-- Individual m2m tag element -->
<t t-name="FieldMany2ManyTag">
<t t-set="i" t-value="0"/>
<t t-foreach="elements" t-as="el">
@@ -1132,7 +1136,7 @@
t-att-style="widget.node.attrs.style"
t-att-tabindex="widget.node.attrs.tabindex"
t-att-autofocus="widget.node.attrs.autofocus">
<img t-if="widget.node.attrs.icon" t-att-src="_s + '/web/static/src/img/icons/' + widget.node.attrs.icon + '.png'" width="16" height="16"/>
<img t-if="widget.node.attrs.icon" t-att-src="_s + widget.node.attrs.icon" width="16" height="16"/>
<span t-if="widget.string"><t t-esc="widget.string"/></span>
</button>
</t>
@@ -1190,6 +1194,41 @@
</table>
</t>
<t t-name="AbstractFormPopup.render">
<div>
<table style="width:100%">
<tr style="width:100%">
<td style="width:100%">
<div class="oe_popup_search" style="width:100%"></div>
</td>
</tr>
<tr style="width:100%">
<td style="width:100%">
<div class="oe_popup_list" style="width:100%"></div>
</td>
</tr>
</table>
<div class="oe_popup_form" style="width:100%"></div>
</div>
</t>
<t t-name="SelectCreatePopup.search.buttons">
<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">
<button type="button" class="oe_button oe_abstractformpopup-form-save oe_highlight">Save</button>
</t>
<t t-if="multi_select">
<button type="button" class="oe_button oe_abstractformpopup-form-save-new oe_highlight">Save &amp; New</button>
<button type="button" class="oe_button oe_abstractformpopup-form-save oe_highlight">Save &amp; Close</button>
</t>
or <a class="oe_button oe_abstractformpopup-form-close oe_bold oe_form_button_cancel" href="javascript:void(0)">Discard</a>
</t>
<t t-name="One2Many.viewmanager" t-extend="ViewManager">
<t t-jquery=".oe-view-manager-header">
this.attr('t-if', 'views.length != 1');
@@ -1220,6 +1259,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"
@@ -1240,7 +1281,6 @@
<span t-name="SearchView.FacetView.Value" class="oe_facet_value">
<t t-esc="widget.model.get('label')"/>
</span>
<t t-name="SearchView.managed-filters">
<option class="oe_search_filters_title" value="">Filters</option>
<optgroup label="-- Filters --">
@@ -1265,7 +1305,6 @@
<p>(Any existing filter with the same name will be replaced)</p>
</div>
</t>
<t t-name="SearchView.render_lines">
<table class="oe_search_render_line" border="0" cellspacing="0" cellpadding="0"
t-foreach="lines" t-as="line">
@@ -1407,8 +1446,8 @@
<div t-name="SearchView.addtodashboard" class="oe_searchview_dashboard">
<h4>Add to Dashboard</h4>
<form>
<input placeholder ="Title of new Dashboard item" title = "Title of new Dashboard item" type="text"/>
<button class="oe_apply" type="submit">save</button>
<p><input placeholder ="Title of new Dashboard item" title = "Title of new Dashboard item" type="text"/></p>
<button class="oe_apply" type="submit">Save</button>
</form>
</div>
<t t-name="SearchView.addtodashboard.selection">
@@ -1462,49 +1501,6 @@
</t>
</select>
</t>
<t t-name="AbstractFormPopup.render">
<div>
<table style="width:100%">
<tr style="width:100%">
<td style="width:100%">
<div class="oe_popup_search" style="width:100%"></div>
</td>
</tr>
<tr style="width:100%">
<td style="width:100%">
<div class="oe_popup_list" style="width:100%"></div>
</td>
</tr>
</table>
<div class="oe_popup_form" style="width:100%"></div>
</div>
</t>
<t t-name="SelectCreatePopup.search.buttons">
<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">
<button type="button" class="oe_button oe_abstractformpopup-form-save oe_highlight">Save</button>
</t>
<t t-if="multi_select">
<button type="button" class="oe_button oe_abstractformpopup-form-save-new oe_highlight">Save &amp; New</button>
<button type="button" class="oe_button oe_abstractformpopup-form-save oe_highlight">Save &amp; Close</button>
</t>
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
(if not deletable add back padding), otherwise the row being added is
missing columns
-->
<t t-jquery="&gt; :last" t-operation="after">
<td t-if="edited and !options.deletable" class="oe-listview-padding"/>
</t>
</t>
<t t-name="view_editor">
<table class="oe_view_editor">
@@ -1569,6 +1565,7 @@
<t t-name="vieweditor_boolean">
<input type="checkbox" t-att-id="widget.name"/>
</t>
<t t-name="ExportView">
<a id="exportview" href="javascript: void(0)" style="text-decoration: none;color: #3D3D3D;">Export</a>
</t>
+50 -13
View File
@@ -1,3 +1,4 @@
@charset "utf-8";
.openerp .oe_kanban_view {
background: url(/web/static/src/img/form_sheetbg.png);
height: inherit;
@@ -49,7 +50,7 @@
.openerp .oe_kanban_view .oe_kanban_group_title {
font-size: 16px;
font-weight: bold;
min-height: 30px;
min-height: 32px;
color: #333333;
text-shadow: 0 1px 0 white;
}
@@ -359,6 +360,9 @@
.openerp .oe_kanban_view .oe_kanban_card .oe_dropdown_kanban {
margin-top: 4px;
}
.openerp .oe_kanban_view .oe_kanban_card .oe_dropdown_kanban .oe_kanban_project_times li {
float: left;
}
.openerp .oe_kanban_view .oe_kanban_star {
float: left;
position: inline-block;
@@ -401,9 +405,6 @@
position: relative;
top: 2px;
}
.openerp .oe_kanban_view .oe_kanban_project_times li {
float: left;
}
.openerp .oe_kanban_view .oe_kanban_status {
position: relative;
top: 4px;
@@ -471,30 +472,25 @@
visibility: hidden;
}
.openerp .oe_kanban_view .oe_kanban_colorpicker {
padding: 3px 6px;
white-space: nowrap;
}
.openerp .oe_kanban_view .oe_kanban_colorpicker li {
float: left;
margin: 0;
padding: 0;
}
.openerp .oe_kanban_view .oe_kanban_colorpicker li a {
display: inline-block;
width: 18px;
height: 18px;
width: 16px;
height: 16px;
border: 1px solid white;
}
.openerp .oe_kanban_view .oe_kanban_colorpicker li a:hover {
border: 1px solid gray !important;
}
.openerp .oe_kanban_view .oe_kanban_colorpicker li:first-child a {
margin-top: 1px;
height: 16px;
border: 1px solid #cccccc;
}
.openerp .oe_kanban_view .oe_kanban_colorpicker li:first-child a:hover {
margin-top: 0px;
height: 18px;
}
.openerp .oe_kanban_view .oe_kanban_color_0 {
background-color: white;
}
@@ -530,3 +526,44 @@
padding: 0px;
background: white;
}
.openerp .oe_popup_form .oe_kanban_buttons .oe_highlight {
color: #404040;
background: none;
}
.openerp .oe_popup_form .oe_kanban_buttons button.oe_highlight {
background-color: #efefef;
background-image: -webkit-gradient(linear, left top, left bottom, from(#efefef), to(#d8d8d8));
background-image: -webkit-linear-gradient(top, #efefef, #d8d8d8);
background-image: -moz-linear-gradient(top, #efefef, #d8d8d8);
background-image: -ms-linear-gradient(top, #efefef, #d8d8d8);
background-image: -o-linear-gradient(top, #efefef, #d8d8d8);
background-image: linear-gradient(to bottom, #efefef, #d8d8d8);
-moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(255, 255, 255, 0.8) inset;
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(255, 255, 255, 0.8) inset;
-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(255, 255, 255, 0.8) inset;
}
.openerp .oe_popup_form .oe_kanban_buttons button.oe_highlight:active {
background-color: #e3e3e3;
background-image: -webkit-gradient(linear, left top, left bottom, from(#e3e3e3), to(#f6f6f6));
background-image: -webkit-linear-gradient(top, #e3e3e3, #f6f6f6);
background-image: -moz-linear-gradient(top, #e3e3e3, #f6f6f6);
background-image: -ms-linear-gradient(top, #e3e3e3, #f6f6f6);
background-image: -o-linear-gradient(top, #e3e3e3, #f6f6f6);
background-image: linear-gradient(to bottom, #e3e3e3, #f6f6f6);
-moz-box-shadow: none;
-webkit-box-shadow: none;
-box-shadow: none;
}
.openerp .oe_popup_form .oe_kanban_buttons button.oe_highlight:hover {
background-color: #f6f6f6;
background-image: -webkit-gradient(linear, left top, left bottom, from(#f6f6f6), to(#e3e3e3));
background-image: -webkit-linear-gradient(top, #f6f6f6, #e3e3e3);
background-image: -moz-linear-gradient(top, #f6f6f6, #e3e3e3);
background-image: -ms-linear-gradient(top, #f6f6f6, #e3e3e3);
background-image: -o-linear-gradient(top, #f6f6f6, #e3e3e3);
background-image: linear-gradient(to bottom, #f6f6f6, #e3e3e3);
-moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(255, 255, 255, 0.8) inset;
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(255, 255, 255, 0.8) inset;
-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(255, 255, 255, 0.8) inset;
}
+35 -12
View File
@@ -1,6 +1,15 @@
@charset "utf-8"
// Mixins {{{
@mixin vertical-gradient($startColor: #555, $endColor: #333)
background-color: $startColor
background-image: -webkit-gradient(linear, left top, left bottom, from($startColor), to($endColor)) /* Saf4+, Chrome */
background-image: -webkit-linear-gradient(top, $startColor, $endColor) /* Chrome 10+, Saf5.1+, iOS 5+ */
background-image: -moz-linear-gradient(top, $startColor, $endColor) /* FF3.6 */
background-image: -ms-linear-gradient(top, $startColor, $endColor) /* IE10 */
background-image: -o-linear-gradient(top, $startColor, $endColor) /* Opera 11.10+ */
background-image: linear-gradient(to bottom, $startColor, $endColor)
@mixin radial-gradient($gradient)
background-position: center center
background-image: -webkit-radial-gradient(circle, $gradient)
@@ -64,7 +73,7 @@
.oe_kanban_group_title
font-size: 16px
font-weight: bold
min-height: 30px
min-height: 32px
color: #333333
text-shadow: 0 1px 0 white
> span
@@ -307,6 +316,10 @@
text-decoration: none
.oe_dropdown_kanban
margin-top: 4px
.oe_kanban_project_times
li
float: left
.oe_kanban_star
float: left
position: inline-block
@@ -337,9 +350,6 @@
position: relative
top: 2px
.oe_kanban_project_times li
float: left
.oe_kanban_status
position: relative
top: 4px
@@ -387,24 +397,20 @@
// }}}
// KanbanColorPicker {{{
.oe_kanban_colorpicker
padding: 3px 6px
white-space: nowrap
.oe_kanban_colorpicker li
float: left
margin: 0
padding: 0
a
display: inline-block
width: 18px
height: 18px
width: 16px
height: 16px
border: 1px solid white
a:hover
border: 1px solid gray !important
.oe_kanban_colorpicker li:first-child a
margin-top: 1px
height: 16px
border: 1px solid #ccc
&:hover
margin-top: 0px
height: 18px
// }}}
// KanbanColors {{{
.oe_kanban_color_0
@@ -442,5 +448,22 @@
padding: 0px
background: #ffffff
.openerp
.oe_popup_form
.oe_kanban_buttons
.oe_highlight
color: #404040
background: none
button.oe_highlight
@include vertical-gradient(#efefef, #d8d8d8)
@include box-shadow((0 1px 2px rgba(0, 0, 0, .1), 0 1px 1px rgba(255, 255, 255, .8) inset))
button.oe_highlight:active
@include vertical-gradient(#e3e3e3, #f6f6f6)
@include box-shadow(none)
button.oe_highlight:hover
@include vertical-gradient(#f6f6f6, #e3e3e3)
@include box-shadow((0 1px 2px rgba(0, 0, 0, .1), 0 1px 1px rgba(255, 255, 255, .8) inset))
// au BufWritePost,FileWritePost *.sass :!sass --style expanded --line-numbers <afile> > "%:p:r.css"
// vim:tabstop=4:shiftwidth=4:softtabstop=4:fdm=marker:
@@ -420,6 +420,15 @@ instance.web_kanban.KanbanGroup = instance.web.OldWidget.extend({
self.quick.appendTo($(".oe_kanban_group_list_header", self.$records));
self.quick.focus();
});
// Add bounce effect on image '+' of kanban header when click on empty space of kanban grouped column.
var add_btn = this.$element.find('.oe_kanban_add');
this.$records.click(function (ev) {
if (ev.target == ev.currentTarget) {
if (!self.state.folded) {
add_btn.wrap('<div>').addClass('oe_bounce');
}
}
});
this.$records.find('.oe_kanban_show_more').click(this.do_show_more);
if (this.state.folded) {
this.do_toggle_fold();
@@ -13,7 +13,7 @@
<div t-name="KanbanView.buttons" class="oe_kanban_buttons">
<t t-if="widget.options.action_buttons !== false">
<t t-if="widget._is_create_enabled()">
<button type="button" class="oe_button oe_kanban_button_new oe_highlight oe_form_button_hi">
<button type="button" class="oe_kanban_button_new oe_highlight">
<t t-esc="widget.options.create_text || _t('Create')"/>
</button>
</t>
+8 -8
View File
@@ -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"
+6
View File
@@ -47,3 +47,9 @@ Undocumented stuff
* 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
+30 -19
View File
@@ -87,34 +87,37 @@ List view edition is an extension to the base listview providing the
capability of inline record edition by delegating to an embedded form
view.
.. todo::
Editability status
++++++++++++++++++
cleanup options and settings for editability configuration. Right
now there are:
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.
``defaults.editable``
The editability status is based on three flags:
``null``, ``"top"`` or ``"bottom"``, generally broken and
useless
``tree/@editable``
``context.set_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.
forces ``options.editable`` to ``"bottom"``
``context.set_editable``
``view.arch.attrs.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.
same as ``defaults.editable``, but applied separately (after
reloading the view), if absent delegates to
``options.editable`` which may have been set previously.
``defaults.editable``
``options.read_only``
Like ``tree/@editable``, one of absent (``null``)), ``"top"`` or
``"bottom"``, fallback for the list view if none of the previous
two flags are set.
force options.editable to false, or something?
.. note:: can probably be replaced by cancelling ``edit:before``
and :js:func:`~openerp.web.ListView.set_editable` which
ultimately behaves weird-as-fuck-ly.
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:
@@ -219,6 +222,14 @@ view provides a number of dedicated events to its lifecycle.
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.