[IMP] don't completely wedge the RTE in case save fails. This may well break snippets...
authorXavier Morel <xmo@openerp.com>
Wed, 23 Oct 2013 13:09:18 +0000 (15:09 +0200)
committerXavier Morel <xmo@openerp.com>
Wed, 23 Oct 2013 13:09:18 +0000 (15:09 +0200)
bzr revid: xmo@openerp.com-20131023130918-j5s81t0j60gitr1t

addons/website/static/src/css/editor.css
addons/website/static/src/css/editor.sass
addons/website/static/src/js/website.editor.js

index 26032aa..8fa0ad8 100644 (file)
@@ -1,4 +1,3 @@
-@charset "utf-8";
 /* ---- CKEditor Minimal Reset ---- */
 .navbar.navbar-inverse .cke_chrome {
   border: none;
@@ -174,6 +173,11 @@ table.editorbar-panel td.selected {
   white-space: pre-wrap;
 }
 
+.oe_carlos_danger {
+  outline: 1px solid red !important;
+  background-color: #ffd9dd !important;
+}
+
 /* ---- SNIPPET EDITOR ---- */
 #oe_snippets {
   position: fixed;
index e4ef24d..5dbe7a8 100644 (file)
@@ -154,6 +154,10 @@ table.editorbar-panel
     content: " "
     white-space: pre-wrap
 
+.oe_carlos_danger
+    outline: 1px solid red !important
+    background-color: #ffd9dd !important
+
 /* ---- SNIPPET EDITOR ---- */
 
 #oe_snippets
index 2249de2..f9d2aef 100644 (file)
             editor.destroy();
             // FIXME: select editables then filter by dirty?
             var defs = this.rte.fetch_editables(root)
-                .removeClass('oe_editable cke_focus')
-                .removeAttr('contentEditable')
                 .filter('.oe_dirty')
+                .removeAttr('contentEditable')
+                .removeClass('oe_dirty oe_editable cke_focus oe_carlos_danger')
                 .map(function () {
                     var $el = $(this);
                     // TODO: Add a queue with concurrency limit in webclient
                     // https://github.com/medikoo/deferred/blob/master/lib/ext/function/gate.js
                     return self.saving_mutex.exec(function () {
                         return self.saveElement($el)
-                            .fail(function () {
-                                var data = $el.data();
-                                console.error(_.str.sprintf('Could not save %s(%d).%s', data.oeModel, data.oeId, data.oeField));
+                            .then(undefined, function (thing, response) {
+                                // because ckeditor regenerates all the dom,
+                                // we can't just setup the popover here as
+                                // everything will be destroyed by the DOM
+                                // regeneration. Add markings instead, and
+                                // returns a new rejection with all relevant
+                                // info
+                                var id = _.uniqueId('carlos_danger_');
+                                $el.addClass('oe_dirty oe_carlos_danger');
+                                $el.addClass(id);
+                                return $.Deferred().reject({
+                                    id: id,
+                                    error: response.data,
+                                });
                             });
                     });
                 }).get();
             return $.when.apply(null, defs).then(function () {
                 website.reload();
+            }, function (failed) {
+                // If there were errors, re-enable edition
+                self.rte.start_edition(true).then(function () {
+                    // jquery's deferred being a pain in the ass
+                    if (!_.isArray(failed)) { failed = [failed]; }
+
+                    _(failed).each(function (failure) {
+                        $(root).find('.' + failure.id)
+                            .removeClass(failure.id)
+                            .popover({
+                                trigger: 'hover',
+                                content: failure.error.message,
+                                placement: 'auto top',
+                            })
+                            // Force-show popovers so users will notice them.
+                            .popover('show');
+                    })
+                });
             });
         },
         /**
          * Saves an RTE content, which always corresponds to a view section (?).
          */
         saveElement: function ($el) {
-            $el.removeClass('oe_dirty');
             var markup = $el.prop('outerHTML');
             return openerp.jsonRpc('/web/dataset/call', 'call', {
                 model: 'ir.ui.view',
 
             return true;
         },
-        start_edition: function () {
+        /**
+         * Makes the page editable
+         *
+         * @param {Boolean} [restart=false] in case the edition was already set
+         *                                  up once and is being re-enabled.
+         * @returns {$.Deferred} deferred indicating when the RTE is ready
+         */
+        start_edition: function (restart) {
             var self = this;
             // create a single editor for the whole page
             var root = document.getElementById('wrapwrap');
-            $(root).on('dragstart', 'img', function (e) {
-                e.preventDefault();
-            });
-            this.webkitSelectionFixer(root);
-            this.tableNavigation(root);
+            if (!restart) {
+                $(root).on('dragstart', 'img', function (e) {
+                    e.preventDefault();
+                });
+                this.webkitSelectionFixer(root);
+                this.tableNavigation(root);
+            }
+            var def = $.Deferred();
             var editor = this.editor = CKEDITOR.inline(root, self._config());
             editor.on('instanceReady', function () {
                 editor.setReadOnly(false);
                 document.execCommand("enableInlineTableEditing", false, "false");
 
                 self.trigger('rte:ready');
+                def.resolve();
             });
+            return def;
         },
 
         setup_editables: function (root) {