[IMP] website ace editor: display more informations about errors when the user save...
authorChristophe Matthieu <chm@openerp.com>
Thu, 20 Feb 2014 10:33:55 +0000 (11:33 +0100)
committerChristophe Matthieu <chm@openerp.com>
Thu, 20 Feb 2014 10:33:55 +0000 (11:33 +0100)
bzr revid: chm@openerp.com-20140220103355-0us8k76yrrodqs0u

addons/website/static/src/js/website.ace.js
addons/website/static/src/xml/website.xml

index 514969f..ed7037e 100644 (file)
         isWellFormed: function () {
             if (document.implementation.createDocument) {
                 var dom = new DOMParser().parseFromString(this.xml, "text/xml");
-                return dom.getElementsByTagName("parsererror").length === 0;
+                var error = dom.getElementsByTagName("parsererror");
+                return error.length === 0 || error;
             } else if (window.ActiveXObject) {
                 // TODO test in IE
                 var msDom = new ActiveXObject("Microsoft.XMLDOM");
                 msDom.async = false;
-                return !msDom.loadXML(this.xml);
+                msDom.loadXML(this.xml);
+                return !msDom.parseError.errorCode || msDom.parseError.reason + "\nline " + msDom.parseError.line;
             }
             return true;
         },
             }), function (session) {
                 return session.isDirty;
             });
-            var requests = _.map(toSave, self.saveView);
+            this.clearError();
+            var requests = _.map(toSave, function (session) {
+                return self.saveView(session);
+            });
             $.when.apply($, requests).then(function () {
                 self.reloadPage.call(self);
-            }).fail(function (source, error) {
-                var message = _.isString(error) ? error
-                    : (error && error.data && error.data.arguments && error.data.arguments[0] === "Access Denied") ? "Access denied: please sign in"
-                    : (error && error.message) ? error.message
-                    : "Unexpected error";
-                self.displayError.call(self, message);
+            }).fail(function (source, session, error) {
+                self.displayError.call(self, source, session, error);
             });
         },
         saveView: function (session) {
+            var self = this;
             var xml = new website.ace.XmlDocument(session.text);
-            if (xml.isWellFormed()) {
-                return openerp.jsonRpc('/web/dataset/call', 'call', {
+            var isWellFormed = xml.isWellFormed();
+            var def = $.Deferred();
+            if (isWellFormed === true) {
+                openerp.jsonRpc('/web/dataset/call', 'call', {
                     model: 'ir.ui.view',
                     method: 'write',
                     args: [[session.id], { 'arch':  xml.xml }, website.get_context()],
+                }).then(function () {
+                    def.resolve();
+                }).fail(function (source, error) {
+                    def.reject("server", session, error);
                 });
             } else {
-                return $.Deferred().reject(null, "Malformed XML document");
+                def.reject(null, session, $(isWellFormed).text());
             }
+            return def;
         },
         updateHash: function () {
             window.location.hash = hash + "?view=" + this.selectedViewId();
             this.updateHash();
             window.location.reload();
         },
-        displayError: function (error) {
-            // TODO Improve feedback (e.g. update 'Save' button + tooltip)
-            alert(error);
+        clearError: function () {
+            this.$(".ace_layer.ace_text-layer .ace_line").css("background", "");
+        },
+        displayError: function (source, session, error) {
+            var self = this;
+            var line, test;
+            // format error message
+            var message = _.isString(error) ? error
+                : (error && error.data && error.data.arguments && error.data.arguments[0] === "Access Denied") ? "Access denied: please sign in"
+                : (error && error.data && error.data.message) ? error.data.message
+                : (error && error.message) ? error.message
+                : "Unexpected error";
+            if (source == "server") {
+                message = eval(message.replace(/^\(/g, '([')
+                    .replace(/\)$/g, '])')
+                    .replace(/u'/g, "'")
+                    .replace(/<([^>]+)>/g, '<b style="color:#661100;">&lt;\$1&gt;</b>'))[1];
+                line = -1;
+            } else {
+                line = message.match(/line ([0-9]+)/i);
+                line = line ? parseInt(line[1],10) : -1;
+                test = new RegExp("^\\s*"+line+"\\s*$");
+            }
+
+            function gotoline() {
+                self.aceEditor.gotoLine(line);
+                setTimeout(function () {
+                    var $lines = self.$(".ace_editor .ace_gutter .ace_gutter-cell");
+                    var index = $lines.filter(function () {
+                        return test.test($(this).text());
+                    }).index();
+                    if (index>0) {
+                        self.$(".ace_layer.ace_text-layer .ace_line:eq(" + index + ")").css("background", "#661100");
+                    }
+                },100);
+            }
+            function onchangeSession (e) {
+                self.aceEditor.off('changeSession', onchangeSession);
+                gotoline();
+            }
+
+            var $list = this.$("#ace-view-list");
+            if (+$list.val() == session.id) {
+                if (line>-1) gotoline();
+            } else {
+                if (line) self.aceEditor.on('changeSession', onchangeSession);
+                this.$("#ace-view-list").val(session.id).change();
+            }
+
+            var $dialog = $(openerp.qweb.render('website.error_dialog', {
+                title: session.text.match(/\s+name=['"]([^'"]+)['"]/i)[1],
+                message:"<b>Malformed XML document</b>:<br/>" + message
+            }));
+            $dialog.appendTo("body");
+            $dialog.modal('show');
         },
         open: function () {
             this.$el.removeClass('oe_ace_closed').addClass('oe_ace_open');
index f25a491..4d9c9fc 100644 (file)
@@ -74,7 +74,7 @@
                     </div>
                     <div class="modal-body" t-if="message or backend_url">
                         <section>
-                            <t t-esc="message"/>
+                            <t t-raw="message"/>
                         </section>
                         <section class="mt32" t-if="backend_url">
                             <p>The web site has encountered an error.</p>