diff --git a/addons/web/common/http.py b/addons/web/common/http.py
index 487800da1b9..cd17f5711e0 100644
--- a/addons/web/common/http.py
+++ b/addons/web/common/http.py
@@ -452,8 +452,8 @@ class Root(object):
static_dirs = self._load_addons(openerp_addons_namespace)
if options.serve_static:
- self.dispatch = werkzeug.wsgi.SharedDataMiddleware(
- self.dispatch, static_dirs)
+ self.dispatch = SuperSharedDataMiddleware(
+ self.dispatch, static_dirs, cache=False)
if options.session_storage:
if not os.path.exists(options.session_storage):
@@ -555,6 +555,75 @@ class Root(object):
return m
ps, _slash, meth = ps.rpartition('/')
return None
+
+class SuperSharedDataMiddleware(werkzeug.wsgi.SharedDataMiddleware):
+ """Redefine SharedDataMiddleware to better handle the cache = False directive.
+ Also desactivate 304 Not Modified headers only when the referer has 'debug' in its
+ arguments.
+ """
+ def __call__(self, environ, start_response):
+ import os
+ import mimetypes
+ import werkzeug.http
+ import urlparse
+ # sanitize the path for non unix systems
+ cleaned_path = environ.get('PATH_INFO', '').strip('/')
+ for sep in os.sep, os.altsep:
+ if sep and sep != '/':
+ cleaned_path = cleaned_path.replace(sep, '/')
+ path = '/'.join([''] + [x for x in cleaned_path.split('/')
+ if x and x != '..'])
+ file_loader = None
+ for search_path, loader in self.exports.iteritems():
+ if search_path == path:
+ real_filename, file_loader = loader(None)
+ if file_loader is not None:
+ break
+ if not search_path.endswith('/'):
+ search_path += '/'
+ if path.startswith(search_path):
+ real_filename, file_loader = loader(path[len(search_path):])
+ if file_loader is not None:
+ break
+ if file_loader is None or not self.is_allowed(real_filename):
+ return self.app(environ, start_response)
+
+ guessed_type = mimetypes.guess_type(real_filename)
+ mime_type = guessed_type[0] or self.fallback_mimetype
+ f, mtime, file_size = file_loader()
+
+ etag = self.generate_etag(mtime, file_size, real_filename)
+ modified = werkzeug.http.is_resource_modified(environ, etag, last_modified=mtime)
+
+ headers = [('Date', werkzeug.http.http_date())]
+ if self.cache:
+ timeout = self.cache_timeout
+ headers += [
+ ('Etag', '"%s"' % etag),
+ ('Cache-Control', 'max-age=%d, public' % timeout)
+ ]
+ if modified:
+ headers.append(('Expires', werkzeug.http.http_date(time() + timeout)))
+ else:
+ headers.append(('Cache-Control', 'no-cache'))
+
+ referer = environ.get('HTTP_REFERER', '')
+ parsed = urlparse.urlparse(referer)
+ debug = not urlparse.parse_qs(parsed.query).has_key('debug')
+ # it's important to put it at the end
+ if not debug and not modified:
+ f.close()
+ start_response('304 Not Modified', headers)
+ return []
+
+ headers.extend((
+ ('Content-Type', mime_type),
+ ('Content-Length', str(file_size)),
+ ('Last-Modified', werkzeug.http.http_date(mtime))
+ ))
+ start_response('200 OK', headers)
+ return werkzeug.wsgi.wrap_file(environ, f)
+
class LibException(Exception):
""" Base of all client lib exceptions """
diff --git a/addons/web/controllers/main.py b/addons/web/controllers/main.py
index 412ea9abda2..7f9710f8aa6 100644
--- a/addons/web/controllers/main.py
+++ b/addons/web/controllers/main.py
@@ -258,8 +258,7 @@ class WebClient(openerpweb.Controller):
file_map = dict(files)
rx_import = re.compile(r"""@import\s+('|")(?!'|"|/|https?://)""", re.U)
- rx_url = re.compile(r"""url\s*\(\s*('|"|)(?!'|"|/|https?://)""", re.U)
-
+ rx_url = re.compile(r"""url\s*\(\s*('|"|)(?!'|"|/|https?://|data:)""", re.U)
def reader(f):
"""read the a css file and absolutify all relative uris"""
@@ -1494,10 +1493,6 @@ class Binary(openerpweb.Controller):
class Action(openerpweb.Controller):
_cp_path = "/web/action"
-
- action_mapping = {
- "ir.actions.act_url": "ir.actions.url",
- }
# For most actions, the type attribute and the model name are the same, but
# there are exceptions. This dict is used to remap action type attributes
@@ -1511,6 +1506,17 @@ class Action(openerpweb.Controller):
Actions = req.session.model('ir.actions.actions')
value = False
context = req.session.eval_context(req.context)
+
+ try:
+ action_id = int(action_id)
+ except ValueError:
+ try:
+ module, xmlid = action_id.split('.', 1)
+ model, action_id = req.session.model('ir.model.data').get_object_reference(module, xmlid)
+ assert model.startswith('ir.actions.')
+ except Exception:
+ action_id = 0 # force failed read
+
base_action = Actions.read([action_id], ['type'], context)
if base_action:
ctx = {}
diff --git a/addons/web/static/lib/jquery.textext/jquery.textext.css b/addons/web/static/lib/jquery.textext/jquery.textext.css
index fe144e48af6..f180ee66184 100644
--- a/addons/web/static/lib/jquery.textext/jquery.textext.css
+++ b/addons/web/static/lib/jquery.textext/jquery.textext.css
@@ -65,10 +65,6 @@
padding: 3px 5px;
cursor: pointer;
}
-.text-core .text-wrap .text-dropdown .text-list .text-suggestion em {
- font-style: normal;
- text-decoration: underline;
-}
.text-core .text-wrap .text-dropdown .text-list .text-suggestion.text-selected {
color: #fff;
background: #6d84b4;
diff --git a/addons/web/static/src/css/base.css b/addons/web/static/src/css/base.css
index 1a7e30b5a84..c48ab0e3012 100644
--- a/addons/web/static/src/css/base.css
+++ b/addons/web/static/src/css/base.css
@@ -188,13 +188,7 @@
}
.openerp.ui-dialog {
display: none;
- position: fixed;
padding: 6px;
- top: 50%;
- left: 50%;
- z-index: 1050;
- width: 560px;
- margin: -150px 0 0 -280px;
background-color: rgba(60, 60, 60, 0.7);
border: 1px solid;
border-color: #888888 #555555 #444444;
@@ -208,6 +202,9 @@
-moz-background-clip: padding-box;
background-clip: padding-box;
}
+.openerp.ui-dialog .ui-dialog-content {
+ padding: 0px;
+}
.openerp.ui-dialog .ui-dialog-titlebar, .openerp.ui-dialog .ui-dialog-content, .openerp.ui-dialog .ui-dialog-buttonpane {
padding: 16px;
}
@@ -246,6 +243,9 @@
.openerp.ui-dialog .ui-dialog-buttonpane button {
margin-left: 8px;
}
+.openerp.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset {
+ float: left;
+}
.openerp.ui-dialog .ui-dialog-titlebar-close {
padding: 0;
}
@@ -268,6 +268,9 @@
color: black;
text-decoration: none;
}
+.openerp.ui-dialog.oe_act_window .ui-dialog-content {
+ padding: 0px;
+}
.openerp .modal-backdrop {
position: fixed;
top: 0;
@@ -308,6 +311,7 @@
}
.openerp .oe_fade {
color: #888888;
+ font-weight: normal;
}
.openerp .oe_bold {
font-weight: bold;
@@ -376,7 +380,8 @@
background: #ed6f6a;
}
.openerp .oe_title {
- width: 60%;
+ width: 50%;
+ float: left;
}
.openerp .oe_title:after {
content: ".";
@@ -386,17 +391,18 @@
visibility: hidden;
}
.openerp .oe_button_box {
- width: 38%;
+ width: 270px;
text-align: right;
}
.openerp .oe_button_box button {
margin: 4px;
}
.openerp .oe_avatar {
- margin: 0 16px 0 0;
+ margin: 0 6px 15px 0;
}
-.openerp .oe_avatar img {
- height: 50px;
+.openerp .oe_avatar > img {
+ height: 90px;
+ max-width: 100px;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
border-radius: 3px;
@@ -405,6 +411,9 @@
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
border: none;
}
+.openerp .oe_avatar + div {
+ margin-left: 5px;
+}
.openerp .oe_button.oe_link {
border: none;
padding: 0;
@@ -450,6 +459,29 @@
.openerp .oe_webclient .oe_star_on {
color: gold;
}
+.openerp .oe_tag {
+ border-radius: 2px;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ -ms-box-sizing: border-box;
+ box-sizing: border-box;
+ border: 1px solid #9daccc;
+ background: #e2e6f0;
+ color: black !important;
+ padding: 0px 3px 0px 3px;
+ margin: 0 2px 2px 0;
+ height: 16px;
+}
+.openerp .oe_tags .text-wrap {
+ width: 100% !important;
+}
+.openerp .oe_tags .text-wrap textarea {
+ width: 100% !important;
+}
+.openerp .oe_tags .text-core .text-wrap .text-dropdown .text-list .text-suggestion em {
+ font-style: italic;
+ text-decoration: none;
+}
.openerp.oe_tooltip {
font-size: 12px;
}
@@ -1136,63 +1168,63 @@
.openerp .oe_view_manager .oe_view_manager_view_kanban {
height: inherit;
}
-.openerp .oe_view_manager .oe_view_manager_header {
+.openerp .oe_view_manager table.oe_view_manager_header {
width: 100%;
+ table-layout: fixed;
}
-.openerp .oe_view_manager .oe_view_manager_header .oe_header_row {
+.openerp .oe_view_manager table.oe_view_manager_header .oe_header_row {
clear: both;
text-shadow: 0 1px 1px white;
}
-.openerp .oe_view_manager .oe_view_manager_header .oe_header_row:last-child td {
+.openerp .oe_view_manager table.oe_view_manager_header .oe_header_row:last-child td {
padding-top: 0;
}
-.openerp .oe_view_manager .oe_view_manager_header .oe_view_manager_sidebar {
+.openerp .oe_view_manager table.oe_view_manager_header .oe_view_manager_sidebar {
margin: 0px auto;
- width: 400px;
text-align: center;
}
-.openerp .oe_view_manager .oe_view_manager_header td {
+.openerp .oe_view_manager table.oe_view_manager_header td {
line-height: 26px;
}
-.openerp .oe_view_manager .oe_view_manager_header h2 {
+.openerp .oe_view_manager table.oe_view_manager_header h2 {
font-size: 18px;
margin: 0;
float: left;
}
-.openerp .oe_view_manager .oe_view_manager_header h2 a {
+.openerp .oe_view_manager table.oe_view_manager_header h2 a {
color: #8a89ba;
}
-.openerp .oe_view_manager .oe_view_manager_header .oe_button_group {
+.openerp .oe_view_manager table.oe_view_manager_header .oe_button_group {
display: inline-block;
border: 1px solid #ababab;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
border-radius: 5px;
}
-.openerp .oe_view_manager .oe_view_manager_header .oe_button_group li {
+.openerp .oe_view_manager table.oe_view_manager_header .oe_button_group li {
float: left;
border-right: 1px solid #ababab;
}
-.openerp .oe_view_manager .oe_view_manager_header .oe_button_group li:last-child {
+.openerp .oe_view_manager table.oe_view_manager_header .oe_button_group li:last-child {
border: none;
}
-.openerp .oe_view_manager .oe_view_manager_header .oe_button_group a {
+.openerp .oe_view_manager table.oe_view_manager_header .oe_button_group a {
color: #4c4c4c;
}
-.openerp .oe_view_manager .oe_view_manager_header .oe_button_group a:hover {
+.openerp .oe_view_manager table.oe_view_manager_header .oe_button_group a:hover {
text-decoration: none;
}
-.openerp .oe_view_manager .oe_view_manager_header .oe_button_group .active {
+.openerp .oe_view_manager table.oe_view_manager_header .oe_button_group .active {
background: #999999;
-moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3) inset;
-webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3) inset;
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3) inset;
}
-.openerp .oe_view_manager .oe_view_manager_header .oe_button_group .active a {
+.openerp .oe_view_manager table.oe_view_manager_header .oe_button_group .active a {
color: white;
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.4);
}
-.openerp .oe_view_manager .oe_view_manager_header .oe_view_manager_buttons {
+.openerp .oe_view_manager table.oe_view_manager_header .oe_view_manager_buttons {
white-space: nowrap;
}
.openerp .oe_view_manager .oe_view_manager_pager {
@@ -1319,7 +1351,7 @@
float: right;
padding: 1px 0;
line-height: 18px;
- width: 480px;
+ width: 400px;
border: 1px solid #ababab;
background: white;
-moz-border-radius: 13px;
@@ -1741,12 +1773,12 @@
width: auto;
}
.openerp .oe_form_nosheet {
- margin-left: 10px;
- margin-right: 10px;
+ margin: 20px;
}
.openerp .oe_form_nosheet > header {
- margin-left: -10px;
- margin-right: -10px;
+ margin-top: -20px;
+ margin-left: -20px;
+ margin-right: -20px;
}
.openerp .oe_form header {
position: relative;
@@ -1765,7 +1797,7 @@
display: inline-block;
float: right;
}
-.openerp .oe_form footer {
+.openerp .oe_form div.oe_chatter {
min-width: 650px;
max-width: 860px;
margin: 0 auto;
@@ -1817,18 +1849,19 @@
.openerp .oe_form .oe_subtotal_footer td.oe_form_group_cell_label {
border-right: none;
}
-.openerp .oe_form .oe_subtotal_footer .oe_form_field {
- width: auto !important;
-}
.openerp .oe_form .oe_subtotal_footer .oe_subtotal_footer_separator {
+ width: 108px;
border-top: 1px solid #cacaca;
- font-sie: 120%;
font-weight: bold;
+ font-size: 18px;
}
.openerp .oe_form .oe_subtotal_footer label.oe_subtotal_footer_separator {
font-weight: bold !important;
padding: 2px 8px 2px 0px !important;
}
+.openerp .oe_form .oe_subtotal_footer label.oe_form_label_help {
+ font-weight: normal;
+}
.openerp .oe_application .oe_form_sheetbg {
background: url(/web/static/src/img/form_sheetbg.png);
padding: 8px 0;
@@ -1854,6 +1887,9 @@
.openerp .oe_application .oe_form_sheet .oe_notebook_page {
padding: 0 16px;
}
+.openerp .oe_form .oe_form_button {
+ margin: 2px;
+}
.openerp .oe_form td.oe_form_group_cell_label {
border-right: 1px solid #dddddd;
padding: 2px 0px 2px 0px;
@@ -1861,17 +1897,17 @@
.openerp .oe_form td.oe_form_group_cell_label label {
line-height: 18px;
display: block;
- min-width: 110px;
+ min-width: 120px;
}
.openerp .oe_form td.oe_form_group_cell + .oe_form_group_cell {
padding-left: 6px;
}
.openerp .oe_form .oe_form_group {
width: 100%;
- margin: 4px 0 4px 0;
+ margin: 6px 0 6px 0;
}
-.openerp .oe_form .oe_form_group .oe_group_right > tbody > tr > td:first-child {
- padding-left: 18px;
+.openerp .oe_form .oe_form_group .oe_form_group_cell.oe_group_right {
+ padding-left: 20px;
}
.openerp .oe_form .oe_form_label_help[for], .openerp .oe_form .oe_form_label[for] {
font-weight: bold;
@@ -1941,15 +1977,6 @@
.openerp .oe_form .oe_form_field_text.oe_inline, .openerp .oe_form .oe_form_field_text.oe_inline > textarea {
width: 500px;
}
-.openerp .oe_form .oe_form_field_float input {
- width: 100px;
-}
-.openerp .oe_form h1 .oe_form_field_float input {
- width: 140px;
-}
-.openerp .oe_form h2 .oe_form_field_float input {
- width: 120px;
-}
.openerp .oe_form h1, .openerp .oe_form h2, .openerp .oe_form h3, .openerp .oe_form h4, .openerp .oe_form h5, .openerp .oe_form h6 {
margin: 0 0 4px 0;
}
@@ -1966,18 +1993,6 @@
.openerp .oe_form .oe_form_field input {
margin: 0px;
}
-.openerp .oe_form .oe_form_field_integer {
- width: 180px;
-}
-.openerp .oe_form .oe_form_field_float {
- width: 180px;
-}
-.openerp .oe_form .oe_form_field_date {
- width: 7.5em;
-}
-.openerp .oe_form .oe_form_field_datetime {
- width: 11em;
-}
.openerp .oe_form input[type="text"], .openerp .oe_form input[type="password"], .openerp .oe_form input[type="file"], .openerp .oe_form select {
height: 22px;
padding-top: 2px;
@@ -2017,32 +2032,6 @@
padding-top: 4px;
width: auto;
}
-.openerp .oe_form .oe_form_field_many2manytags .text-wrap {
- width: 100% !important;
-}
-.openerp .oe_form .oe_form_field_many2manytags .text-wrap textarea {
- width: 100% !important;
-}
-.openerp .oe_form .oe_form_field_many2manytags .oe_form_field_many2manytags_box {
- border-radius: 2px;
- -webkit-box-sizing: border-box;
- -moz-box-sizing: border-box;
- -ms-box-sizing: border-box;
- box-sizing: border-box;
- position: relative;
- float: left;
- border: 1px solid #9daccc;
- background: #e2e6f0;
- color: black;
- padding: 0px 3px 0px 3px;
- margin: 0 2px 2px 0;
- height: 16px;
- font: 11px "lucida grande", tahoma, verdana, arial, sans-serif;
-}
-.openerp .oe_form .oe_form_field_many2manytags .text-core .text-wrap .text-dropdown .text-list .text-suggestion em {
- font-style: italic;
- text-decoration: none;
-}
.openerp .oe_form .oe_datepicker_container {
display: none;
}
@@ -2096,6 +2085,18 @@
position: relative;
overflow: hidden;
}
+.openerp .oe_form_editable .oe_form .oe_form_field_integer {
+ width: 7em !important;
+}
+.openerp .oe_form_editable .oe_form .oe_form_field_float {
+ width: 8em !important;
+}
+.openerp .oe_form_editable .oe_form .oe_form_field_date {
+ width: 7.5em !important;
+}
+.openerp .oe_form_editable .oe_form .oe_form_field_datetime {
+ width: 11.5em !important;
+}
.openerp .oe_hidden_input_file {
overflow: hidden;
position: relative;
@@ -2125,6 +2126,7 @@
}
.openerp .oe_form .oe_form_field_image .oe_form_field_image_controls {
position: absolute;
+ white-space: nowrap;
top: 1px;
padding: 3px 0 0 0;
margin: 0 1px;
@@ -2152,27 +2154,33 @@
.openerp .oe_form .oe_form_field_one2many > .oe_view_manager .oe_list_pager_single_page {
display: none;
}
-.openerp .oe_form_field_one2many .oe_list .oe_list_edit_row_save {
+.openerp .oe_form_field_one2many .oe_list_content > thead, .openerp .oe_form_field_many2many .oe_list_content > thead {
+ border-bottom: 1px;
+}
+.openerp .oe_form_field_one2many .oe_list_content > tbody tr:nth-child(odd), .openerp .oe_form_field_many2many .oe_list_content > tbody tr:nth-child(odd) {
+ background: transparent;
+}
+.openerp .oe_form_field_one2many .oe_list .oe_list_edit_row_save, .openerp .oe_form_field_many2many .oe_list .oe_list_edit_row_save {
background: url(/web/static/src/img/iconset-b-remove.png) 50% 50% no-repeat;
}
-.openerp .oe_form_field_one2many .oe_list .oe_list_edit_row_save:before {
+.openerp .oe_form_field_one2many .oe_list .oe_list_edit_row_save:before, .openerp .oe_form_field_many2many .oe_list .oe_list_edit_row_save:before {
visibility: hidden;
}
-.openerp .oe_form_field_one2many > .oe_view_manager .oe_header_row_top {
+.openerp .oe_form_field_one2many > .oe_view_manager .oe_header_row_top, .openerp .oe_form_field_many2many > .oe_view_manager .oe_header_row_top {
display: none;
}
-.openerp .oe_form_field_one2many > .oe_view_manager .oe_view_manager_header2 td {
+.openerp .oe_form_field_one2many > .oe_view_manager .oe_view_manager_header2 td, .openerp .oe_form_field_many2many > .oe_view_manager .oe_view_manager_header2 td {
padding: 0px 8px;
line-height: 16px;
}
-.openerp .oe_form_field_one2many > .oe_view_manager .oe_view_manager_header2 td .oe_i {
+.openerp .oe_form_field_one2many > .oe_view_manager .oe_view_manager_header2 td .oe_i, .openerp .oe_form_field_many2many > .oe_view_manager .oe_view_manager_header2 td .oe_i {
font-size: 13px;
}
-.openerp .oe_form_field_one2many > .oe_view_manager .oe_view_manager_header2 td .oe_pager_group {
+.openerp .oe_form_field_one2many > .oe_view_manager .oe_view_manager_header2 td .oe_pager_group, .openerp .oe_form_field_many2many > .oe_view_manager .oe_view_manager_header2 td .oe_pager_group {
height: auto;
line-height: 16px;
}
-.openerp .oe_form_field_one2many > .oe_view_manager .oe_view_manager_header2 td .oe_pager_group li {
+.openerp .oe_form_field_one2many > .oe_view_manager .oe_view_manager_header2 td .oe_pager_group li, .openerp .oe_form_field_many2many > .oe_view_manager .oe_view_manager_header2 td .oe_pager_group li {
height: auto;
line-height: 16px;
}
@@ -2185,6 +2193,10 @@
.openerp .oe_list_content td:first-child:after, .openerp .oe_list_content th:first-child:after {
border-width: 0;
}
+.openerp .oe_list_content td.oe_number {
+ text-align: right !important;
+ max-width: 100px;
+}
.openerp .oe_list_content > thead {
border-bottom: 2px solid #cacaca;
background: #eeeeee;
@@ -2233,8 +2245,8 @@
.openerp .oe_list_content > tbody > tr > td.oe_list_field_cell {
padding: 3px 6px;
}
-.openerp .oe_list_content > tbody > tr > td, .openerp .oe_list_content > tbody > tr > th {
- line-height: 18px;
+.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;
@@ -2250,9 +2262,6 @@
.openerp .oe_list_content > tbody > tr > td.oe_list_checkbox:first-child:after, .openerp .oe_list_content > tbody > tr th.oe_list_checkbox:first-child:after {
border-width: 0;
}
-.openerp .oe_list_content > tbody > tr > td.oe_number {
- text-align: right !important;
-}
.openerp .oe_list_content > tbody > tr:nth-child(odd) {
background-color: #f0f0fa;
background-color: #f0f0fa;
@@ -2353,6 +2362,59 @@
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;
diff --git a/addons/web/static/src/css/base.sass b/addons/web/static/src/css/base.sass
index 559125aa3c3..8a2c510ec42 100644
--- a/addons/web/static/src/css/base.sass
+++ b/addons/web/static/src/css/base.sass
@@ -205,13 +205,7 @@ $sheet-max-width: 860px
// Modal box
&.ui-dialog
display: none
- position: fixed
padding: 6px
- top: 50%
- left: 50%
- z-index: 1050
- width: 560px
- margin: -150px 0 0 -280px
//overflow: hidden
background-color: rgba(60,60,60,0.7)
border: 1px solid
@@ -220,6 +214,8 @@ $sheet-max-width: 860px
@include radius(8px)
@include box-shadow(0 1px 12px rgba(0, 0, 0, 0.6))
@include background-clip()
+ .ui-dialog-content
+ padding: 0px
.ui-dialog-titlebar, .ui-dialog-content, .ui-dialog-buttonpane
padding: 16px
.ui-dialog-titlebar
@@ -241,6 +237,8 @@ $sheet-max-width: 860px
@include radius(0 0 2px 2px)
button
margin-left: 8px
+ .ui-dialog-buttonset
+ float: left
.ui-dialog-titlebar-close
padding: 0
.ui-icon-closethick
@@ -260,6 +258,10 @@ $sheet-max-width: 860px
color: black
text-decoration: none
+ &.ui-dialog.oe_act_window
+ .ui-dialog-content
+ padding: 0px
+
.modal-backdrop
position: fixed
top: 0
@@ -294,6 +296,7 @@ $sheet-max-width: 860px
cursor: wait
.oe_fade
color: #888
+ font-weight: normal
.oe_bold
font-weight: bold
.oe_inline
@@ -322,7 +325,8 @@ $sheet-max-width: 860px
&:hover
background: #ED6F6A
.oe_title
- width: 60%
+ width: 50%
+ float: left
.oe_title:after
content: "."
display: block
@@ -330,17 +334,20 @@ $sheet-max-width: 860px
clear: both
visibility: hidden
.oe_button_box
- width: 38%
+ width: 270px
text-align: right
button
margin: 4px
.oe_avatar
- margin: 0 16px 0 0
- img
- height: 50px
+ margin: 0 6px 15px 0
+ > img
+ height: 90px
+ max-width: 100px
@include radius(3px)
@include box-shadow(0 1px 3px rgba(0, 0, 0, 0.3))
border: none
+ .oe_avatar + div
+ margin-left: 5px
.oe_button.oe_link
@include reset()
img
@@ -362,8 +369,26 @@ $sheet-max-width: 860px
text-decoration: none
.oe_star_on
color: gold
-
- //.oe_edit_only
+ // }}}
+ // Tags (for many2many tags, among others) {{{
+ .oe_tag
+ border-radius: 2px
+ @include box-sizing(border)
+ border: 1px solid #9DACCC
+ background: #E2E6F0
+ color: black !important
+ padding: 0px 3px 0px 3px
+ margin: 0 2px 2px 0
+ height: 16px
+ // font: 11px "lucida grande", tahoma, verdana, arial, sans-serif
+ .oe_tags
+ .text-wrap
+ width: 100% !important
+ textarea
+ width: 100% !important
+ .text-core .text-wrap .text-dropdown .text-list .text-suggestion em
+ font-style: italic
+ text-decoration: none
// }}}
// Tooltips {{{
&.oe_tooltip
@@ -823,7 +848,7 @@ $sheet-max-width: 860px
text-shadow: 0 1px 1px rgba(0,0,0,0.2)
@include radius(4px)
@include box-shadow(inset 0 1px 1px rgba(0, 0, 0, 0.2))
- .oe_menu_counter
+ .oe_menu_counter
float: right
background: #8a89ba
color: #eee
@@ -846,7 +871,7 @@ $sheet-max-width: 860px
color: $colour4
text-shadow: 0 1px 1px white
@include box-shadow(0 1px 1px rgba(0, 0, 0, 0.2))
- .oe_menu_counter
+ .oe_menu_counter
background: #eee
color: #8a89ba
.oe_menu_toggler:before
@@ -888,8 +913,9 @@ $sheet-max-width: 860px
.oe_view_manager_view_kanban
height: inherit
- .oe_view_manager_header
+ table.oe_view_manager_header
width: 100%
+ table-layout: fixed
.oe_header_row
//min-height: 26px
//line-height: 26px
@@ -900,7 +926,6 @@ $sheet-max-width: 860px
padding-top: 0
.oe_view_manager_sidebar
margin: 0px auto
- width: 400px
text-align: center
td
line-height: 26px
@@ -1033,7 +1058,7 @@ $sheet-max-width: 860px
float: right
padding: 1px 0
line-height: 18px
- width: 480px
+ width: 400px
border: 1px solid #ababab
background: white
@include radius(13px)
@@ -1312,7 +1337,7 @@ $sheet-max-width: 860px
margin: 0 0 0 4px
padding: 0
-
+
// }}}
// Views Common {{{
.oe_view_nocontent
@@ -1356,25 +1381,25 @@ $sheet-max-width: 860px
display: none !important
.oe_form .oe_form_field_date
width: auto
- .oe_form_nosheet
- margin-left: 10px
- margin-right: 10px
+ .oe_form_nosheet
+ margin: 20px
.oe_form_nosheet > header
- margin-left: -10px
- margin-right: -10px
+ margin-top: -20px
+ margin-left: -20px
+ margin-right: -20px
// }}}
// FormView.custom tags and classes {{{
- .oe_form
+ .oe_form
header
position: relative
border-bottom: 1px solid #cacaca
@include vertical-gradient(#fcfcfc, #dedede)
padding: 0 8px
- line-height: 30px
+ line-height: 30px
ul
display: inline-block
float: right
- footer
+ div.oe_chatter
min-width: 650px
max-width: $sheet-max-width
margin: 0 auto
@@ -1387,12 +1412,12 @@ $sheet-max-width: 860px
vertical-align: top
margin-left: 8px
li
- border-right: none
+ border-right: none
padding: 0
margin: 0
- float: left
+ float: left
vertical-align: top
- height: 30px
+ height: 30px
padding: 0 0 0 12px
&:first-child
border-left: 1px solid #cacaca
@@ -1414,21 +1439,22 @@ $sheet-max-width: 860px
padding: 0 !important
td.oe_form_group_cell_label
border-right: none
- .oe_form_field
- width: auto !important
.oe_subtotal_footer_separator
+ width: 108px
border-top: 1px solid #cacaca
- font-sie: 120%
font-weight: bold
+ font-size: 18px
label.oe_subtotal_footer_separator
font-weight: bold !important
padding: 2px 8px 2px 0px !important
+ label.oe_form_label_help
+ font-weight: normal
// no sheet in popups
.oe_application
.oe_form_sheetbg
background: url(/web/static/src/img/form_sheetbg.png)
padding: 8px 0
- border-bottom: 1px solid #ddd
+ border-bottom: 1px solid #ddd
.oe_form_sheet_width
min-width: 650px
max-width: $sheet-max-width
@@ -1446,21 +1472,22 @@ $sheet-max-width: 860px
// }}}
// FormView.group {{{
.oe_form
+ .oe_form_button
+ margin: 2px
td.oe_form_group_cell_label
border-right: 1px solid #ddd
padding: 2px 0px 2px 0px
label
line-height: 18px
display: block
- min-width: 110px
+ min-width: 120px
td.oe_form_group_cell + .oe_form_group_cell
padding-left: 6px
.oe_form_group
width: 100%
- margin: 4px 0 4px 0
- .oe_group_right
- > tbody > tr > td:first-child
- padding-left: 18px
+ margin: 6px 0 6px 0
+ .oe_form_group_cell.oe_group_right
+ padding-left: 20px
// }}}
// FormView.label {{{
.oe_form
@@ -1521,12 +1548,6 @@ $sheet-max-width: 860px
width: 100%
.oe_form_field_text.oe_inline, .oe_form_field_text.oe_inline > textarea
width: 500px
- .oe_form_field_float input
- width: 100px
- h1 .oe_form_field_float input
- width: 140px
- h2 .oe_form_field_float input
- width: 120px
h1, h2, h3, h4, h5, h6
margin: 0 0 4px 0
input
@@ -1539,14 +1560,6 @@ $sheet-max-width: 860px
line-height: 18px
input
margin: 0px
- .oe_form_field_integer
- width: 180px
- .oe_form_field_float
- width: 180px
- .oe_form_field_date
- width: 7.5em
- .oe_form_field_datetime
- width: 11em
input[type="text"], input[type="password"], input[type="file"], select
height: 22px
padding-top: 2px
@@ -1572,26 +1585,6 @@ $sheet-max-width: 860px
.oe_form_field_boolean
padding-top: 4px
width: auto
- .oe_form_field_many2manytags
- .text-wrap
- width: 100% !important
- textarea
- width: 100% !important
- .oe_form_field_many2manytags_box
- border-radius: 2px
- @include box-sizing(border)
- position: relative
- float: left
- border: 1px solid #9DACCC
- background: #E2E6F0
- color: black
- padding: 0px 3px 0px 3px
- margin: 0 2px 2px 0
- height: 16px
- font: 11px "lucida grande", tahoma, verdana, arial, sans-serif
- .text-core .text-wrap .text-dropdown .text-list .text-suggestion em
- font-style: italic
- text-decoration: none
.oe_datepicker_container
display: none
.oe_datepicker_root
@@ -1636,6 +1629,16 @@ $sheet-max-width: 860px
> div
position: relative
overflow: hidden
+ .oe_form_editable
+ .oe_form
+ .oe_form_field_integer
+ width: 7em !important
+ .oe_form_field_float
+ width: 8em !important
+ .oe_form_field_date
+ width: 7.5em !important
+ .oe_form_field_datetime
+ width: 11.5em !important
// }}}
// FormView.fields_binary {{{
/* http://www.quirksmode.org/dom/inputfile.html
@@ -1669,6 +1672,7 @@ $sheet-max-width: 860px
vertical-align: top
.oe_form_field_image_controls
position: absolute
+ white-space: nowrap
top: 1px
padding: 3px 0 0 0
margin: 0 1px
@@ -1694,8 +1698,14 @@ $sheet-max-width: 860px
.oe_form .oe_form_field_one2many > .oe_view_manager
.oe_list_pager_single_page
display: none
- .oe_form_field_one2many
+ .oe_form_field_one2many,.oe_form_field_many2many
// TODO: oe_form_field_one2many_list?
+ .oe_list_content
+ > thead
+ border-bottom: 1px
+ > tbody
+ tr:nth-child(odd)
+ background: transparent
.oe_list .oe_list_edit_row_save
background: url(/web/static/src/img/iconset-b-remove.png) 50% 50% no-repeat
&:before
@@ -1728,6 +1738,9 @@ $sheet-max-width: 860px
td:first-child, th:first-child
&:after
border-width: 0
+ td.oe_number
+ text-align: right !important
+ max-width: 100px
> thead
border-bottom: 2px solid #cacaca
background: #eee
@@ -1763,8 +1776,9 @@ $sheet-max-width: 860px
border-top: 1px solid #ddd
> td.oe_list_field_cell
padding: 3px 6px
+ progress
+ width: 100%
> td, > th
- line-height: 18px
> button
border: none
background: transparent
@@ -1774,8 +1788,6 @@ $sheet-max-width: 860px
width: 17px
&:after
border-width: 0
- > td.oe_number
- text-align: right !important
> tr:nth-child(odd)
background-color: #f0f0fa
@include vertical-gradient(#f0f0fa, #eeeef6)
@@ -1853,6 +1865,49 @@ $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)
diff --git a/addons/web/static/src/js/chrome.js b/addons/web/static/src/js/chrome.js
index b87ebe56856..094e2f184e6 100644
--- a/addons/web/static/src/js/chrome.js
+++ b/addons/web/static/src/js/chrome.js
@@ -63,7 +63,7 @@ instance.web.Dialog = instance.web.Widget.extend({
this.dialog_options = {
modal: true,
destroy_on_close: true,
- width: $(window).width() * (($(window).width() > 1024) ? 0.5 : 0.75),
+ width: 900,
min_width: 0,
max_width: '95%',
height: 'auto',
@@ -145,9 +145,9 @@ instance.web.Dialog = instance.web.Widget.extend({
_.each(this.getChildren(), function(el) {
el.destroy();
});
- if (! this.isDestroyed()) {
- this.$element.dialog('destroy');
- }
+ if (! this.isDestroyed()) {
+ this.$element.dialog('destroy');
+ }
this._super();
}
});
@@ -212,11 +212,11 @@ instance.web.CrashManager = instance.web.CallbackEnabled.extend({
dialog.$element.html(QWeb.render('CrashManager.error', {session: instance.connection, error: error}));
},
on_javascript_exception: function(exception) {
- this.on_traceback({
- type: _t("Client Error"),
- message: exception,
- data: {debug: ""}
- });
+ this.on_traceback({
+ type: _t("Client Error"),
+ message: exception,
+ data: {debug: ""}
+ });
},
});
@@ -482,24 +482,26 @@ 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.$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.proxy('_db_list_loaded'));
- });
+ self.open_db_manager();
});
- return self.load_db_list().then(self.proxy('_db_list_loaded'));
+ return self.load_db_list().then(self.on_db_list_loaded);
},
load_db_list: function (force) {
var d = $.when(), self = this;
@@ -514,11 +516,14 @@ instance.web.Login = instance.web.Widget.extend({
}
return d;
},
- _db_list_loaded: function () {
- var list = this._db_list,
- dbdiv = this.$element.find('div.oe_login_dbpane');
+ on_db_list_loaded: function () {
+ var self = this;
+ var list = this._db_list;
+ 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 && list.length === 1) {
+ if(list.length === 0) {
+ self.open_db_manager();
+ } else if(list && list.length === 1) {
dbdiv.hide();
} else {
dbdiv.show();
@@ -667,7 +672,7 @@ instance.web.Menu = instance.web.Widget.extend({
* @param {Number} id the action_id to match
*/
open_action: function (id) {
- var $menu = this.$element.add(this.$secondary_menus).find('a[data-action-id=' + id + ']');
+ var $menu = this.$element.add(this.$secondary_menus).find('a[data-action-id="' + id + '"]');
var menu_id = $menu.data('menu');
if (menu_id) {
this.open_menu(menu_id);
@@ -822,8 +827,8 @@ instance.web.UserMenu = instance.web.Widget.extend({
{text: _t("Change password"), click: function(){ self.change_password(); }},
{text: _t("Cancel"), click: function(){ $(this).dialog('destroy'); }},
{text: _t("Save"), click: function(){
- var inner_viewmanager = action_manager.inner_viewmanager;
- inner_viewmanager.views[inner_viewmanager.active_view].controller.do_save()
+ var inner_widget = action_manager.inner_widget;
+ inner_widget.views[inner_widget.active_view].controller.do_save()
.then(function() {
self.dialog.destroy();
// needs to refresh interface in case language changed
@@ -894,11 +899,12 @@ instance.web.WebClient = instance.web.Widget.extend({
});
this.$element.on('click', '.oe_dropdown_toggle', function(ev) {
ev.preventDefault();
- var $menu = $(this).find('.oe_dropdown_menu');
+ var $toggle = $(this);
+ var $menu = $toggle.find('.oe_dropdown_menu');
var state = $menu.is('.oe_opened');
setTimeout(function() {
// Do not alter propagation
- $menu.toggleClass('oe_opened', !state);
+ $toggle.add($menu).toggleClass('oe_opened', !state);
if (!state) {
// Move $menu if outside window's edge
var doc_width = $(document).width();
@@ -1036,6 +1042,7 @@ instance.web.WebClient = instance.web.Widget.extend({
if (options.needaction) {
action.context.search_default_needaction_pending = true;
}
+ self.action_manager.clear_breadcrumbs();
self.action_manager.do_action(action);
});
},
diff --git a/addons/web/static/src/js/coresetup.js b/addons/web/static/src/js/coresetup.js
index a00ca4002e5..a5a62b9bcc1 100644
--- a/addons/web/static/src/js/coresetup.js
+++ b/addons/web/static/src/js/coresetup.js
@@ -404,10 +404,11 @@ instance.web.Session = instance.web.JsonRPC.extend( /** @lends instance.web.Sess
}
});
+
/**
* Event Bus used to bind events scoped in the current instance
*/
-instance.web.bus = new (instance.web.Class.extend(instance.web.EventDispatcherMixin, {
+instance.web.Bus = instance.web.Class.extend(instance.web.EventDispatcherMixin, {
init: function() {
instance.web.EventDispatcherMixin.init.call(this, parent);
var self = this;
@@ -425,7 +426,8 @@ instance.web.bus = new (instance.web.Class.extend(instance.web.EventDispatcherMi
});
});
}
-}))();
+})
+instance.web.bus = new instance.web.Bus();
/** OpenERP Translations */
instance.web.TranslationDataBase = instance.web.Class.extend(/** @lends instance.web.TranslationDataBase# */{
diff --git a/addons/web/static/src/js/view_editor.js b/addons/web/static/src/js/view_editor.js
index 8733a191b21..6df78679ecb 100644
--- a/addons/web/static/src/js/view_editor.js
+++ b/addons/web/static/src/js/view_editor.js
@@ -53,7 +53,7 @@ instance.web.ViewEditor = instance.web.OldWidget.extend({
this.main_view_id = this.parent.fields_view.view_id;
this.action_manager = new instance.web.ActionManager(this);
$.when(this.action_manager.do_action(action)).then(function() {
- var viewmanager = self.action_manager.inner_viewmanager,
+ var viewmanager = self.action_manager.inner_widget,
controller = viewmanager.views[viewmanager.active_view].controller;
self.action_manager.appendTo(self.view_edit_dialog.$element);
self.action_manager.renderElement(self.view_edit_dialog);
@@ -88,7 +88,7 @@ instance.web.ViewEditor = instance.web.OldWidget.extend({
} else {
$.when(self.do_save_view(view_values)).then(function() {
self.create_view_dialog.close();
- var controller = self.action_manager.inner_viewmanager.views[self.action_manager.inner_viewmanager.active_view].controller;
+ var controller = self.action_manager.inner_widget.views[self.action_manager.inner_widget.active_view].controller;
controller.reload_content();
});
}
@@ -167,7 +167,7 @@ instance.web.ViewEditor = instance.web.OldWidget.extend({
do_delete_view: function() {
var self = this;
if (confirm(_t("Do you really want to remove this view?"))) {
- var controller = this.action_manager.inner_viewmanager.views[this.action_manager.inner_viewmanager.active_view].controller;
+ var controller = this.action_manager.inner_widget.views[this.action_manager.inner_widget.active_view].controller;
this.dataset.unlink([this.main_view_id]).then(function() {
controller.reload_content();
self.main_view_id = self.parent.fields_view.view_id;
@@ -397,7 +397,7 @@ instance.web.ViewEditor = instance.web.OldWidget.extend({
action_manager.do_action(action);
}},
{text: _t("Close"), click: function(){
- self.action_manager.inner_viewmanager.views[self.action_manager.inner_viewmanager.active_view].controller.reload_content();
+ self.action_manager.inner_widget.views[self.action_manager.inner_widget.active_view].controller.reload_content();
self.edit_xml_dialog.close();
}}
]
@@ -998,7 +998,7 @@ instance.web.ViewEditor = instance.web.OldWidget.extend({
};
var action_manager = new instance.web.ActionManager(self);
$.when(action_manager.do_action(action)).then(function() {
- var controller = action_manager.dialog_viewmanager.views['form'].controller;
+ var controller = action_manager.dialog_widget.views['form'].controller;
controller.on_button_cancel.add_last(function(){
action_manager.destroy()
});
diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js
index d629b8e9b3d..3f389d3d41f 100644
--- a/addons/web/static/src/js/view_form.js
+++ b/addons/web/static/src/js/view_form.js
@@ -9,7 +9,7 @@ instance.web.form = {};
/**
* Interface implemented by the form view or any other object
* able to provide the features necessary for the fields to work.
- *
+ *
* Properties:
* - display_invalid_fields : if true, all fields where is_valid() return true should
* be displayed as invalid.
@@ -287,10 +287,12 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
on_record_loaded: function(record) {
var self = this, set_values = [];
if (!record) {
+ this.set({ 'title' : undefined });
this.do_warn("Form", "The record could not be found in the database.", true);
return $.Deferred().reject();
}
this.datarecord = record;
+ this.set({ 'title' : record.id ? record.name : "New record" });
if (this.qweb) {
this.kill_current_form();
@@ -524,7 +526,7 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
this.on_form_changed();
}
if (!_.isEmpty(result.warning)) {
- instance.web.dialog($(QWeb.render("CrashManager.warning", result.warning)), {
+ instance.web.dialog($(QWeb.render("CrashManager.warning", result.warning)), {
title:result.warning.title,
modal: true,
buttons: [
@@ -800,13 +802,13 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
});
},
get_fields_values: function(blacklist) {
- blacklist = blacklist || [];
+ blacklist = blacklist || [];
var values = {};
var ids = this.get_selected_ids();
values["id"] = ids.length > 0 ? ids[0] : false;
_.each(this.fields, function(value_, key) {
- if (_.include(blacklist, key))
- return;
+ if (_.include(blacklist, key))
+ return;
var val = value_.get_value();
values[key] = val;
});
@@ -953,7 +955,7 @@ instance.web.form.FormRenderingEngineInterface = instance.web.Class.extend({
/**
* Default rendering engine for the form view.
- *
+ *
* It is necessary to set the view using set_view() before usage.
*/
instance.web.form.FormRenderingEngine = instance.web.form.FormRenderingEngineInterface.extend({
@@ -1184,8 +1186,7 @@ instance.web.form.FormRenderingEngine = instance.web.form.FormRenderingEngineInt
row_cols = cols;
} else if (tagName==='group') {
// When , we need a spacing between the two groups
- $child.addClass('oe_group_right')
-
+ $td.addClass('oe_group_right')
}
row_cols -= colspan;
@@ -1211,12 +1212,6 @@ instance.web.form.FormRenderingEngine = instance.web.form.FormRenderingEngineInt
$child = $td.children(':first');
switch ($child[0].tagName.toLowerCase()) {
case 'separator':
- if ($child.attr('orientation') === 'vertical') {
- $td.addClass('oe_vertical_separator').attr('width', '1');
- $td.empty();
- row_cols-= $td.attr('colspan') || 1;
- total--;
- }
break;
case 'label':
if ($child.attr('for')) {
@@ -1276,7 +1271,7 @@ instance.web.form.FormRenderingEngine = instance.web.form.FormRenderingEngineInt
page_attrs.__page = $new_page;
page_attrs.__ic = ic;
pages.push(page_attrs);
-
+
$new_page.children().each(function() {
self.process($(this));
});
@@ -1302,7 +1297,7 @@ instance.web.form.FormRenderingEngine = instance.web.form.FormRenderingEngineInt
}
});
});
-
+
this.handle_common_properties($new_notebook, $notebook);
return $new_notebook;
},
@@ -1585,7 +1580,7 @@ instance.web.form.FormWidget = instance.web.Widget.extend(instance.web.form.Invi
parent: {}
});
if (a_dataset.parent_view) {
- fields_values.parent = a_dataset.parent_view.get_fields_values([a_dataset.child_name]);
+ fields_values.parent = a_dataset.parent_view.get_fields_values([a_dataset.child_name]);
}
return fields_values;
},
@@ -1603,7 +1598,7 @@ instance.web.form.FormWidget = instance.web.Widget.extend(instance.web.form.Invi
if (! v_context) {
v_context = (this.field || {}).context || {};
}
-
+
if (v_context.__ref || true) { //TODO: remove true
var fields_values = this._build_eval_context(blacklist);
v_context = new instance.web.CompoundContext(v_context).set_eval_context(fields_values);
@@ -1711,14 +1706,14 @@ instance.web.form.WidgetButton = instance.web.form.FormWidget.extend({
/**
* Interface to be implemented by fields.
- *
+ *
* Properties:
* - readonly: boolean. If set to true the field should appear in readonly mode.
* - force_readonly: boolean, When it is true, the field should always appear
* in read only mode, no matter what the value of the "readonly" property can be.
* Events:
* - changed_value: triggered to inform the view to check on_changes
- *
+ *
*/
instance.web.form.FieldInterface = {
/**
@@ -1729,14 +1724,14 @@ instance.web.form.FieldInterface = {
init: function(field_manager, node) {},
/**
* Called by the form view to indicate the value of the field.
- *
+ *
* set_value() may return an object that can be passed to $.when() that represents the moment when
* the field has finished all operations necessary before the user can effectively use the widget.
- *
+ *
* Multiple calls to set_value() can occur at any time and must be handled correctly by the implementation,
* regardless of any asynchronous operation currently running and the status of any promise that a
* previous call to set_value() could have returned.
- *
+ *
* set_value() must be able, at any moment, to handle the syntax returned by the "read" method of the
* osv class in the OpenERP server as well as the syntax used by the set_value() (see below). It must
* also be able to handle any other format commonly used in the _defaults key on the models in the addons
@@ -1746,16 +1741,16 @@ instance.web.form.FieldInterface = {
set_value: function(value_) {},
/**
* Get the current value of the widget.
- *
+ *
* Must always return a syntaxically correct value to be passed to the "write" method of the osv class in
* the OpenERP server, although it is not assumed to respect the constraints applied to the field.
* For example if the field is marqued as "required", a call to get_value() can return false.
- *
+ *
* get_value() can also be called *before* a call to set_value() and, in that case, is supposed to
* return a defaut value according to the type of field.
- *
+ *
* This method is always assumed to perform synchronously, it can not return a promise.
- *
+ *
* If there was no user interaction to modify the value of the field, it is always assumed that
* get_value() return the same semantic value than the one passed in the last call to set_value(),
* altough the syntax can be different. This can be the case for type of fields that have a different
@@ -1785,14 +1780,14 @@ instance.web.form.FieldInterface = {
/**
* Abstract class for classes implementing FieldInterface.
- *
+ *
* Properties:
* - effective_readonly: when it is true, the widget is displayed as readonly. Vary depending
* the values of the "readonly" property and the "force_readonly" property on the field manager.
* - value: useful property to hold the value of the field. By default, set_value() and get_value()
* set and retrieve the value property. Changing the value property also triggers automatically
* a 'changed_value' event that inform the view to trigger on_changes.
- *
+ *
*/
instance.web.form.AbstractField = instance.web.form.FormWidget.extend(instance.web.form.FieldInterface, {
/**
@@ -1811,7 +1806,7 @@ instance.web.form.AbstractField = instance.web.form.FormWidget.extend(instance.w
this.string = this.node.attrs.string || this.field.string || this.name;
this.set({'value': false});
this.set({required: this.modifiers['required'] === true});
-
+
// some events to make the property "effective_readonly" sync automatically with "readonly" and
// "force_readonly"
this.set({"readonly": this.modifiers['readonly'] === true});
@@ -1821,7 +1816,7 @@ instance.web.form.AbstractField = instance.web.form.FormWidget.extend(instance.w
this.on("change:readonly", this, test_effective_readonly);
this.on("change:force_readonly", this, test_effective_readonly);
_.bind(test_effective_readonly, this)();
-
+
this.on("change:value", this, function() {
if (! this._inhibit_on_change)
this.trigger('changed_value');
@@ -2003,7 +1998,7 @@ instance.web.form.FieldChar = instance.web.form.AbstractField.extend(instance.we
});
instance.web.form.FieldID = instance.web.form.FieldChar.extend({
-
+
});
instance.web.form.FieldEmail = instance.web.form.FieldChar.extend({
@@ -2396,7 +2391,7 @@ instance.web.form.FieldSelection = instance.web.form.AbstractField.extend(instan
} else {
var self = this;
var option = _(this.values)
- .detect(function (record) { return record[0] === self.get('value'); });
+ .detect(function (record) { return record[0] === self.get('value'); });
this.$element.text(option ? option[1] : this.values[0][1]);
}
},
@@ -2575,7 +2570,7 @@ instance.web.form.FieldMany2One = instance.web.form.AbstractField.extend(instanc
render_editable: function() {
var self = this;
this.$input = this.$element.find("input");
-
+
self.$input.tipsy({
title: function() {
return "No element was selected, you should create or select one from the dropdown list.";
@@ -2583,10 +2578,10 @@ instance.web.form.FieldMany2One = instance.web.form.AbstractField.extend(instanc
trigger:'manual',
fade: true,
});
-
+
this.$drop_down = this.$element.find(".oe_m2o_drop_down_button");
this.$follow_button = $(".oe_m2o_cm_button", this.$element);
-
+
this.$follow_button.click(function() {
if (!self.get('value')) {
self.focus();
@@ -2880,7 +2875,7 @@ instance.web.form.FieldOne2Many = instance.web.form.AbstractField.extend({
},
load_views: function() {
var self = this;
-
+
var modes = this.node.attrs.mode;
modes = !!modes ? modes.split(",") : ["tree"];
var views = [];
@@ -3082,30 +3077,30 @@ instance.web.form.FieldOne2Many = instance.web.form.AbstractField.extend({
save_any_view: function() {
if (this.doing_on_change)
return false;
- return this.session.synchronized_mode(_.bind(function() {
- if (this.viewmanager && this.viewmanager.views && this.viewmanager.active_view &&
- this.viewmanager.views[this.viewmanager.active_view] &&
- this.viewmanager.views[this.viewmanager.active_view].controller) {
- var view = this.viewmanager.views[this.viewmanager.active_view].controller;
- if (this.viewmanager.active_view === "form") {
- if (!view.is_initialized.isResolved()) {
- return false;
- }
- var res = $.when(view.do_save());
- if (!res.isResolved() && !res.isRejected()) {
- console.warn("Asynchronous get_value() is not supported in form view.");
- }
- return res;
- } else if (this.viewmanager.active_view === "list") {
- var res = $.when(view.ensure_saved());
- if (!res.isResolved() && !res.isRejected()) {
- console.warn("Asynchronous get_value() is not supported in list view.");
- }
- return res;
- }
- }
- return false;
- }, this));
+ return this.session.synchronized_mode(_.bind(function() {
+ if (this.viewmanager && this.viewmanager.views && this.viewmanager.active_view &&
+ this.viewmanager.views[this.viewmanager.active_view] &&
+ this.viewmanager.views[this.viewmanager.active_view].controller) {
+ var view = this.viewmanager.views[this.viewmanager.active_view].controller;
+ if (this.viewmanager.active_view === "form") {
+ if (!view.is_initialized.isResolved()) {
+ return false;
+ }
+ var res = $.when(view.do_save());
+ if (!res.isResolved() && !res.isRejected()) {
+ console.warn("Asynchronous get_value() is not supported in form view.");
+ }
+ return res;
+ } else if (this.viewmanager.active_view === "list") {
+ var res = $.when(view.ensure_saved());
+ if (!res.isResolved() && !res.isRejected()) {
+ console.warn("Asynchronous get_value() is not supported in list view.");
+ }
+ return res;
+ }
+ }
+ return false;
+ }, this));
},
is_syntax_valid: function() {
if (!this.viewmanager.views[this.viewmanager.active_view])
@@ -3462,7 +3457,7 @@ instance.web.form.FieldMany2ManyTags = instance.web.form.AbstractField.extend(in
$("textarea", self.$element).css("padding-left", "3px");
self.tags.addTags(_.map(data, function(el) {return {name: el[1], id:el[0]};}));
} else {
- self.$element.html(QWeb.render("FieldMany2ManyTags.box", {elements: data}));
+ self.$element.html(QWeb.render("FieldMany2ManyTag", {elements: data}));
}
};
if (! self.get('values') || self.get('values').length > 0) {
@@ -3634,7 +3629,7 @@ instance.web.form.FieldMany2ManyKanban = instance.web.form.AbstractField.extend(
this.dataset.on_unlink.add_last(function(ids) {
self.dataset_changed();
});
-
+
this.is_setted.then(function() {
self.load_view();
});
@@ -3750,7 +3745,7 @@ instance.web.form.Many2ManyKanbanView = instance.web_kanban.KanbanView.extend({
});
instance.web.form.Many2ManyQuickCreate = instance.web.Widget.extend({
template: 'Many2ManyKanban.quick_create',
-
+
/**
* close_btn: If true, the widget will display a "Close" button able to trigger
* a "close" event.
@@ -3866,8 +3861,8 @@ instance.web.form.AbstractFormPopup = instance.web.OldWidget.extend({
var self = this;
this.renderElement();
new instance.web.Dialog(this, {
- width: '90%',
min_width: '800px',
+ dialogClass: 'oe_act_window',
close: function() {
self.check_exit(true);
},
@@ -4443,7 +4438,7 @@ instance.web.form.FieldStatus = instance.web.form.AbstractField.extend({
this.selection = [];
// get fold information from widget
var fold = ((this.node.attrs || {}).statusbar_fold || true);
- // build final domain: if fold option required, add the
+ // build final domain: if fold option required, add the
if (fold == true) {
var domain = new instance.web.CompoundDomain(['|'], ['&'], self.build_domain(), [['fold', '=', false]], [['id', '=', self.selected_value]]);
} else {
@@ -4475,7 +4470,7 @@ instance.web.form.FieldStatus = instance.web.form.AbstractField.extend({
var shown = _.map(((this.node.attrs || {}).statusbar_visible || "").split(","),
function(x) { return _.str.trim(x); });
shown = _.select(shown, function(x) { return x.length > 0; });
-
+
if (shown.length == 0) {
this.to_show = this.selection;
} else {
diff --git a/addons/web/static/src/js/view_list.js b/addons/web/static/src/js/view_list.js
index 3033404b387..edc53f82042 100644
--- a/addons/web/static/src/js/view_list.js
+++ b/addons/web/static/src/js/view_list.js
@@ -1045,7 +1045,7 @@ instance.web.ListView.List = instance.web.Class.extend( /** @lends instance.web.
render_cell: function () {
return self.render_cell.apply(self, arguments); }
}, this)));
- this.pad_table_to(5);
+ this.pad_table_to(4);
},
pad_table_to: function (count) {
if (this.records.length >= count ||
diff --git a/addons/web/static/src/js/view_tree.js b/addons/web/static/src/js/view_tree.js
index e8bd7351f1f..2181b2aa157 100644
--- a/addons/web/static/src/js/view_tree.js
+++ b/addons/web/static/src/js/view_tree.js
@@ -63,6 +63,12 @@ instance.web.TreeView = instance.web.View.extend(/** @lends instance.web.TreeVie
}
return fields;
},
+ store_record:function(records){
+ var self = this;
+ _(records).each(function (record) {
+ self.records[record.id] = record;
+ });
+ },
on_loaded: function (fields_view) {
var self = this;
var has_toolbar = !!fields_view.arch.attrs.toolbar;
@@ -87,17 +93,19 @@ instance.web.TreeView = instance.web.View.extend(/** @lends instance.web.TreeVie
this.$element.addClass(this.fields_view.arch.attrs['class']);
this.dataset.read_slice(this.fields_list()).then(function(records) {
+ self.store_record(records);
if (!has_toolbar) {
// WARNING: will do a second read on the same ids, but only on
// first load so not very important
- self.getdata(null, _(records).pluck('id'));
+ self.render_data({'null':records})
+ self.getdata(_.pluck(records,"id"));
return;
}
var $select = self.$element.find('select')
.change(function () {
var $option = $(this).find(':selected');
- self.getdata($option.val(), $option.data('children'));
+ self.getdata($option.val());
});
_(records).each(function (record) {
self.records[record.id] = record;
@@ -112,7 +120,12 @@ instance.web.TreeView = instance.web.View.extend(/** @lends instance.web.TreeVie
$select.change();
}
});
-
+ this.$element.find("#tree_view_expand").click(function(){
+ self.expand_all();
+ });
+ this.$element.find("#tree_view_collapse").click(function(){
+ self.collpase_all();
+ });
// TODO store open nodes in url ?...
this.do_push_state({});
@@ -128,6 +141,22 @@ instance.web.TreeView = instance.web.View.extend(/** @lends instance.web.TreeVie
return [color, py.parse(py.tokenize(expr)), expr];
}).value();
},
+ expand_all: function(){
+ var self = this;
+ var tr = this.$element.find(".oe-treeview-table tbody tr[id^='treerow_']");
+ _.each(tr,function(rec){
+ self.showcontent($(rec).attr('data-id'),true);
+ });
+ },
+ collpase_all: function(){
+ var self = this;
+ var root_tr = this.$element.find(".oe-treeview-table tbody tr[data-level='"+1+"']");
+ _.each(root_tr,function(rec){
+ if($(rec).hasClass('oe_open')){
+ self.showcontent($(rec).attr('data-id'),false);
+ }
+ });
+ },
/**
* Returns the color for the provided record in the current view (from the
* ``@colors`` attribute)
@@ -164,50 +193,44 @@ instance.web.TreeView = instance.web.View.extend(/** @lends instance.web.TreeVie
});
this.$element.delegate('.treeview-tr', 'click', function () {
- var is_loaded = 0,
- $this = $(this),
+ var $this = $(this),
record_id = $this.data('id'),
- record = self.records[record_id],
- children_ids = record[self.children_field];
-
- _(children_ids).each(function(childid) {
- if (self.$element.find('#treerow_' + childid).length) {
- if (self.$element.find('#treerow_' + childid).is(':hidden')) {
- is_loaded = -1;
- } else {
- is_loaded++;
- }
- }
- });
- if (is_loaded === 0) {
- if (!$this.parent().hasClass('oe_open')) {
- self.getdata(record_id, children_ids);
- }
- } else {
- self.showcontent(record_id, is_loaded < 0);
- }
+ bool = $this.parent().hasClass('oe_open');
+ self.showcontent(record_id, !bool);
});
},
// get child data of selected value
- getdata: function (id, children_ids) {
+ getdata: function (id) {
var self = this;
-
- self.dataset.read_ids(children_ids, this.fields_list()).then(function(records) {
- _(records).each(function (record) {
- self.records[record.id] = record;
- });
-
- var $curr_node = self.$element.find('#treerow_' + id);
+ var parent_child ={};
+ id = _.isArray(id)?id:parseInt(id);
+ var ir_model_data = new instance.web.Model(this.model,self.dataset.get_context() || {},[['id','child_of',id]]).query();
+ ir_model_data._execute().then(function(records){
+ self.store_record(records);
+ _.each(records,function(rec){
+ if(rec[self.children_field].length === 0)return;
+ parent_child[rec.id] = [];
+ _.each(rec[self.children_field],function(key){
+ parent_child[rec.id].push(self.records[key]);
+ });
+ })
+ self.render_data(parent_child);
+ });
+ },
+ render_data: function(groupby){
+ var self = this;
+ _.each(_.keys(groupby),function(key){
+ var $curr_node = self.$element.find('#treerow_' + key);
+ var record = groupby[key];
var children_rows = QWeb.render('TreeView.rows', {
- 'records': records,
+ 'records': record,
'children_field': self.children_field,
'fields_view': self.fields_view.arch.children,
'fields': self.fields,
- 'level': $curr_node.data('level') || 0,
+ 'level': ($curr_node.data('level') || 0) + 1,
'render': instance.web.format_value,
'color_for': self.color_for
});
-
if ($curr_node.length) {
$curr_node.addClass('oe_open');
$curr_node.after(children_rows);
@@ -215,8 +238,10 @@ instance.web.TreeView = instance.web.View.extend(/** @lends instance.web.TreeVie
self.$element.find('tbody').html(children_rows);
}
});
+ self.collpase_all();
},
+
// Get details in listview
activate: function(id) {
var self = this;
@@ -259,13 +284,5 @@ instance.web.TreeView = instance.web.View.extend(/** @lends instance.web.TreeVie
}, this);
},
- do_show: function () {
- this.$element.show();
- },
-
- do_hide: function () {
- this.$element.hide();
- this.hidden = true;
- }
});
};
diff --git a/addons/web/static/src/js/views.js b/addons/web/static/src/js/views.js
index 6586807264d..bd102d867de 100644
--- a/addons/web/static/src/js/views.js
+++ b/addons/web/static/src/js/views.js
@@ -10,28 +10,111 @@ instance.web.ActionManager = instance.web.Widget.extend({
init: function(parent) {
this._super(parent);
this.inner_action = null;
- this.inner_viewmanager = null;
+ this.inner_widget = null;
this.dialog = null;
- this.dialog_viewmanager = null;
- this.client_widget = null;
+ this.dialog_widget = null;
+ this.breadcrumbs = [];
+ },
+ start: function() {
+ this._super.apply(this, arguments);
+ this.$element.on('click', '.oe_breadcrumb_item', this.on_breadcrumb_clicked);
},
dialog_stop: function () {
if (this.dialog) {
- this.dialog_viewmanager.destroy();
- this.dialog_viewmanager = null;
+ this.dialog_widget.destroy();
+ this.dialog_widget = null;
this.dialog.destroy();
this.dialog = null;
}
},
- content_stop: function () {
- if (this.inner_viewmanager) {
- this.inner_viewmanager.destroy();
- this.inner_viewmanager = null;
+ /**
+ * Add a new item to the breadcrumb
+ *
+ * If the title of an item is an array, the multiple title mode is in use.
+ * (eg: a widget with multiple views might need to display a title for each view)
+ * In multiple title mode, the show() callback can check the index it receives
+ * in order to detect which of its titles has been clicked on by the user.
+ *
+ * @param {Object} item breadcrumb item
+ * @param {Object} item.widget widget containing the view(s) to be added to the breadcrumb added
+ * @param {Function} [item.show] triggered whenever the widget should be shown back
+ * @param {Function} [item.hide] triggered whenever the widget should be shown hidden
+ * @param {Function} [item.destroy] triggered whenever the widget should be destroyed
+ * @param {String|Array} [item.title] title(s) of the view(s) to be displayed in the breadcrumb
+ * @param {Function} [item.get_title] should return the title(s) of the view(s) to be displayed in the breadcrumb
+ */
+ push_breadcrumb: function(item) {
+ var last = this.breadcrumbs.slice(-1)[0];
+ if (last) {
+ last.hide();
}
- if (this.client_widget) {
- this.client_widget.destroy();
- this.client_widget = null;
+ var item = _.extend({
+ show: function(index) {
+ this.widget.$element.show();
+ },
+ hide: function() {
+ this.widget.$element.hide();
+ },
+ destroy: function() {
+ this.widget.destroy();
+ },
+ get_title: function() {
+ return this.title || this.widget.get('title');
+ }
+ }, item);
+ item.id = _.uniqueId('breadcrumb_');
+ this.breadcrumbs.push(item);
+ },
+ on_breadcrumb_clicked: function(ev) {
+ var $e = $(ev.target);
+ var id = $e.data('id');
+ var item;
+ for (var i = this.breadcrumbs.length - 1; i >= 0; i--) {
+ var it = this.breadcrumbs[i];
+ if (it.id == id) {
+ item = it;
+ break;
+ }
+ this.remove_breadcrumb(i);
}
+ var index = $e.parent().find('.oe_breadcrumb_item[data-id=' + $e.data('id') + ']').index($e);
+ item.show(index, $e);
+ this.inner_widget = item.widget;
+ },
+ clear_breadcrumbs: function() {
+ while (this.breadcrumbs.length) {
+ this.remove_breadcrumb(0);
+ }
+ },
+ remove_breadcrumb: function(index) {
+ var item = this.breadcrumbs.splice(index, 1)[0];
+ if (item) {
+ var dups = _.filter(this.breadcrumbs, function(it) {
+ return item.widget === it.widget;
+ });
+ if (!dups.length) {
+ item.destroy();
+ }
+ }
+ },
+ get_title: function() {
+ var titles = [];
+ for (var i = 0; i < this.breadcrumbs.length; i += 1) {
+ var item = this.breadcrumbs[i];
+ var tit = item.get_title();
+ if (!_.isArray(tit)) {
+ tit = [tit];
+ }
+ for (var j = 0; j < tit.length; j += 1) {
+ var label = _.escape(tit[j]);
+ if (i === this.breadcrumbs.length - 1 && j === tit.length - 1) {
+ titles.push(label);
+ } else {
+ titles.push(_.str.sprintf('%s', item.id, label));
+ }
+ }
+ }
+ return titles.join(' / ');
},
do_push_state: function(state) {
if (this.getParent() && this.getParent().do_push_state) {
@@ -49,7 +132,7 @@ instance.web.ActionManager = instance.web.Widget.extend({
var self = this,
action_loaded;
if (state.action_id) {
- var run_action = (!this.inner_viewmanager) || this.inner_viewmanager.action.id !== state.action_id;
+ var run_action = (!this.inner_widget || !this.inner_widget.action) || this.inner_widget.action.id !== state.action_id;
if (run_action) {
this.null_action();
action_loaded = this.do_action(state.action_id);
@@ -89,13 +172,13 @@ instance.web.ActionManager = instance.web.Widget.extend({
}
$.when(action_loaded || null).then(function() {
- if (self.inner_viewmanager) {
- self.inner_viewmanager.do_load_state(state, warm);
+ if (self.inner_widget && self.inner_widget.do_load_state) {
+ self.inner_widget.do_load_state(state, warm);
}
});
},
do_action: function(action, on_close) {
- if (_.isNumber(action)) {
+ 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);
@@ -124,7 +207,7 @@ instance.web.ActionManager = instance.web.Widget.extend({
},
null_action: function() {
this.dialog_stop();
- this.content_stop();
+ this.clear_breadcrumbs();
},
ir_actions_act_window: function (action, on_close) {
var self = this;
@@ -137,29 +220,31 @@ instance.web.ActionManager = instance.web.Widget.extend({
}
if (action.target === 'new') {
if (this.dialog === null) {
- this.dialog = new instance.web.Dialog(this, { width: '80%' });
+ // These buttons will be overwrited by