diff --git a/addons/web/controllers/main.py b/addons/web/controllers/main.py index 72ffd9567f6..ad8d91ed1dd 100644 --- a/addons/web/controllers/main.py +++ b/addons/web/controllers/main.py @@ -575,6 +575,20 @@ def from_elementtree(el, preserve_whitespaces=False): res["children"] = kids return res + +def content_disposition(filename, req): + filename = filename.encode('utf8') + escaped = urllib2.quote(filename) + browser = req.httprequest.user_agent.browser + version = int((req.httprequest.user_agent.version or '0').split('.')[0]) + if browser == 'msie' and version < 9: + return "attachment; filename=%s" % escaped + elif browser == 'safari': + return "attachment; filename=%s" % filename + else: + return "attachment; filename*=UTF-8''%s" % escaped + + #---------------------------------------------------------- # OpenERP Web web Controllers #---------------------------------------------------------- @@ -841,7 +855,7 @@ class Database(openerpweb.Controller): } return req.make_response(db_dump, [('Content-Type', 'application/octet-stream; charset=binary'), - ('Content-Disposition', 'attachment; filename="' + filename + '"')], + ('Content-Disposition', content_disposition(filename, req))], {'fileToken': int(token)} ) except xmlrpclib.Fault, e: @@ -1520,17 +1534,6 @@ class Binary(openerpweb.Controller): def placeholder(self, req): addons_path = openerpweb.addons_manifest['web']['addons_path'] return open(os.path.join(addons_path, 'web', 'static', 'src', 'img', 'placeholder.png'), 'rb').read() - def content_disposition(self, filename, req): - filename = filename.encode('utf8') - escaped = urllib2.quote(filename) - browser = req.httprequest.user_agent.browser - version = int((req.httprequest.user_agent.version or '0').split('.')[0]) - if browser == 'msie' and version < 9: - return "attachment; filename=%s" % escaped - elif browser == 'safari': - return "attachment; filename=%s" % filename - else: - return "attachment; filename*=UTF-8''%s" % escaped @openerpweb.httprequest def saveas(self, req, model, field, id=None, filename_field=None, **kw): @@ -1566,7 +1569,7 @@ class Binary(openerpweb.Controller): filename = res.get(filename_field, '') or filename return req.make_response(filecontent, [('Content-Type', 'application/octet-stream'), - ('Content-Disposition', self.content_disposition(filename, req))]) + ('Content-Disposition', content_disposition(filename, req))]) @openerpweb.httprequest def saveas_ajax(self, req, data, token): @@ -1596,7 +1599,7 @@ class Binary(openerpweb.Controller): filename = res.get(filename_field, '') or filename return req.make_response(filecontent, headers=[('Content-Type', 'application/octet-stream'), - ('Content-Disposition', self.content_disposition(filename, req))], + ('Content-Disposition', content_disposition(filename, req))], cookies={'fileToken': int(token)}) @openerpweb.httprequest @@ -1861,7 +1864,8 @@ class Export(View): return req.make_response(self.from_data(columns_headers, import_data), - headers=[('Content-Disposition', 'attachment; filename="%s"' % self.filename(model)), + headers=[('Content-Disposition', + content_disposition(self.filename(model), req)), ('Content-Type', self.content_type)], cookies={'fileToken': int(token)}) @@ -1997,11 +2001,11 @@ class Reports(View): file_name = reports.read(res_id[0], ['name'], context)['name'] else: file_name = action['report_name'] + file_name = '%s.%s' % (file_name, report_struct['format']) return req.make_response(report, headers=[ - # maybe we should take of what characters can appear in a file name? - ('Content-Disposition', 'attachment; filename="%s.%s"' % (file_name, report_struct['format'])), + ('Content-Disposition', content_disposition(file_name, req)), ('Content-Type', report_mimetype), ('Content-Length', len(report))], cookies={'fileToken': int(token)}) diff --git a/addons/web/i18n/ru.po b/addons/web/i18n/ru.po index fa80053a306..ed5735602d0 100644 --- a/addons/web/i18n/ru.po +++ b/addons/web/i18n/ru.po @@ -8,14 +8,14 @@ msgstr "" "Project-Id-Version: openerp-web\n" "Report-Msgid-Bugs-To: FULL NAME \n" "POT-Creation-Date: 2012-07-02 09:06+0200\n" -"PO-Revision-Date: 2012-10-23 14:30+0000\n" +"PO-Revision-Date: 2012-11-01 12:07+0000\n" "Last-Translator: Chertykov Denis \n" "Language-Team: Russian \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-10-24 05:20+0000\n" -"X-Generator: Launchpad (build 16179)\n" +"X-Launchpad-Export-Date: 2012-11-02 05:20+0000\n" +"X-Generator: Launchpad (build 16218)\n" #. openerp-web #: addons/web/static/src/js/chrome.js:176 @@ -306,7 +306,7 @@ msgstr "Группировать по: %s" #. openerp-web #: addons/web/static/src/js/search.js:1132 msgid "GroupBy" -msgstr "" +msgstr "Группировать по" #. openerp-web #: addons/web/static/src/js/search.js:1267 @@ -535,7 +535,7 @@ msgstr "Удалить" #. openerp-web #: addons/web/static/src/xml/base.xml:762 msgid "Duplicate" -msgstr "Клонировать" +msgstr "Дублировать" #. openerp-web #: addons/web/static/src/js/view_form.js:133 @@ -867,13 +867,13 @@ msgstr "Удалить" #: addons/web/static/src/xml/base.xml:166 #: addons/web/static/src/xml/base.xml:329 msgid "Backup" -msgstr "Резервное копирование" +msgstr "Резервная копия" #. openerp-web #: addons/web/static/src/xml/base.xml:195 #: addons/web/static/src/xml/base.xml:330 msgid "Restore" -msgstr "Востановить" +msgstr "Восстановить" #. openerp-web #: addons/web/static/src/xml/base.xml:332 @@ -908,7 +908,7 @@ msgstr "Язык по умолчанию:" #. openerp-web #: addons/web/static/src/xml/base.xml:91 msgid "Admin password:" -msgstr "Пароль Администратора:" +msgstr "Пароль администратора:" #. openerp-web #: addons/web/static/src/xml/base.xml:95 @@ -1080,7 +1080,7 @@ msgstr "Изменить действие" #. openerp-web #: addons/web/static/src/xml/base.xml:486 msgid "Edit Workflow" -msgstr "Редактировать Процесс" +msgstr "Редактировать процесс" #. openerp-web #: addons/web/static/src/xml/base.xml:491 @@ -1222,7 +1222,7 @@ msgstr "При изменении:" #. openerp-web #: addons/web/static/src/xml/base.xml:981 msgid "Relation:" -msgstr "Отношение:" +msgstr "Связь:" #. openerp-web #: addons/web/static/src/xml/base.xml:985 @@ -1411,12 +1411,12 @@ msgstr "Применить" #. openerp-web #: addons/web/static/src/xml/base.xml:1509 msgid "Save & New" -msgstr "Сохранить и Создать" +msgstr "Сохранить и создать" #. openerp-web #: addons/web/static/src/xml/base.xml:1510 msgid "Save & Close" -msgstr "Сохранить и Закрыть" +msgstr "Сохранить и закрыть" #. openerp-web #: addons/web/static/src/xml/base.xml:1617 @@ -1556,7 +1556,7 @@ msgid "" "For use if CSV files have titles on multiple lines, skips more than a single " "line during import" msgstr "" -"Применимо если в CSV файле заголовки расположены в нескольких строках и из " +"Применимо если в CSV файле заголовки расположены в нескольких строках и их " "необходимо пропустить" #. openerp-web @@ -1669,9 +1669,6 @@ msgstr "Предпросмотр файла, который система не #~ msgid "Activate the developper mode" #~ msgstr "Активировать режим разработчика" -#~ msgid "Notebook Page \"" -#~ msgstr "Страница Блокнота \"" - #~ msgid "Filter disabled due to invalid syntax" #~ msgstr "Фильтр отключен из-за неверного синтаксиса" @@ -1686,3 +1683,6 @@ msgstr "Предпросмотр файла, который система не #~ msgid "Advanced Filters" #~ msgstr "Расширенные фильтры" + +#~ msgid "Notebook Page \"" +#~ msgstr "Страница блокнота \"" diff --git a/addons/web/i18n/sl.po b/addons/web/i18n/sl.po index e15e7b572bc..687742a1775 100644 --- a/addons/web/i18n/sl.po +++ b/addons/web/i18n/sl.po @@ -8,14 +8,14 @@ msgstr "" "Project-Id-Version: openerp-web\n" "Report-Msgid-Bugs-To: FULL NAME \n" "POT-Creation-Date: 2012-07-02 09:06+0200\n" -"PO-Revision-Date: 2012-01-31 06:25+0000\n" -"Last-Translator: ERP Basing \n" +"PO-Revision-Date: 2012-11-01 16:38+0000\n" +"Last-Translator: Dusan Laznik \n" "Language-Team: Slovenian \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-10-21 05:02+0000\n" -"X-Generator: Launchpad (build 16165)\n" +"X-Launchpad-Export-Date: 2012-11-02 05:20+0000\n" +"X-Generator: Launchpad (build 16218)\n" #. openerp-web #: addons/web/static/src/js/chrome.js:176 @@ -129,62 +129,62 @@ msgstr "OpenERP-Community Version" #. openerp-web #: addons/web/static/src/js/coresetup.js:619 msgid "less than a minute ago" -msgstr "" +msgstr "manj kot minuto nazaj" #. openerp-web #: addons/web/static/src/js/coresetup.js:620 msgid "about a minute ago" -msgstr "" +msgstr "približno pred minuto" #. openerp-web #: addons/web/static/src/js/coresetup.js:621 #, python-format msgid "%d minutes ago" -msgstr "" +msgstr "pred %d minutami" #. openerp-web #: addons/web/static/src/js/coresetup.js:622 msgid "about an hour ago" -msgstr "" +msgstr "pred približno eno uro" #. openerp-web #: addons/web/static/src/js/coresetup.js:623 #, python-format msgid "%d hours ago" -msgstr "" +msgstr "Pred %d urami" #. openerp-web #: addons/web/static/src/js/coresetup.js:624 msgid "a day ago" -msgstr "" +msgstr "pred enim dnevom" #. openerp-web #: addons/web/static/src/js/coresetup.js:625 #, python-format msgid "%d days ago" -msgstr "" +msgstr "pred %d dnevi" #. openerp-web #: addons/web/static/src/js/coresetup.js:626 msgid "about a month ago" -msgstr "" +msgstr "približno pred enim mesecem" #. openerp-web #: addons/web/static/src/js/coresetup.js:627 #, python-format msgid "%d months ago" -msgstr "" +msgstr "pred %d meseci" #. openerp-web #: addons/web/static/src/js/coresetup.js:628 msgid "about a year ago" -msgstr "" +msgstr "približno pred enim letom" #. openerp-web #: addons/web/static/src/js/coresetup.js:629 #, python-format msgid "%d years ago" -msgstr "" +msgstr "Pred %d leti" #. openerp-web #: addons/web/static/src/js/data_export.js:6 @@ -293,13 +293,13 @@ msgstr "" #. openerp-web #: addons/web/static/src/js/search.js:999 msgid "Filter" -msgstr "" +msgstr "Filter:" #. openerp-web #: addons/web/static/src/js/search.js:1108 #, python-format msgid "Group by: %s" -msgstr "" +msgstr "Združi po: %s" #. openerp-web #: addons/web/static/src/js/search.js:1132 @@ -347,7 +347,7 @@ msgstr "Filtri" #. openerp-web #: addons/web/static/src/js/search.js:1762 msgid "Advanced" -msgstr "" +msgstr "Napredeno" #. openerp-web #: addons/web/static/src/js/search.js:1853 @@ -632,7 +632,7 @@ msgstr "Dodaj: " #. openerp-web #: addons/web/static/src/js/view_form.js:4230 msgid "Save As..." -msgstr "" +msgstr "Shrani kot ..." #. openerp-web #: addons/web/static/src/js/view_form.js:4230 @@ -669,7 +669,7 @@ msgstr "Skupina" #. openerp-web #: addons/web/static/src/js/view_list.js:549 msgid "Do you really want to remove these records?" -msgstr "" +msgstr "Res želite odstraniti te zapise?" #. openerp-web #: addons/web/static/src/js/views.js:925 @@ -679,7 +679,7 @@ msgstr "Opozorilo" #. openerp-web #: addons/web/static/src/js/view_list.js:716 msgid "You must select at least one record." -msgstr "" +msgstr "Izbrati morate vsaj en zapis" #. openerp-web #: addons/web/static/src/js/view_list.js:1243 @@ -727,17 +727,17 @@ msgstr "" #. openerp-web #: addons/web/static/src/js/views.js:716 msgid "Print" -msgstr "" +msgstr "Tiskanje" #. openerp-web #: addons/web/static/src/js/views.js:717 msgid "Attachment" -msgstr "" +msgstr "Priponka" #. openerp-web #: addons/web/static/src/js/views.js:718 addons/web/static/src/xml/base.xml:276 msgid "More" -msgstr "" +msgstr "Dodatno" #. openerp-web #: addons/web/static/src/js/views.js:810 @@ -757,7 +757,7 @@ msgstr "Izbrati morate vsaj en zapis." #. openerp-web #: addons/web/static/src/js/views.js:875 msgid "Uploading..." -msgstr "" +msgstr "Pošiljanje ..." #. openerp-web #: addons/web/static/src/js/views.js:885 @@ -963,7 +963,7 @@ msgstr "" #. openerp-web #: addons/web/static/src/xml/base.xml:327 msgid "Log out" -msgstr "" +msgstr "Odjava" #. openerp-web #: addons/web/static/src/xml/base.xml:333 @@ -1028,7 +1028,7 @@ msgstr "Potrditev gesla:" #. openerp-web #: addons/web/static/src/xml/base.xml:390 msgid "Open" -msgstr "" +msgstr "Odpri" #. openerp-web #: addons/web/static/src/xml/base.xml:390 @@ -1123,18 +1123,18 @@ msgstr "" #. openerp-web #: addons/web/static/src/xml/base.xml:527 msgid "Add..." -msgstr "" +msgstr "Dodaj ..." #. openerp-web #: addons/web/static/src/xml/base.xml:622 #: addons/web/static/src/xml/base.xml:687 msgid "or" -msgstr "" +msgstr "ali" #. openerp-web #: addons/web/static/src/xml/base.xml:687 msgid "Discard" -msgstr "" +msgstr "Opusti" #. openerp-web #: addons/web/static/src/xml/base.xml:806 @@ -1220,7 +1220,7 @@ msgstr "" #. openerp-web #: addons/web/static/src/xml/base.xml:981 msgid "Relation:" -msgstr "" +msgstr "Relacija:" #. openerp-web #: addons/web/static/src/xml/base.xml:985 @@ -1235,7 +1235,7 @@ msgstr "Odpri vir" #. openerp-web #: addons/web/static/src/xml/base.xml:1063 msgid "Select date" -msgstr "" +msgstr "Izberi datum" #. openerp-web #: addons/web/static/src/xml/base.xml:948 @@ -1298,7 +1298,7 @@ msgstr "" #. openerp-web #: addons/web/static/src/xml/base.xml:1260 msgid "Button Type:" -msgstr "" +msgstr "Vrsta tipke:" #. openerp-web #: addons/web/static/src/xml/base.xml:1264 @@ -1318,7 +1318,7 @@ msgstr "Polje" #. openerp-web #: addons/web/static/src/xml/base.xml:1205 msgid "Advanced Search..." -msgstr "" +msgstr "Napredno iskanje ..." #. openerp-web #: addons/web/static/src/xml/base.xml:1287 @@ -1363,7 +1363,7 @@ msgstr "" #. openerp-web #: addons/web/static/src/xml/base.xml:1381 msgid "Filter name" -msgstr "" +msgstr "Ime filtra" #. openerp-web #: addons/web/static/src/xml/base.xml:1383 diff --git a/addons/web/static/lib/cleditor/jquery.cleditor.js b/addons/web/static/lib/cleditor/jquery.cleditor.js index c0763136c99..0fff0152776 100644 --- a/addons/web/static/lib/cleditor/jquery.cleditor.js +++ b/addons/web/static/lib/cleditor/jquery.cleditor.js @@ -295,7 +295,12 @@ // Bind the window resize event when the width or height is auto or % if (/auto|%/.test("" + options.width + options.height)) - $(window).resize(function() {refresh(editor);}); + $(window).resize(function() { + // CHM Note MonkeyPatch: if the DOM is not remove, refresh the cleditor + if(editor.$main.parent().parent().size()) { + refresh(editor); + } + }); // Create the iframe and resize the controls refresh(editor); @@ -562,7 +567,7 @@ //================== // Private Functions //================== - + // checksum - returns a checksum using the Adler-32 method function checksum(text) { diff --git a/addons/web/static/src/css/base.css b/addons/web/static/src/css/base.css index 17b65ae91be..b030d0712f0 100644 --- a/addons/web/static/src/css/base.css +++ b/addons/web/static/src/css/base.css @@ -217,7 +217,7 @@ background-clip: padding-box; } .openerp.ui-dialog .ui-dialog-content { - padding: 0px; + padding: 0; } .openerp.ui-dialog .ui-dialog-titlebar, .openerp.ui-dialog .ui-dialog-content, .openerp.ui-dialog .ui-dialog-buttonpane { padding: 16px; @@ -1186,7 +1186,7 @@ color: white; padding: 2px 4px; margin: 1px 6px 0 0; - border: 1px solid lightgrey; + border: 1px solid lightGray; text-shadow: 0 1px 1px rgba(0, 0, 0, 0.2); -moz-border-radius: 4px; -webkit-border-radius: 4px; @@ -1211,7 +1211,7 @@ transform: scale(1.1); } .openerp .oe_secondary_submenu .oe_active { - border-top: 1px solid lightgrey; + border-top: 1px solid lightGray; border-bottom: 1px solid #dedede; text-shadow: 0 1px 1px rgba(0, 0, 0, 0.2); -moz-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.2), inset 0 -1px 3px rgba(40, 40, 40, 0.2); @@ -2060,10 +2060,11 @@ padding-bottom: 0; } .openerp .oe_form div.oe_chatter { + box-sizing: border-box; min-width: 682px; max-width: 892px; margin: 0 auto; - padding: 16px 0 48px; + padding: 16px 16px 48px; } .openerp .oe_form div.oe_form_configuration p, .openerp .oe_form div.oe_form_configuration ul, .openerp .oe_form div.oe_form_configuration ol { color: #aaaaaa; @@ -2135,7 +2136,7 @@ } .openerp .oe_form .oe_form_label_help[for] span, .openerp .oe_form .oe_form_label[for] span { font-size: 80%; - color: darkgreen; + color: darkGreen; vertical-align: top; position: relative; top: -4px; @@ -2566,11 +2567,9 @@ .openerp .oe_list_editable .oe_list_content td.oe_list_field_cell { padding: 4px 6px 3px 6px; } -.openerp .oe_list.oe_list_editable td.oe_list_record_delete { - position: absolute; -} .openerp .oe_list.oe_list_editable.oe_editing .oe_edition .oe_list_field_cell:not(.oe_readonly) { color: transparent; + text-shadow: none; } .openerp .oe_list.oe_list_editable.oe_editing .oe_edition .oe_list_field_cell:not(.oe_readonly) * { visibility: hidden; @@ -2877,6 +2876,78 @@ color: #333333; } +.openerp .oe_fileupload { + display: inline-block; + clear: both; + width: 100%; +} +.openerp .oe_fileupload .oe_add { + float: left; + position: relative; + width: 100%; + left: 2px; + top: 7px; +} +.openerp .oe_fileupload .oe_add button { + display: inline; + height: 24px; + font-size: 12px; + line-height: 12px; + vertical-align: middle; +} +.openerp .oe_fileupload .oe_add button.oe_attach { + width: 24px; + overflow: hidden; + width: 24px; + overflow: hidden; + background: transparent; + color: #7c7bad; + box-shadow: none; + border: none; + text-shadow: none; +} +.openerp .oe_fileupload .oe_add button.oe_attach .oe_e { + position: relative; + top: -1px; + left: -9px; +} +.openerp .oe_fileupload .oe_add input.oe_form_binary_file { + display: inline-block; + margin-left: -5px; + height: 28px; + width: 52px; + margin-top: -26px; +} +.openerp .oe_fileupload .oe_add .oe_attach_label { + color: #7c7bad; + margin-left: -3px; +} +.openerp .oe_fileupload .oe_attachments { + margin-bottom: 4px; + margin-right: 0px; + font-size: 12px; + border-radius: 2px; + border: solid 1px rgba(124, 123, 173, 0.14); +} +.openerp .oe_fileupload .oe_attachments .oe_attachment { + padding: 2px; + padding-left: 4px; + padding-right: 4px; +} +.openerp .oe_fileupload .oe_attachments .oe_attachment .oe_e { + font-size: 23px; + margin-top: -5px; +} +.openerp .oe_fileupload .oe_attachments .oe_attachment .oe_e:hover { + text-decoration: none; +} +.openerp .oe_fileupload .oe_attachments .oe_attachment:nth-child(odd) { + background: white; +} +.openerp .oe_fileupload .oe_attachments .oe_attachment:nth-child(even) { + background: #f4f5fa; +} + .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 15e1898883d..79a688cf823 100644 --- a/addons/web/static/src/css/base.sass +++ b/addons/web/static/src/css/base.sass @@ -258,6 +258,7 @@ $sheet-padding: 16px // so remove position:relative .ui-tabs position: static + // Modal box &.ui-dialog display: none @@ -271,7 +272,7 @@ $sheet-padding: 16px @include box-shadow(0 1px 12px rgba(0, 0, 0, 0.6)) @include background-clip() .ui-dialog-content - padding: 0px + padding: 0 .ui-dialog-titlebar, .ui-dialog-content, .ui-dialog-buttonpane padding: 16px .ui-dialog-titlebar @@ -1636,10 +1637,11 @@ $sheet-padding: 16px width: 400px padding-bottom: 0 div.oe_chatter + box-sizing: border-box min-width: $sheet-min-width + 2* $sheet-padding max-width: $sheet-max-width + 2* $sheet-padding margin: 0 auto - padding: 16px 0 48px + padding: 16px 16px 48px div.oe_form_configuration p, ul, ol color: #aaa @@ -2032,14 +2034,12 @@ $sheet-padding: 16px .oe_list_content td.oe_list_field_cell padding: 4px 6px 3px 6px - .oe_list.oe_list_editable - td.oe_list_record_delete - position: absolute .oe_list.oe_list_editable.oe_editing .oe_edition .oe_list_field_cell:not(.oe_readonly) * visibility: hidden color: transparent + text-shadow: none .oe_m2o_drop_down_button top: 5px .oe_m2o_cm_button @@ -2278,6 +2278,67 @@ $sheet-padding: 16px float: right color: #333 // }}} + +.openerp + .oe_fileupload + display: inline-block + clear: both + width: 100% + .oe_add + float: left + position: relative + width: 100% + left: +2px + top: +7px + button + display: inline + height: 24px + font-size: 12px + line-height: 12px + vertical-align: middle + button.oe_attach + width: 24px + overflow: hidden + width: 24px + overflow: hidden + background: transparent + color: #7C7BAD + box-shadow: none + border: none + text-shadow: none + .oe_e + position: relative + top: -1px + left: -9px + input.oe_form_binary_file + display: inline-block + margin-left: -5px + height: 28px + width: 52px + margin-top: -26px + .oe_attach_label + color: #7C7BAD + margin-left: -3px + .oe_attachments + margin-bottom: 4px + margin-right: 0px + font-size: 12px + border-radius: 2px + border: solid 1px rgba(124,123,173,0.14) + .oe_attachment + padding: 2px + padding-left: 4px + padding-right: 4px + .oe_e + font-size: 23px + margin-top: -5px + .oe_e:hover + text-decoration: none + .oe_attachment:nth-child(odd) + background: white + .oe_attachment:nth-child(even) + background: #F4F5FA + // Kitten Mode {{{ .kitten-mode-activated background-image: url(http://placekitten.com/g/1365/769) diff --git a/addons/web/static/src/js/data.js b/addons/web/static/src/js/data.js index 467b74040c7..2f8679794b0 100644 --- a/addons/web/static/src/js/data.js +++ b/addons/web/static/src/js/data.js @@ -471,7 +471,7 @@ instance.web.DataSet = instance.web.CallbackEnabled.extend({ default_get: function(fields, options) { options = options || {}; return this._model.call('default_get', - [fields], {context: this._model.context(options.context)}); + [fields], {context: this.get_context(options.context)}); }, /** * Creates a new record in db @@ -480,7 +480,7 @@ instance.web.DataSet = instance.web.CallbackEnabled.extend({ * @returns {$.Deferred} */ create: function(data) { - return this._model.call('create', [data], {context: this._model.context()}); + return this._model.call('create', [data], {context: this.get_context()}); }, /** * Saves the provided data in an existing db record @@ -493,7 +493,7 @@ instance.web.DataSet = instance.web.CallbackEnabled.extend({ */ write: function (id, data, options) { options = options || {}; - return this._model.call('write', [[id], data], {context: this._model.context(options.context)}).done(this.trigger('dataset_changed', id, data, options)); + return this._model.call('write', [[id], data], {context: this.get_context(options.context)}).done(this.trigger('dataset_changed', id, data, options)); }, /** * Deletes an existing record from the database @@ -501,7 +501,7 @@ instance.web.DataSet = instance.web.CallbackEnabled.extend({ * @param {Number|String} ids identifier of the record to delete */ unlink: function(ids) { - return this._model.call('unlink', [ids], {context: this._model.context()}).done(this.trigger('dataset_changed', ids)); + return this._model.call('unlink', [ids], {context: this.get_context()}).done(this.trigger('dataset_changed', ids)); }, /** * Calls an arbitrary RPC method @@ -532,7 +532,7 @@ instance.web.DataSet = instance.web.CallbackEnabled.extend({ * @returns {$.Deferred} */ name_get: function(ids) { - return this._model.call('name_get', [ids], {context: this._model.context()}); + return this._model.call('name_get', [ids], {context: this.get_context()}); }, /** * @@ -556,7 +556,7 @@ instance.web.DataSet = instance.web.CallbackEnabled.extend({ * @param name */ name_create: function(name) { - return this._model.call('name_create', [name], {context: this._model.context()}); + return this._model.call('name_create', [name], {context: this.get_context()}); }, exec_workflow: function (id, signal) { return this._model.exec_workflow(id, signal); @@ -606,7 +606,7 @@ instance.web.DataSet = instance.web.CallbackEnabled.extend({ return instance.session.rpc('/web/dataset/resequence', { model: this.model, ids: ids, - context: this._model.context(options.context), + context: this.get_context(options.context), }).then(function (results) { return results; }); diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js index 66ba41ec0cf..6bb2909e764 100644 --- a/addons/web/static/src/js/view_form.js +++ b/addons/web/static/src/js/view_form.js @@ -427,7 +427,7 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM var onchange = _.str.trim(on_change); var call = onchange.match(/^\s?(.*?)\((.*?)\)\s?$/); if (!call) { - return null; + throw new Error("Wrong on change format: " + onchange); } var method = call[1]; @@ -494,71 +494,59 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM var self = this; return this.on_change_mutex.exec(function() { try { - var response = {}, can_process_onchange = $.Deferred(); + var def; processed = processed || []; processed.push(widget.name); var on_change = widget.node.attrs.on_change; if (on_change) { var change_spec = self.parse_on_change(on_change, widget); - if (change_spec) { - var ajax = { - url: '/web/dataset/onchange', - async: false - }; - can_process_onchange = self.rpc(ajax, { - model: self.dataset.model, - method: change_spec.method, - args: [(self.datarecord.id == null ? [] : [self.datarecord.id])].concat(change_spec.args), - context_id: change_spec.context_index == undefined ? null : change_spec.context_index + 1 - }).done(function(r) { - _.extend(response, r); - }); - } else { - console.warn("Wrong on_change format", on_change); - } - } - // fail if onchange failed - if (can_process_onchange.state() === 'rejected') { - return can_process_onchange; + def = self.rpc('/web/dataset/onchange', { + model: self.dataset.model, + method: change_spec.method, + args: [(self.datarecord.id == null ? [] : [self.datarecord.id])].concat(change_spec.args), + context_id: change_spec.context_index == undefined ? null : change_spec.context_index + 1 + }); + } else { + def = $.when({}); } + return def.then(function(response) { + if (widget.field['change_default']) { + var fieldname = widget.name + var value_; + if (response.value && (fieldname in response.value)) { + // Use value from onchange if onchange executed + value_ = response.value[fieldname]; + } else { + // otherwise get form value for field + value_ = self.fields[fieldname].get_value(); + } + var condition = fieldname + '=' + value_; - if (widget.field['change_default']) { - var fieldname = widget.name, value_; - if (response.value && (fieldname in response.value)) { - // Use value from onchange if onchange executed - value_ = response.value[fieldname]; - } else { - // otherwise get form value for field - value_ = self.fields[fieldname].get_value(); + if (value_) { + return self.rpc('/web/dataset/call', { + model: 'ir.values', + method: 'get_defaults', + args: [self.model, condition] + }).then(function (results) { + if (!results.length) { + return response; + } + if (!response.value) { + response.value = {}; + } + for(var i=0; i 0) { @@ -2986,7 +2974,10 @@ instance.web.form.FieldMany2One = instance.web.form.AbstractField.extend(instanc self.ed_def = $.Deferred(); self.ed_def.done(function() { self.show_error_displayer(); + ignore_blur = false; + self.trigger('focused'); }); + ignore_blur = true; setTimeout(function() { self.ed_def.resolve(); self.uned_def.reject(); @@ -3316,7 +3307,7 @@ instance.web.form.FieldOne2Many = instance.web.form.AbstractField.extend({ e.cancel = true; }); _(controller.columns).find(function (column) { - if (!column instanceof instance.web.list.Handle) { + if (!(column instanceof instance.web.list.Handle)) { return false; } column.modifiers.invisible = true; @@ -4869,6 +4860,132 @@ instance.web.form.FieldBinaryImage = instance.web.form.FieldBinary.extend({ } }); +/** + * Widget for (one2many field) to upload one or more file in same time and display in list. + * The user can delete his files. + * Options on attribute ; "blockui" {Boolean} block the UI or not + * during the file is uploading + */ +instance.web.form.FieldOne2ManyBinaryMultiFiles = instance.web.form.AbstractField.extend({ + template: "FieldBinaryFileUploader", + init: function(field_manager, node) { + this._super(field_manager, node); + this.field_manager = field_manager; + this.node = node; + if(this.field.type != "one2many" || this.field.relation != 'ir.attachment') { + throw "The type of the field '"+this.field.string+"' must be a one2many field with a relation to 'ir.attachment' model."; + } + this.ds_file = new instance.web.DataSetSearch(this, 'ir.attachment'); + this.fileupload_id = _.uniqueId('oe_fileupload_temp'); + $(window).on(this.fileupload_id, _.bind(this.on_file_loaded, this)); + }, + start: function() { + this._super(this); + this.$el.on('change', 'input.oe_form_binary_file', this.on_file_change ); + }, + get_value: function() { + return _.map(this.get('value'), function (value) { return commands.link_to( value.id ); }); + }, + get_file_url: function (attachment) { + return instance.origin + '/web/binary/saveas?session_id=' + this.session.session_id + '&model=ir.attachment&field=datas&filename_field=datas_fname&id=' + attachment['id']; + }, + render_value: function () { + var render = $(instance.web.qweb.render('FieldBinaryFileUploader.files', {'widget': this})); + render.on('click', '.oe_delete', _.bind(this.on_file_delete, this)); + this.$('.oe_placeholder_files, .oe_attachments').replaceWith( render ); + + // reinit input type file + var $input = this.$('input.oe_form_binary_file'); + $input.after($input.clone(true)).remove(); + this.$(".oe_fileupload").show(); + }, + on_file_change: function (event) { + event.stopPropagation(); + var self = this; + var $target = $(event.target); + if ($target.val() !== '') { + + var filename = $target.val().replace(/.*[\\\/]/,''); + + // if the files is currently uploded, don't send again + if( !isNaN(_.find(this.get('value'), function (file) { return (file.filename || file.name) == filename && file.upload; } )) ) { + return false; + } + + // block UI or not + if(this.node.attrs.blockui) { + instance.web.blockUI(); + } + + // if the files exits for this answer, delete the file before upload + var files = _.filter(this.get('value'), function (file) { + if((file.filename || file.name) == filename) { + self.ds_file.unlink([file.id]); + return false; + } else { + return true; + } + }); + + // TODO : unactivate send on wizard and form + + // submit file + this.$('form.oe_form_binary_form').submit(); + this.$(".oe_fileupload").hide(); + + // add file on result + files.push({ + 'id': 0, + 'name': filename, + 'filename': filename, + 'url': '', + 'upload': true + }); + + this.set({'value': files}); + } + }, + on_file_loaded: function (event, result) { + // unblock UI + if(this.node.attrs.blockui) { + instance.web.unblockUI(); + } + + // TODO : activate send on wizard and form + + var files = this.get('value'); + for(var i in files){ + if(files[i].filename == result.filename && files[i].upload) { + files[i] = { + 'id': result.id, + 'name': result.name, + 'filename': result.filename, + 'url': this.get_file_url(result) + }; + } + } + + this.set({'value': files}); + this.render_value() + }, + on_file_delete: function (event) { + event.stopPropagation(); + var file_id=$(event.target).data("id"); + if (file_id) { + var files=[]; + for(var i in this.get('value')){ + if(file_id != this.get('value')[i].id){ + files.push(this.get('value')[i]); + } + else { + this.ds_file.unlink([file_id]); + } + } + this.set({'value': files}); + } + }, +}); + instance.web.form.FieldStatus = instance.web.form.AbstractField.extend({ template: "FieldStatus", init: function(field_manager, node) { @@ -5021,6 +5138,7 @@ instance.web.form.widgets = new instance.web.Registry({ 'progressbar': 'instance.web.form.FieldProgressBar', 'image': 'instance.web.form.FieldBinaryImage', 'binary': 'instance.web.form.FieldBinaryFile', + 'one2many_binary': 'instance.web.form.FieldOne2ManyBinaryMultiFiles', 'statusbar': 'instance.web.form.FieldStatus', 'monetary': 'instance.web.form.FieldMonetary', }); diff --git a/addons/web/static/src/js/view_list.js b/addons/web/static/src/js/view_list.js index 86eb4c72674..cc6846a6f48 100644 --- a/addons/web/static/src/js/view_list.js +++ b/addons/web/static/src/js/view_list.js @@ -1100,7 +1100,6 @@ instance.web.ListView.List = instance.web.Class.extend( /** @lends instance.web. }, this); if (!this.$current) { return; } this.$current.remove(); - this.$current = null; }, get_records: function () { return this.records.map(function (record) { diff --git a/addons/web/static/src/js/view_list_editable.js b/addons/web/static/src/js/view_list_editable.js index 92a314a9e03..aec480502fa 100644 --- a/addons/web/static/src/js/view_list_editable.js +++ b/addons/web/static/src/js/view_list_editable.js @@ -252,9 +252,10 @@ openerp.web.list_editable = function (instance) { var position = $cell.position(); field.set_dimensions($cell.outerHeight(), $cell.outerWidth()); - field.$el.css({ - top: position.top, - left: position.left, + field.$el.position({ + my: 'left top', + at: 'left top', + of: $cell }); }, /** @@ -410,15 +411,15 @@ openerp.web.list_editable = function (instance) { }); this.editor.$el.on('keyup keydown', function (e) { - if (!self.editor.is_editing()) { return; } + if (!self.editor.is_editing()) { return true; } var key = _($.ui.keyCode).chain() .map(function (v, k) { return {name: k, code: v}; }) .find(function (o) { return o.code === e.which; }) .value(); - if (!key) { return; } + if (!key) { return true; } var method = e.type + '_' + key.name; - if (!(method in self)) { return; } - self[method](e); + if (!(method in self)) { return true; } + return self[method](e); }); }, /** @@ -446,7 +447,10 @@ openerp.web.list_editable = function (instance) { keyup_ENTER: function () { return this._next(); }, - keyup_ESCAPE: function () { + keydown_ESCAPE: function (e) { + return false; + }, + keyup_ESCAPE: function (e) { return this.cancel_edition(); }, /** diff --git a/addons/web/static/src/xml/base.xml b/addons/web/static/src/xml/base.xml index 9880abd20f7..275d31a9fde 100644 --- a/addons/web/static/src/xml/base.xml +++ b/addons/web/static/src/xml/base.xml @@ -1169,11 +1169,54 @@ - + +