diff --git a/addons/website/static/lib/bootstrap-tour/bootstrap-tour.css b/addons/website/static/lib/bootstrap-tour/bootstrap-tour.css deleted file mode 100755 index 72c6e8cbab7..00000000000 --- a/addons/website/static/lib/bootstrap-tour/bootstrap-tour.css +++ /dev/null @@ -1,43 +0,0 @@ -.tour-backdrop { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 1009; - background-color: #000; - opacity: 0.8; -} -.tour-step-backdrop { - position: relative; - z-index: 1011; -} -.tour-step-background { - position: absolute; - z-index: 1010; - background: #fff; - border-radius: 6px; -} -.popover[class*="tour-"] .popover-navigation { - padding: 9px 14px; -} -.popover[class*="tour-"] .popover-navigation *[data-role=end] { - float: right; -} -.popover[class*="tour-"] .popover-navigation *[data-role=prev], -.popover[class*="tour-"] .popover-navigation *[data-role=next], -.popover[class*="tour-"] .popover-navigation *[data-role=end] { - cursor: pointer; -} -.popover[class*="tour-"] .popover-navigation *[data-role=prev].disabled, -.popover[class*="tour-"] .popover-navigation *[data-role=next].disabled, -.popover[class*="tour-"] .popover-navigation *[data-role=end].disabled { - cursor: default; -} -.popover[class*="tour-"].orphan { - position: fixed; - margin-top: 0; -} -.popover[class*="tour-"].orphan .arrow { - display: none; -} diff --git a/addons/website/static/lib/bootstrap-tour/bootstrap-tour.js b/addons/website/static/lib/bootstrap-tour/bootstrap-tour.js deleted file mode 100755 index 8b45d6da9ee..00000000000 --- a/addons/website/static/lib/bootstrap-tour/bootstrap-tour.js +++ /dev/null @@ -1,559 +0,0 @@ -/* =========================================================== -# bootstrap-tour - v0.6.1 -# http://bootstraptour.com -# ============================================================== -# Copyright 2012-2013 Ulrich Sossou -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -*/ -(function() { - (function($, window) { - var Tour, document; - document = window.document; - Tour = (function() { - function Tour(options) { - this._options = $.extend({ - name: "tour", - container: "body", - keyboard: true, - storage: window.localStorage, - debug: false, - backdrop: false, - redirect: true, - orphan: false, - basePath: "", - template: "

", - afterSetState: function(key, value) {}, - afterGetState: function(key, value) {}, - afterRemoveState: function(key) {}, - onStart: function(tour) {}, - onEnd: function(tour) {}, - onShow: function(tour) {}, - onShown: function(tour) {}, - onHide: function(tour) {}, - onHidden: function(tour) {}, - onNext: function(tour) {}, - onPrev: function(tour) {} - }, options); - this._steps = []; - this.setCurrentStep(); - this.backdrop = { - overlay: null, - $element: null, - $background: null - }; - } - - Tour.prototype.setState = function(key, value) { - var keyName; - if (this._options.storage) { - keyName = "" + this._options.name + "_" + key; - this._options.storage.setItem(keyName, value); - return this._options.afterSetState(keyName, value); - } else { - if (this._state == null) { - this._state = {}; - } - return this._state[key] = value; - } - }; - - Tour.prototype.removeState = function(key) { - var keyName; - if (this._options.storage) { - keyName = "" + this._options.name + "_" + key; - this._options.storage.removeItem(keyName); - return this._options.afterRemoveState(keyName); - } else { - if (this._state != null) { - return delete this._state[key]; - } - } - }; - - Tour.prototype.getState = function(key) { - var keyName, value; - if (this._options.storage) { - keyName = "" + this._options.name + "_" + key; - value = this._options.storage.getItem(keyName); - } else { - if (this._state != null) { - value = this._state[key]; - } - } - if (value === void 0 || value === "null") { - value = null; - } - this._options.afterGetState(key, value); - return value; - }; - - Tour.prototype.addSteps = function(steps) { - var step, _i, _len, _results; - _results = []; - for (_i = 0, _len = steps.length; _i < _len; _i++) { - step = steps[_i]; - _results.push(this.addStep(step)); - } - return _results; - }; - - Tour.prototype.addStep = function(step) { - return this._steps.push(step); - }; - - Tour.prototype.getStep = function(i) { - if (this._steps[i] != null) { - return $.extend({ - id: "step-" + i, - path: "", - placement: "right", - title: "", - content: "

", - next: i === this._steps.length - 1 ? -1 : i + 1, - prev: i - 1, - animation: true, - container: this._options.container, - backdrop: this._options.backdrop, - redirect: this._options.redirect, - orphan: this._options.orphan, - template: this._options.template, - onShow: this._options.onShow, - onShown: this._options.onShown, - onHide: this._options.onHide, - onHidden: this._options.onHidden, - onNext: this._options.onNext, - onPrev: this._options.onPrev - }, this._steps[i]); - } - }; - - Tour.prototype.start = function(force) { - var promise, - _this = this; - if (force == null) { - force = false; - } - if (this.ended() && !force) { - return this._debug("Tour ended, start prevented."); - } - $(document).off("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role=next]").on("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role=next]:not(.disabled)", function(e) { - e.preventDefault(); - return _this.next(); - }); - $(document).off("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role=prev]").on("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role=prev]:not(.disabled)", function(e) { - e.preventDefault(); - return _this.prev(); - }); - $(document).off("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role=end]").on("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role=end]", function(e) { - e.preventDefault(); - return _this.end(); - }); - this._onResize(function() { - return _this.showStep(_this._current); - }); - this._setupKeyboardNavigation(); - promise = this._makePromise(this._options.onStart != null ? this._options.onStart(this) : void 0); - return this._callOnPromiseDone(promise, this.showStep, this._current); - }; - - Tour.prototype.next = function() { - var promise; - if (this.ended()) { - return this._debug("Tour ended, next prevented."); - } - promise = this.hideStep(this._current); - return this._callOnPromiseDone(promise, this._showNextStep); - }; - - Tour.prototype.prev = function() { - var promise; - if (this.ended()) { - return this._debug("Tour ended, prev prevented."); - } - promise = this.hideStep(this._current); - return this._callOnPromiseDone(promise, this._showPrevStep); - }; - - Tour.prototype.goto = function(i) { - var promise; - if (this.ended()) { - return this._debug("Tour ended, goto prevented."); - } - promise = this.hideStep(this._current); - return this._callOnPromiseDone(promise, this.showStep, i); - }; - - Tour.prototype.end = function() { - var endHelper, hidePromise, - _this = this; - endHelper = function(e) { - $(document).off("click.tour-" + _this._options.name); - $(document).off("keyup.tour-" + _this._options.name); - $(window).off("resize.tour-" + _this._options.name); - _this.setState("end", "yes"); - if (_this._options.onEnd != null) { - return _this._options.onEnd(_this); - } - }; - hidePromise = this.hideStep(this._current); - return this._callOnPromiseDone(hidePromise, endHelper); - }; - - Tour.prototype.ended = function() { - return !!this.getState("end"); - }; - - Tour.prototype.restart = function() { - this.removeState("current_step"); - this.removeState("end"); - this.setCurrentStep(0); - return this.start(); - }; - - Tour.prototype.hideStep = function(i) { - var hideStepHelper, promise, step, - _this = this; - step = this.getStep(i); - promise = this._makePromise(step.onHide != null ? step.onHide(this, i) : void 0); - hideStepHelper = function(e) { - var $element; - $element = _this._isOrphan(step) ? $("body") : $(step.element); - $element.popover("destroy"); - if (step.reflex) { - $element.css("cursor", "").off("click.tour-" + _this._options.name); - } - if (step.backdrop) { - _this._hideBackdrop(); - } - if (step.onHidden != null) { - return step.onHidden(_this); - } - }; - this._callOnPromiseDone(promise, hideStepHelper); - return promise; - }; - - Tour.prototype.showStep = function(i) { - var promise, showStepHelper, skipToPrevious, step, - _this = this; - step = this.getStep(i); - if (!step) { - return; - } - skipToPrevious = i < this._current; - promise = this._makePromise(step.onShow != null ? step.onShow(this, i) : void 0); - showStepHelper = function(e) { - var current_path, path; - _this.setCurrentStep(i); - path = $.isFunction(step.path) ? step.path.call() : _this._options.basePath + step.path; - current_path = [document.location.pathname, document.location.hash].join(""); - if (_this._isRedirect(path, current_path)) { - _this._redirect(step, path); - return; - } - if (_this._isOrphan(step)) { - if (!step.orphan) { - _this._debug("Skip the orphan step " + (_this._current + 1) + ". Orphan option is false and the element doesn't exist or is hidden."); - if (skipToPrevious) { - _this._showPrevStep(); - } else { - _this._showNextStep(); - } - return; - } - _this._debug("Show the orphan step " + (_this._current + 1) + ". Orphans option is true."); - } - if (step.backdrop) { - _this._showBackdrop(!_this._isOrphan(step) ? step.element : void 0); - } - _this._showPopover(step, i); - if (step.onShown != null) { - step.onShown(_this); - } - return _this._debug("Step " + (_this._current + 1) + " of " + _this._steps.length); - }; - return this._callOnPromiseDone(promise, showStepHelper); - }; - - Tour.prototype.setCurrentStep = function(value) { - if (value != null) { - this._current = value; - return this.setState("current_step", value); - } else { - this._current = this.getState("current_step"); - return this._current = this._current === null ? 0 : parseInt(this._current, 10); - } - }; - - Tour.prototype._showNextStep = function() { - var promise, showNextStepHelper, step, - _this = this; - step = this.getStep(this._current); - showNextStepHelper = function(e) { - return _this.showStep(step.next); - }; - promise = this._makePromise((step.onNext != null ? step.onNext(this) : void 0)); - return this._callOnPromiseDone(promise, showNextStepHelper); - }; - - Tour.prototype._showPrevStep = function() { - var promise, showPrevStepHelper, step, - _this = this; - step = this.getStep(this._current); - showPrevStepHelper = function(e) { - return _this.showStep(step.prev); - }; - promise = this._makePromise((step.onPrev != null ? step.onPrev(this) : void 0)); - return this._callOnPromiseDone(promise, showPrevStepHelper); - }; - - Tour.prototype._debug = function(text) { - if (this._options.debug) { - return window.console.log("Bootstrap Tour '" + this._options.name + "' | " + text); - } - }; - - Tour.prototype._isRedirect = function(path, currentPath) { - return (path != null) && path !== "" && path.replace(/\?.*$/, "").replace(/\/?$/, "") !== currentPath.replace(/\/?$/, ""); - }; - - Tour.prototype._redirect = function(step, path) { - if ($.isFunction(step.redirect)) { - return step.redirect.call(this, path); - } else if (step.redirect === true) { - this._debug("Redirect to " + path); - return document.location.href = path; - } - }; - - Tour.prototype._isOrphan = function(step) { - return (step.element == null) || !$(step.element).length || $(step.element).is(":hidden"); - }; - - Tour.prototype._showPopover = function(step, i) { - var $element, $navigation, $template, $tip, isOrphan, options, - _this = this; - options = $.extend({}, this._options); - $template = $.isFunction(step.template) ? $(step.template(i, step)) : $(step.template); - $navigation = $template.find(".popover-navigation"); - isOrphan = this._isOrphan(step); - if (isOrphan) { - step.element = "body"; - step.placement = "top"; - $template = $template.addClass("orphan"); - } - $element = $(step.element); - $template.addClass("tour-" + this._options.name); - if (step.options) { - $.extend(options, step.options); - } - if (step.reflex) { - $element.css("cursor", "pointer").on("click.tour-" + this._options.name, function(e) { - if (_this._current < _this._steps.length - 1) { - return _this.next(); - } else { - return _this.end(); - } - }); - } - if (step.prev < 0) { - $navigation.find("*[data-role=prev]").addClass("disabled"); - } - if (step.next < 0) { - $navigation.find("*[data-role=next]").addClass("disabled"); - } - step.template = $template.clone().wrap("
").parent().html(); - $element.popover({ - placement: step.placement, - trigger: "manual", - title: step.title, - content: step.content, - html: true, - animation: step.animation, - container: step.container, - template: step.template, - selector: step.element - }).popover("show"); - $tip = $element.data("bs.popover") ? $element.data("bs.popover").tip() : $element.data("popover").tip(); - $tip.attr("id", step.id); - this._scrollIntoView($tip); - this._reposition($tip, step); - if (isOrphan) { - return this._center($tip); - } - }; - - Tour.prototype._reposition = function($tip, step) { - var offsetBottom, offsetHeight, offsetRight, offsetWidth, originalLeft, originalTop, tipOffset; - offsetWidth = $tip[0].offsetWidth; - offsetHeight = $tip[0].offsetHeight; - tipOffset = $tip.offset(); - originalLeft = tipOffset.left; - originalTop = tipOffset.top; - offsetBottom = $(document).outerHeight() - tipOffset.top - $tip.outerHeight(); - if (offsetBottom < 0) { - tipOffset.top = tipOffset.top + offsetBottom; - } - offsetRight = $("html").outerWidth() - tipOffset.left - $tip.outerWidth(); - if (offsetRight < 0) { - tipOffset.left = tipOffset.left + offsetRight; - } - if (tipOffset.top < 0) { - tipOffset.top = 0; - } - if (tipOffset.left < 0) { - tipOffset.left = 0; - } - $tip.offset(tipOffset); - if (step.placement === "bottom" || step.placement === "top") { - if (originalLeft !== tipOffset.left) { - return this._replaceArrow($tip, (tipOffset.left - originalLeft) * 2, offsetWidth, "left"); - } - } else { - if (originalTop !== tipOffset.top) { - return this._replaceArrow($tip, (tipOffset.top - originalTop) * 2, offsetHeight, "top"); - } - } - }; - - Tour.prototype._center = function($tip) { - return $tip.css("top", $(window).outerHeight() / 2 - $tip.outerHeight() / 2); - }; - - Tour.prototype._replaceArrow = function($tip, delta, dimension, position) { - return $tip.find(".arrow").css(position, delta ? 50 * (1 - delta / dimension) + "%" : ""); - }; - - Tour.prototype._scrollIntoView = function(tip) { - return $("html, body").stop().animate({ - scrollTop: Math.ceil(tip.offset().top - ($(window).height() / 2)) - }); - }; - - Tour.prototype._onResize = function(callback, timeout) { - return $(window).on("resize.tour-" + this._options.name, function() { - clearTimeout(timeout); - return timeout = setTimeout(callback, 100); - }); - }; - - Tour.prototype._setupKeyboardNavigation = function() { - var _this = this; - if (this._options.keyboard) { - return $(document).on("keyup.tour-" + this._options.name, function(e) { - if (!e.which) { - return; - } - switch (e.which) { - case 39: - e.preventDefault(); - if (_this._current < _this._steps.length - 1) { - return _this.next(); - } else { - return _this.end(); - } - break; - case 37: - e.preventDefault(); - if (_this._current > 0) { - return _this.prev(); - } - break; - case 27: - e.preventDefault(); - return _this.end(); - } - }); - } - }; - - Tour.prototype._makePromise = function(result) { - if (result && $.isFunction(result.then)) { - return result; - } else { - return null; - } - }; - - Tour.prototype._callOnPromiseDone = function(promise, cb, arg) { - var _this = this; - if (promise) { - return promise.then(function(e) { - return cb.call(_this, arg); - }); - } else { - return cb.call(this, arg); - } - }; - - Tour.prototype._showBackdrop = function(element) { - if (this.backdrop.overlay !== null) { - return; - } - this._showOverlay(); - if (element != null) { - return this._showOverlayElement(element); - } - }; - - Tour.prototype._hideBackdrop = function() { - if (this.backdrop.overlay === null) { - return; - } - if (this.backdrop.$element) { - this._hideOverlayElement(); - } - return this._hideOverlay(); - }; - - Tour.prototype._showOverlay = function() { - this.backdrop = $("
", { - "class": "tour-backdrop" - }); - return $("body").append(this.backdrop); - }; - - Tour.prototype._hideOverlay = function() { - this.backdrop.remove(); - return this.backdrop.overlay = null; - }; - - Tour.prototype._showOverlayElement = function(element) { - var $background, $element, offset; - $element = $(element); - $background = $("
"); - offset = $element.offset(); - offset.top = offset.top; - offset.left = offset.left; - $background.width($element.innerWidth()).height($element.innerHeight()).addClass("tour-step-background").offset(offset); - $element.addClass("tour-step-backdrop"); - $("body").append($background); - this.backdrop.$element = $element; - return this.backdrop.$background = $background; - }; - - Tour.prototype._hideOverlayElement = function() { - this.backdrop.$element.removeClass("tour-step-backdrop"); - this.backdrop.$background.remove(); - this.backdrop.$element = null; - return this.backdrop.$background = null; - }; - - return Tour; - - })(); - return window.Tour = Tour; - })(jQuery, window); - -}).call(this); diff --git a/addons/website/static/src/css/editor.css b/addons/website/static/src/css/editor.css index 4e9038837f3..7d8b1e609e8 100644 --- a/addons/website/static/src/css/editor.css +++ b/addons/website/static/src/css/editor.css @@ -518,10 +518,30 @@ div.tour-backdrop { z-index: 2009; } -.popover.tour { - z-index: 2010; +.popover.tour.orphan .arrow { + display: none; +} +.popover.tour .popover-navigation { + padding: 9px 14px; +} +.popover.tour .popover-navigation *[data-role="end"] { + float: right; +} +.popover.tour .popover-navigation *[data-role="next"], .popover.tour .popover-navigation *[data-role="end"] { + cursor: pointer; } .popover.fixed { position: fixed; } + +.tour-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1100; + background-color: black; + opacity: 0.8; +} diff --git a/addons/website/static/src/css/editor.sass b/addons/website/static/src/css/editor.sass index 53eb89a4341..d39b6abd453 100644 --- a/addons/website/static/src/css/editor.sass +++ b/addons/website/static/src/css/editor.sass @@ -451,9 +451,26 @@ $editorbar_height: 30px div.tour-backdrop z-index: 2009 .popover.tour - z-index: 2010 + &.orphan .arrow + display: none + .popover-navigation + padding: 9px 14px + *[data-role="end"] + float: right + *[data-role="next"],*[data-role="end"] + cursor: pointer .popover.fixed position: fixed +.tour-backdrop + position: fixed + top: 0 + right: 0 + bottom: 0 + left: 0 + z-index: 1100 + background-color: #000 + opacity: 0.8 + // }}} diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 2119d05f650..be69c66b615 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -545,7 +545,7 @@ observer.disconnect(); var editor = this.rte.editor; - var root = editor.element.$; + var root = editor.element && editor.element.$; editor.destroy(); // FIXME: select editables then filter by dirty? var defs = this.rte.fetch_editables(root) diff --git a/addons/website/static/src/js/website.snippets.editor.js b/addons/website/static/src/js/website.snippets.editor.js index 0177e8b8b64..8f49409924d 100644 --- a/addons/website/static/src/js/website.snippets.editor.js +++ b/addons/website/static/src/js/website.snippets.editor.js @@ -362,7 +362,6 @@ }, clean_for_save: function () { var self = this; - $("*[contentEditable], *[attributeEditable]") .removeAttr('contentEditable') .removeAttr('attributeEditable'); diff --git a/addons/website/static/src/js/website.tour.banner.js b/addons/website/static/src/js/website.tour.banner.js index d401cc40128..3d55220084e 100644 --- a/addons/website/static/src/js/website.tour.banner.js +++ b/addons/website/static/src/js/website.tour.banner.js @@ -4,127 +4,116 @@ var website = openerp.website; var _t = openerp._t; - website.EditorBar.include({ - start: function () { - this.registerTour(new website.Tour.Banner(this)); - return this._super(); - }, - }); - - website.Tour.Banner = website.Tour.extend({ + website.Tour.register({ id: 'banner', - name: "Build a page", + name: _t("Build a page"), path: '/page/website.homepage', - init: function () { - var self = this; - self.steps = [ - { - title: _t("Welcome to your website!"), - content: _t("This tutorial will guide you to build your home page. We will start by adding a banner."), - popover: { next: _t("Start Tutorial"), end: _t("Skip It") }, - }, - { - waitNot: '.popover.tour', - element: 'button[data-action=edit]', - placement: 'bottom', - title: _t("Edit this page"), - content: _t("Every page of your website can be modified through the Edit button."), - popover: { fixed: true }, - }, - { - element: 'button[data-action=snippet]', - placement: 'bottom', - title: _t("Insert building blocks"), - content: _t("Click here to insert blocks of content in the page."), - popover: { fixed: true }, - }, - { - snippet: '#snippet_structure .oe_snippet:first', - placement: 'bottom', - title: _t("Drag & Drop a Banner"), - content: _t("Drag the Banner block and drop it in your page."), - popover: { fixed: true }, - }, - { - waitFor: '.oe_overlay_options .oe_options:visible', - element: '#wrap .carousel:first div.carousel-content', - placement: 'top', - title: _t("Customize banner's text"), - content: _t("Click in the text and start editing it."), - sampleText: 'Here, a customized text', - }, - { - waitNot: '#wrap .carousel:first div.carousel-content:has(h2:'+ - 'containsExact('+_t('Your Banner Title')+')):has(h3:'+ - 'containsExact('+_t('Click to customize this text')+'))', - element: '.oe_snippet_parent:visible', - placement: 'bottom', - title: _t("Get banner properties"), - content: _t("Select the parent container to get the global options of the banner."), - popover: { fixed: true }, - }, - { - element: '.oe_overlay_options .oe_options:visible', - placement: 'left', - title: _t("Customize the banner"), - content: _t("Customize any block through this menu. Try to change the background of the banner."), - popover: { next: _t("Continue") }, - }, - { - waitNot: '.popover.tour', - element: 'button[data-action=snippet]', - placement: 'bottom', - title: _t("Add Another Block"), - content: _t("Let's add another building block to your page."), - popover: { fixed: true }, - }, - { - snippet: '#snippet_structure .oe_snippet:eq(6)', - placement: 'bottom', - title: _t("Drag & Drop This Block"), - content: _t("Drag the 'Features' block and drop it below the banner."), - popover: { fixed: true }, - }, - { - waitFor: '.oe_overlay_options .oe_options:visible', - element: 'button[data-action=save]', - placement: 'right', - title: _t("Save your modifications"), - content: _t("Publish your page by clicking on the 'Save' button."), - popover: { fixed: true }, - }, - { - waitFor: 'button[data-action=edit]:visible', - title: _t("Good Job!"), - content: _t("Well done, you created your homepage."), - popover: { next: _t("Continue") }, - }, - { - waitNot: '.popover.tour', - element: 'a[data-action=show-mobile-preview]', - placement: 'bottom', - title: _t("Test Your Mobile Version"), - content: _t("Let's check how your homepage looks like on mobile devices."), - popover: { fixed: true }, - }, - { - element: '.modal:has(#mobile-viewport) button[data-dismiss=modal]', - placement: 'right', - title: _t("Check Mobile Preview"), - content: _t("Scroll to check rendering and then close the mobile preview."), - popover: { next: _t("Continue") }, - }, - { - waitNot: '.modal', - element: '#content-menu-button', - placement: 'left', - title: _t("Add new pages and menus"), - content: _t("The 'Content' menu allows you to add pages or add the top menu."), - popover: { next: _t("Close Tutorial") }, - }, - ]; - return this._super(); - }, + steps: [ + { + title: _t("Welcome to your website!"), + content: _t("This tutorial will guide you to build your home page. We will start by adding a banner."), + popover: { next: _t("Start Tutorial"), end: _t("Skip It") }, + }, + { + waitNot: '.popover.tour', + element: 'button[data-action=edit]', + placement: 'bottom', + title: _t("Edit this page"), + content: _t("Every page of your website can be modified through the Edit button."), + popover: { fixed: true }, + }, + { + element: 'button[data-action=snippet]', + placement: 'bottom', + title: _t("Insert building blocks"), + content: _t("Click here to insert blocks of content in the page."), + popover: { fixed: true }, + }, + { + snippet: '#snippet_structure .oe_snippet:first', + placement: 'bottom', + title: _t("Drag & Drop a Banner"), + content: _t("Drag the Banner block and drop it in your page."), + popover: { fixed: true }, + }, + { + waitFor: '.oe_overlay_options .oe_options:visible', + element: '#wrap .carousel:first div.carousel-content', + placement: 'top', + title: _t("Customize banner's text"), + content: _t("Click in the text and start editing it."), + sampleText: 'Here, a customized text', + }, + { + waitNot: '#wrap .carousel:first div.carousel-content:has(h2:'+ + 'containsExact('+_t('Your Banner Title')+')):has(h3:'+ + 'containsExact('+_t('Click to customize this text')+'))', + element: '.oe_snippet_parent:visible', + placement: 'bottom', + title: _t("Get banner properties"), + content: _t("Select the parent container to get the global options of the banner."), + popover: { fixed: true }, + }, + { + element: '.oe_overlay_options .oe_options:visible', + placement: 'left', + title: _t("Customize the banner"), + content: _t("Customize any block through this menu. Try to change the background of the banner."), + popover: { next: _t("Continue") }, + }, + { + waitNot: '.popover.tour', + element: 'button[data-action=snippet]', + placement: 'bottom', + title: _t("Add Another Block"), + content: _t("Let's add another building block to your page."), + popover: { fixed: true }, + }, + { + snippet: '#snippet_structure .oe_snippet:eq(6)', + placement: 'bottom', + title: _t("Drag & Drop This Block"), + content: _t("Drag the 'Features' block and drop it below the banner."), + popover: { fixed: true }, + }, + { + waitFor: '.oe_overlay_options .oe_options:visible', + element: 'button[data-action=save]', + placement: 'right', + title: _t("Save your modifications"), + content: _t("Publish your page by clicking on the 'Save' button."), + popover: { fixed: true }, + }, + { + waitFor: 'button[data-action=edit]:visible', + title: _t("Good Job!"), + content: _t("Well done, you created your homepage."), + popover: { next: _t("Continue") }, + }, + { + waitNot: '.popover.tour', + element: 'a[data-action=show-mobile-preview]', + placement: 'bottom', + title: _t("Test Your Mobile Version"), + content: _t("Let's check how your homepage looks like on mobile devices."), + popover: { fixed: true }, + }, + { + element: '.modal:has(#mobile-viewport) button[data-dismiss=modal]', + placement: 'right', + title: _t("Check Mobile Preview"), + content: _t("Scroll to check rendering and then close the mobile preview."), + popover: { next: _t("Continue") }, + }, + { + waitNot: '.modal', + element: '#content-menu-button', + placement: 'left', + title: _t("Add new pages and menus"), + content: _t("The 'Content' menu allows you to add pages or add the top menu."), + popover: { next: _t("Close Tutorial") }, + }, + ] }); }()); diff --git a/addons/website/static/src/js/website.tour.js b/addons/website/static/src/js/website.tour.js index 911b6c7431a..2a661b4cc9b 100644 --- a/addons/website/static/src/js/website.tour.js +++ b/addons/website/static/src/js/website.tour.js @@ -6,7 +6,7 @@ if (typeof openerp === "undefined") { var error = "openerp is undefined" + "\nhref: " + window.location.href + "\nreferrer: " + document.referrer - + "\nlocalStorage: " + JSON.stringify(window.localStorage); + + "\nlocalStorage: " + window.localStorage.getItem("tour"); if (typeof $ !== "undefined") { error += '\n\n' + $("body").html(); } @@ -15,7 +15,7 @@ if (typeof openerp === "undefined") { var website = window.openerp.website; -// don't rewrite website.Tour in test mode +// don't rewrite T in test mode if (typeof website.Tour !== "undefined") { return; } @@ -23,40 +23,26 @@ if (typeof website.Tour !== "undefined") { // don't need template to use bootstrap Tour in automatic mode if (typeof QWeb2 !== "undefined") { website.add_template_file('/website/static/src/xml/website.tour.xml'); - } -// don't need to use bootstrap Tour to launch an automatic tour -function bootstrap_tour_stub () { - if (typeof Tour === "undefined") { - window.Tour = function Tour() {}; - Tour.prototype.addSteps = function () {}; - Tour.prototype.end = function () {}; - Tour.prototype.goto = function () {}; - } -} - - - if (website.EditorBar) { website.EditorBar.include({ tours: [], start: function () { var self = this; var menu = $('#help-menu'); - _.each(this.tours, function (tour) { + _.each(T.tours, function (tour) { + if (tour.mode === "test") { + return; + } var $menuItem = $($.parseHTML('
  • '+tour.name+'
  • ')); $menuItem.click(function () { - tour.reset(); - tour.run(); + T.reset(); + T.run(tour.id); }); menu.append($menuItem); }); return this._super(); - }, - registerTour: function (tour) { - website.Tour.add(tour); - this.tours.push(tour); } }); } @@ -94,351 +80,401 @@ $.ajaxSetup({ } }); -website.Tour = openerp.Class.extend({ - steps: [], - defaultDelay: 50, //ms - defaultOverLaps: 5000, //ms - localStorage: window.localStorage, - init: function () {}, +///////////////////////////////////////////////// - run: function (automatic) { - this.reset(); +var localStorage = window.localStorage; - for (var k in this.localStorage) { - if (!k.indexOf("tour-") && k.indexOf("-test") > -1) return; - } - - website.Tour.busy = true; - - if (automatic) { - this.localStorage.setItem("tour-"+this.id+"-test-automatic", true); +var T = website.Tour = { + tours: {}, + defaultDelay: 50, + retryRunningDelay: 1000, + errorDelay: 5000, + state: null, + $element: null, + timer: null, + testtimer: null, + currentTimer: null, + register: function (tour) { + if (tour.mode !== "test") tour.mode = "tutorial"; + T.tours[tour.id] = tour; + }, + run: function (tour_id, mode) { + var tour = T.tours[tour_id]; + this.time = new Date().getTime(); + if (tour.path && !window.location.href.match(new RegExp("("+T.getLang()+")?"+tour.path+"#?$", "i"))) { + var href = "/"+T.getLang()+tour.path; + console.log("Tour Begin from run method (redirection to "+href+")"); + T.saveState(tour.id, mode || tour.mode, -1); + window.location.href = href; } else { - this.localStorage.removeItem("tour-"+this.id+"-test-automatic"); + console.log("Tour Begin from run method"); + T.saveState(tour.id, mode || tour.mode, 0); + T.running(); } - this.automatic = automatic; - - if (this.path) { - // redirect to begin of the tour in function of the language - if (!this.testUrl(this.path+"(#.*)?$")) { - var path = this.path.split('#'); - window.location.href = "/"+this.getLang()+path[0] + "#tutorial."+this.id+"=true&" + path.slice(1, path.length).join("#"); - return; - } - } - - var self = this; - this.localStorage.setItem("tour-"+this.id+"-test", 0); - website.Tour.waitReady.call(this, function () {self._running();}); }, - running: function () { - var self = this; - if (+this.localStorage.getItem("tour-"+this.id+"-test") >= this.steps.length-1) { - this.endTour(); + registerSteps: function (tour) { + if (tour.register) { return; } + tour.register = true; - if (website.Tour.is_busy()) return; + for (var index=0, len=tour.steps.length; index 0 && tour.steps[index-1] && + tour.steps[index-1].popover && tour.steps[index-1].popover.next) { + step.waitNot = '.popover.tour.fade.in:visible'; } - return; - } - - var self = this; - website.Tour.waitReady.call(this, function () {self._running();}); - }, - _running: function () { - var stepId = this.localStorage.getItem("tour-"+this.id+"-test"); - - if (stepId != null) { - this.registerTour(); - this.nextStep(stepId, this.automatic ? this.autoNextStep : null, this.automatic ? this.defaultOverLaps : null); - } - }, - - reset: function () { - website.Tour.busy = false; - for (var k in this.steps) { - this.steps[k].busy = false; - } - clearTimeout(self.timer); - clearTimeout(self.testtimer); - - for (var k in this.localStorage) { - if (!k.indexOf("tour-") || !k.indexOf(this.id)) { - this.localStorage.removeItem(k); - } - } - - $('.popover.tour').remove(); - }, - - getLang: function () { - return $("html").attr("lang").replace(/-/, '_'); - }, - testUrl: function (url) { - return new RegExp("(/"+this.getLang()+")?"+url, "i").test(window.location.href); - }, - testPathUrl: function () { - if (!this.testPath || this.testUrl(this.testPath)) return true; - }, - checkRunningUrl: function () { - if (window.location.hash.indexOf("tutorial."+this.id+"=true") > -1) { - this.localStorage.setItem("tour-"+this.id+"-test", 0); - window.location.hash = window.location.hash.replace(/tutorial.+=true&?/, ''); - } - }, - - registerTour: function () { - if (this.automatic) { - bootstrap_tour_stub(); - } - this.tour = new Tour({ - name: this.id, - storage: this.tourStorage, - keyboard: false, - template: this.popover(), - onHide: function () { - window.scrollTo(0, 0); - } - }); - this.registerSteps(); - }, - registerSteps: function () { - for (var index=0, len=this.steps.length; index 0 && this.steps[index-1] && - this.steps[index-1].popover && this.steps[index-1].popover.next) { - step.waitNot = '.popover.tour:visible'; - } - if (!step.waitFor && index > 0 && this.steps[index-1].snippet) { + if (!step.waitFor && index > 0 && tour.steps[index-1].snippet) { step.waitFor = '.oe_overlay_options .oe_options:visible'; } - step._title = step._title || step.title; - step.title = this.popoverTitle({ title: step._title }); - step.template = step.template || this.popover( step.popover ); - if (!step.element) step.orphan = true; - if (step.snippet) { + var snippet = step.element && step.element.match(/#oe_snippets (.*) \.oe_snippet_thumbnail/); + if (snippet) { + step.snippet = snippet[1]; + } else if (step.snippet) { step.element = '#oe_snippets '+step.snippet+' .oe_snippet_thumbnail'; } + if (!step.element) { + step.element = "body"; + step.orphan = true; + step.backdrop = true; + } } - - if (this.steps[index-1] && - this.steps[index-1].popover && this.steps[index-1].popover.next) { + if (tour.steps[index-1] && + tour.steps[index-1].popover && tour.steps[index-1].popover.next) { var step = { - stepId: ""+index, - waitNot: '.popover.tour:visible' + _title: "", + id: index, + waitNot: '.popover.tour.fade.in:visible' }; - this.steps.push(step); + tour.steps.push(step); } - this.tour.addSteps(this.steps); + // rendering bootstrap tour and popover + if (tour.mode !== "test") { + for (var index=0, len=tour.steps.length; index
    '); + } + + if (step.backdrop || $element.parents("#website-top-navbar, .modal").size()) { + $tip.css("z-index", 2010); + } + + // button click event + $tip.find("button") + .one("click", function () { + step.busy = true; + if (!$(this).is("[data-role='next']")) { + clearTimeout(T.timer); + T.endTour(); + } + T.closePopover(); + }); + + T.repositionPopover(); + }, + repositionPopover: function() { + var popover = T.$element.data("bs.popover"); + var $tip = T.$element.data("bs.popover").tip(); + + if (popover.options.orphan) { + return $tip.css("top", $(window).outerHeight() / 2 - $tip.outerHeight() / 2); + } + + var offsetBottom, offsetHeight, offsetRight, offsetWidth, originalLeft, originalTop, tipOffset; + offsetWidth = $tip[0].offsetWidth; + offsetHeight = $tip[0].offsetHeight; + tipOffset = $tip.offset(); + originalLeft = tipOffset.left; + originalTop = tipOffset.top; + offsetBottom = $(document).outerHeight() - tipOffset.top - $tip.outerHeight(); + if (offsetBottom < 0) { + tipOffset.top = tipOffset.top + offsetBottom; + } + offsetRight = $("html").outerWidth() - tipOffset.left - $tip.outerWidth(); + if (offsetRight < 0) { + tipOffset.left = tipOffset.left + offsetRight; + } + if (tipOffset.top < 0) { + tipOffset.top = 0; + } + if (tipOffset.left < 0) { + tipOffset.left = 0; + } + $tip.offset(tipOffset); + if (popover.options.placement === "bottom" || popover.options.placement === "top") { + var left = T.$element.offset().left + T.$element.outerWidth()/2 - tipOffset.left; + $tip.find(".arrow").css("left", left ? left + "px" : ""); + } else if (popover.options.placement !== "auto") { + var top = T.$element.offset().top + T.$element.outerHeight()/2 - tipOffset.top; + $tip.find(".arrow").css("top", top ? top + "px" : ""); + } + }, + popoverTitle: function (tour, options) { + return openerp.qweb ? openerp.qweb.render('website.tour_popover_title', options) : options.title; + }, popover: function (options) { - try { - return openerp.qweb.render('website.tour_popover', options); - } catch (e) { - if (!this.automatic) throw e; - return ""; - } + return openerp.qweb ? openerp.qweb.render('website.tour_popover', options) : options.title; + }, + getLang: function () { + return $("html").attr("lang").replace(/-/, '_'); + }, + getState: function () { + var state = JSON.parse(localStorage.getItem("tour") || 'false') || {}; + if (state) { this.time = state.time; } + var tour_id,mode,step_id; + if (!state.id && window.location.href.indexOf("#tutorial.") > -1) { + state = { + "id": window.location.href.match(/#tutorial\.(.*)=true/)[1], + "mode": "tutorial", + "step_id": 0 + }; + window.location.hash = ""; + console.log("Tour Begin from url hash"); + T.saveState(state.id, state.mode, state.step_id); + } + if (!state.id) { + return; + } + state.tour = T.tours[state.id]; + state.step = state.tour && state.tour.steps[state.step_id === -1 ? 0 : state.step_id]; + return state; + }, + error: function (step, message) { + var state = T.getState(); + message += '\n tour: ' + state.id + + '\n step: ' + step.id + ": '" + (step._title || step.title) + "'" + + '\n href: ' + window.location.href + + '\n referrer: ' + document.referrer + + '\n element: ' + Boolean(!step.element || ($(step.element).size() && $(step.element).is(":visible") && !$(step.element).is(":hidden"))) + + '\n waitNot: ' + Boolean(!step.waitNot || !$(step.waitNot).size()) + + '\n waitFor: ' + Boolean(!step.waitFor || $(step.waitFor).size()) + + "\n localStorage: " + JSON.stringify(localStorage) + + '\n\n' + $("body").html(); + T.reset(); + throw new Error(message); + }, + lists: function () { + var tour_ids = []; + for (var k in T.tours) { + tour_ids.push(k); + } + return tour_ids; + }, + saveState: function (tour_id, mode, step_id) { + localStorage.setItem("tour", JSON.stringify({"id":tour_id, "mode":mode, "step_id":step_id || 0, "time": this.time})); + }, + reset: function () { + var state = T.getState(); + if (state) { + for (var k in state.tour.steps) { + state.tour.steps[k].busy = false; + } + } + localStorage.removeItem("tour"); + clearTimeout(T.timer); + clearTimeout(T.testtimer); + T.closePopover(); + }, + running: function () { + function run () { + var state = T.getState(); + if (!state) return; + if (state.tour) { + console.log("Tour '"+state.id+"' is running"); + T.registerSteps(state.tour); + T.nextStep(); + } else { + console.log("Tour '"+state.id+"' wait for running (tour undefined)"); + setTimeout(T.running, state.mode === "test" ? T.defaultDelay : T.retryRunningDelay); + } + } + setTimeout(function () { + if ($.ajaxBusy) { + $(document).ajaxStop(run); + } else { + run(); + } + },0); }, - - timer: null, - testtimer: null, check: function (step) { return (step && (!step.element || ($(step.element).size() && $(step.element).is(":visible") && !$(step.element).is(":hidden"))) && (!step.waitNot || !$(step.waitNot).size()) && (!step.waitFor || $(step.waitFor).size())); }, - waitNextStep: function (step, callback, overlaps) { - var self = this; + waitNextStep: function () { + var state = T.getState(); var time = new Date().getTime(); var timer; + var next = state.tour.steps[state.step.id+1]; + var overlaps = state.mode === "test" ? T.errorDelay : 0; window.onbeforeunload = function () { - clearTimeout(self.timer); - clearTimeout(self.testtimer); + clearTimeout(T.timer); + clearTimeout(T.testtimer); }; - // check popover activity - $(".popover.tour button") - .off() - .on("click", function () { - var help = $("#help-menu-button"); - var offset = help.offset(); - var left = (offset.left > 0) ? (offset.left + help.width()) : offset.left; - var top = (help.height() > 0) ? (offset.top + help.height()) : offset.top; - - if ($(this).is("[data-role='next']") && step.element) { - $(".popover.tour").remove(); - } - if (step.busy) return; - if (!$(this).is("[data-role='next']") || !step.element) { - $('.popover.tour') - .animate({ - left: left, - top: top, - width: '1px', - height: '1px', - opacity: 0 - }, 800, - function(){ - $(".popover.tour").remove(); - clearTimeout(self.timer); - step.busy = true; - self.tour.end(); - self.endTour(callback); - }); - } - }); - function checkNext () { - clearTimeout(self.timer); - if (step.busy) return; - if (self.check(step)) { - step.busy = true; + T.autoTogglePopover(); + + clearTimeout(T.timer); + if (T.check(next)) { + clearTimeout(T.currentTimer); // use an other timeout for cke dom loading setTimeout(function () { - self.nextStep(step.stepId, callback, overlaps); - }, self.defaultDelay); + T.nextStep(next); + }, T.defaultDelay); } else if (!overlaps || new Date().getTime() - time < overlaps) { - if (self.current.element) { - var $popover = $(".popover.tour"); - if(!$(self.current.element).is(":visible")) { - $popover.data("hide", true).fadeOut(300); - } else if($popover.data("hide")) { - $popover.data("hide", false).fadeIn(150); - } - } - self.timer = setTimeout(checkNext, self.defaultDelay); + T.timer = setTimeout(checkNext, T.defaultDelay); } else { - self.reset(); - throw new Error("Can't arrive to step " + step.stepId + ": '" + step._title + "'" - + '\nhref: ' + window.location.href - + '\nelement: ' + Boolean(!step.element || ($(step.element).size() && $(step.element).is(":visible") && !$(step.element).is(":hidden"))) - + '\nwaitNot: ' + Boolean(!step.waitNot || !$(step.waitNot).size()) - + '\nwaitFor: ' + Boolean(!step.waitFor || $(step.waitFor).size()) - + '\n\n' + $("body").html() - ); + T.error(next, "Can't reach the next step"); } } checkNext(); }, - step: function (stepId) { - var steps = this.steps.slice(0,this.steps.length), - step; - while (step = steps.shift()) { - if (!stepId || step.stepId === stepId) - return step; + nextStep: function (step) { + var state = T.getState(); + + if (!state) { + return; } - return null; - }, - next: function (stepId) { - var steps = this.steps.slice(0,this.steps.length), - step, next, index=0; - while (step = steps.shift()) { - if (!stepId || step.stepId === stepId) { - // clear popover (fix for boostrap tour if the element is removed before destroy popover) - $(".popover.tour").remove(); - // go to step in bootstrap tour - this.tour.goto(index); - if (step.onload) step.onload(); - next = steps.shift(); - break; - } - index++; + + step = step || state.step; + T.saveState(state.id, state.mode, step.id); + + if (step.id !== state.step_id) { + console.log("Tour Step: '" + (step._title || step.title) + "' (" + (new Date().getTime() - this.time) + "ms)"); } - return next; - }, - nextStep: function (stepId, callback, overlaps) { - var self = this; - if (!this.localStorage.getItem("tour-"+this.id+"-test")) return; - this.localStorage.setItem("tour-"+this.id+"-test", stepId || 0); + T.autoTogglePopover(true); - this.current = this.step(stepId); - var next = this.next(stepId); + if (step.onload) { + step.onload(); + } + var next = state.tour.steps[step.id+1]; if (next) { setTimeout(function () { - self.waitNextStep(next, callback, overlaps); - if (callback) setTimeout(function(){callback.call(self, next);}, self.defaultDelay); - }, next && next.wait || 0); + T.waitNextStep(); + if (state.mode === "test") { + setTimeout(function(){ + T.autoNextStep(state.tour, step); + }, T.defaultDelay); + } + }, next.wait || 0); } else { - this.endTour(); + T.endTour(); } }, endTour: function () { - var test = parseInt(this.localStorage.getItem("tour-"+this.id+"-test"),10) >= this.steps.length-1; - this.reset(); + var state = T.getState(); + var test = state.step.id >= state.tour.steps.length-1; + T.reset(); if (test) { console.log('ok'); } else { console.log('error'); } }, - autoNextStep: function () { - var self = this; - clearTimeout(self.testtimer); + autoNextStep: function (tour, step) { + clearTimeout(T.testtimer); function autoStep () { - var step = self.current; if (!step) return; if (step.autoComplete) { step.autoComplete(tour); } - var $popover = $(".popover.tour"); - if ($popover.find("button[data-role='next']:visible").size()) { - $popover.find("button[data-role='next']:visible").click(); - $popover.remove(); - } + $(".popover.tour [data-role='next']").click(); var $element = $(step.element); if (!$element.size()) return; if (step.snippet) { - - var selector = '#oe_snippets '+step.snippet+' .oe_snippet_thumbnail'; - self.autoDragAndDropSnippet(selector); - - } else if (step.element.match(/#oe_snippets .* \.oe_snippet_thumbnail/)) { - - self.autoDragAndDropSnippet($element); + + T.autoDragAndDropSnippet($element); } else if ($element.is(":visible")) { @@ -473,7 +509,7 @@ website.Tour = openerp.Class.extend({ } } - self.testtimer = setTimeout(autoStep, 100); + T.testtimer = setTimeout(autoStep, 100); }, autoDragAndDropSnippet: function (selector) { var $thumbnail = $(selector).first(); @@ -483,64 +519,11 @@ website.Tour = openerp.Class.extend({ var $dropZone = $(".oe_drop_zone").first(); var dropPosition = $dropZone.position(); $dropZone.trigger($.Event("mouseup", { which: 1, pageX: dropPosition.left, pageY: dropPosition.top })); - }, - -}); - - -website.Tour.tours = {}; -website.Tour.busy = false; -website.Tour.add = function (tour) { - website.Tour.waitReady(function () { - tour = tour.id ? tour : new tour(); - if (!website.Tour.tours[tour.id]) { - website.Tour.tours[tour.id] = tour; - tour.running(); - } - }); -}; -website.Tour.get = function (id) { - return website.Tour.tours[id]; -}; -website.Tour.each = function (callback) { - website.Tour.waitReady(function () { - for (var k in website.Tour.tours) { - callback.call(website.Tour.tours[k]); - } - }); -}; -website.Tour.waitReady = function (callback) { - var self = this; - $(document).ready(function () { - if ($.ajaxBusy) { - $(document).ajaxStop(function() { - setTimeout(function () { - callback.call(self); - },0); - }); - } - else { - setTimeout(function () { - callback.call(self); - },0); - } - }); -}; -website.Tour.run_test = function (id) { - website.Tour.waitReady(function () { - if (!website.Tour.is_busy()) { - website.Tour.tours[id].run(true); - } - }); -}; -website.Tour.is_busy = function () { - for (var k in this.localStorage) { - if (!k.indexOf("tour-")) { - return k; - } } - return website.Tour.busy; }; +//$(document).ready(T.running); +website.ready().then(T.running); + }()); diff --git a/addons/website/tests/test_ui.py b/addons/website/tests/test_ui.py index 54cd8a73a67..7eb88d00df3 100644 --- a/addons/website/tests/test_ui.py +++ b/addons/website/tests/test_ui.py @@ -8,6 +8,6 @@ class TestUi(openerp.tests.HttpCase): self.phantom_js("/", "console.log('ok')", "openerp.website.editor", login='admin') def test_04_admin_tour_banner(self): - self.phantom_js("/", "openerp.website.Tour.run_test('banner')", "openerp.website.Tour.tours.banner", login='admin') + self.phantom_js("/", "openerp.website.Tour.run('banner', 'test')", "openerp.website.Tour.tours.banner", login='admin') # vim:et: diff --git a/addons/website/views/website_templates.xml b/addons/website/views/website_templates.xml index 324ae70f9e6..dc7ce76b8f5 100644 --- a/addons/website/views/website_templates.xml +++ b/addons/website/views/website_templates.xml @@ -256,7 +256,6 @@ - @@ -268,7 +267,6 @@ - diff --git a/addons/website_blog/static/src/js/website.tour.blog.js b/addons/website_blog/static/src/js/website.tour.blog.js index 3470e2e383b..050bf549225 100644 --- a/addons/website_blog/static/src/js/website.tour.blog.js +++ b/addons/website_blog/static/src/js/website.tour.blog.js @@ -4,117 +4,105 @@ var website = openerp.website; var _t = openerp._t; - website.EditorBar.include({ - start: function () { - this.registerTour(new website.Tour.Blog(this)); - return this._super(); - }, - }); - - website.Tour.Blog = website.Tour.extend({ - id: 'blog', - name: "Create a blog post", - testPath: '/(blog|blogpost)', - init: function () { - var self = this; - self.steps = [ - { - title: _t("New Blog Post"), - content: _t("Let's go through the first steps to write beautiful blog posts."), - popover: { next: _t("Start Tutorial"), end: _t("Skip") }, - }, - { - element: '#content-menu-button', - placement: 'left', - title: _t("Add Content"), - content: _t("Use this 'Content' menu to create a new blog post like any other document (page, menu, products, event, ...)."), - popover: { fixed: true }, - }, - { - element: 'a[data-action=new_blog_post]', - placement: 'left', - title: _t("New Blog Post"), - content: _t("Select this menu item to create a new blog post."), - popover: { fixed: true }, - }, - { - element: '.modal:has(#editor_new_blog) button.btn-primary', - placement: 'right', - title: _t("Create Blog Post"), - content: _t("Click Continue to create the blog post."), - }, - { - waitFor: 'body:has(button[data-action=save]:visible):has(.js_blog)', - title: _t("Blog Post Created"), - content: _t("This is your new blog post. Let's edit it."), - popover: { next: _t("Continue") }, - }, - { - element: 'h1[data-oe-expression="blog_post.name"]', - placement: 'bottom', - sampleText: 'New Blog', - title: _t("Set a Title"), - content: _t("Click on this area and set a catchy title for your blog post."), - }, - { - waitNot: '#wrap h1[data-oe-model="blog.post"]:contains("Blog Post Title")', - element: 'button[data-action=snippet]', - placement: 'left', - title: _t("Layout Your Blog Post"), - content: _t("Use well designed building blocks to structure the content of your blog. Click 'Insert Blocks' to add new content."), - popover: { fixed: true }, - }, - { - snippet: '#snippet_structure .oe_snippet:eq(2)', - placement: 'bottom', - title: _t("Drag & Drop a Block"), - content: _t("Drag this block and drop it in your page."), - popover: { fixed: true }, - }, - { - element: 'button[data-action=snippet]', - placement: 'bottom', - title: _t("Add Another Block"), - content: _t("Let's add another block to your post."), - popover: { fixed: true }, - }, - { - snippet: '#snippet_structure .oe_snippet:eq(4)', - placement: 'bottom', - title: _t("Drag & Drop a block"), - content: _t("Drag this block and drop it below the image block."), - popover: { fixed: true }, - }, - { - element: '.oe_active .oe_snippet_remove', - placement: 'top', - title: _t("Delete the block"), - content: _t("From this toolbar you can move, duplicate or delete the selected zone. Click on the garbage can image to delete the block. Or click on the Title and delete it."), - }, - { - waitNot: '.oe_active .oe_snippet_remove:visible', - element: 'button[data-action=save]', - placement: 'right', - title: _t("Save Your Blog"), - content: _t("Click the Save button to record changes on the page."), - popover: { fixed: true }, - }, - { - waitFor: 'button[data-action=edit]:visible', - element: 'button.btn-danger.js_publish_btn', - placement: 'top', - title: _t("Publish Your Post"), - content: _t("Your blog post is not yet published. You can update this draft version and publish it once you are ready."), - }, - { - waitFor: '.js_publish_management button.js_publish_btn.btn-success:visible', - title: "Thanks!", - content: _t("This tutorial is finished. To discover more features, improve the content of this page and try the Promote button in the top right menu."), - popover: { next: _t("Close Tutorial") }, - }, - ]; - return this._super(); - }, + website.Tour.register({ + id: 'blog', + name: _t("Create a blog post"), + steps: [ + { + title: _t("New Blog Post"), + content: _t("Let's go through the first steps to write beautiful blog posts."), + popover: { next: _t("Start Tutorial"), end: _t("Skip") }, + }, + { + element: '#content-menu-button', + placement: 'left', + title: _t("Add Content"), + content: _t("Use this 'Content' menu to create a new blog post like any other document (page, menu, products, event, ...)."), + popover: { fixed: true }, + }, + { + element: 'a[data-action=new_blog_post]', + placement: 'left', + title: _t("New Blog Post"), + content: _t("Select this menu item to create a new blog post."), + popover: { fixed: true }, + }, + { + element: '.modal:has(#editor_new_blog) button.btn-primary', + placement: 'right', + title: _t("Create Blog Post"), + content: _t("Click Continue to create the blog post."), + }, + { + waitFor: 'body:has(button[data-action=save]:visible):has(.js_blog)', + title: _t("Blog Post Created"), + content: _t("This is your new blog post. Let's edit it."), + popover: { next: _t("Continue") }, + }, + { + element: 'h1[data-oe-expression="blog_post.name"]', + placement: 'bottom', + sampleText: 'New Blog', + title: _t("Set a Title"), + content: _t("Click on this area and set a catchy title for your blog post."), + }, + { + waitNot: '#wrap h1[data-oe-model="blog.post"]:contains("Blog Post Title")', + element: 'button[data-action=snippet]', + placement: 'left', + title: _t("Layout Your Blog Post"), + content: _t("Use well designed building blocks to structure the content of your blog. Click 'Insert Blocks' to add new content."), + popover: { fixed: true }, + }, + { + snippet: '#snippet_structure .oe_snippet:eq(2)', + placement: 'bottom', + title: _t("Drag & Drop a Block"), + content: _t("Drag this block and drop it in your page."), + popover: { fixed: true }, + }, + { + element: 'button[data-action=snippet]', + placement: 'bottom', + title: _t("Add Another Block"), + content: _t("Let's add another block to your post."), + popover: { fixed: true }, + }, + { + snippet: '#snippet_structure .oe_snippet:eq(4)', + placement: 'bottom', + title: _t("Drag & Drop a block"), + content: _t("Drag this block and drop it below the image block."), + popover: { fixed: true }, + }, + { + element: '.oe_active .oe_snippet_remove', + placement: 'top', + title: _t("Delete the block"), + content: _t("From this toolbar you can move, duplicate or delete the selected zone. Click on the garbage can image to delete the block. Or click on the Title and delete it."), + }, + { + waitNot: '.oe_active .oe_snippet_remove:visible', + element: 'button[data-action=save]', + placement: 'right', + title: _t("Save Your Blog"), + content: _t("Click the Save button to record changes on the page."), + popover: { fixed: true }, + }, + { + waitFor: 'button[data-action=edit]:visible', + element: 'button.btn-danger.js_publish_btn', + placement: 'top', + title: _t("Publish Your Post"), + content: _t("Your blog post is not yet published. You can update this draft version and publish it once you are ready."), + }, + { + waitFor: '.js_publish_management button.js_publish_btn.btn-success:visible', + title: "Thanks!", + content: _t("This tutorial is finished. To discover more features, improve the content of this page and try the Promote button in the top right menu."), + popover: { next: _t("Close Tutorial") }, + }, + ] }); }()); diff --git a/addons/website_blog/tests/test_ui.py b/addons/website_blog/tests/test_ui.py index e99884ba4b1..b34ef25c002 100644 --- a/addons/website_blog/tests/test_ui.py +++ b/addons/website_blog/tests/test_ui.py @@ -2,5 +2,5 @@ import openerp.tests class TestUi(openerp.tests.HttpCase): def test_admin(self): - self.phantom_js("/", "openerp.website.Tour.run_test('blog')", "openerp.website.Tour") + self.phantom_js("/", "openerp.website.Tour.run('blog', 'test')", "openerp.website.Tour.tours.blog") diff --git a/addons/website_event/static/src/js/website.tour.event.js b/addons/website_event/static/src/js/website.tour.event.js index ef013398acb..07a12d81f34 100644 --- a/addons/website_event/static/src/js/website.tour.event.js +++ b/addons/website_event/static/src/js/website.tour.event.js @@ -4,115 +4,103 @@ var website = openerp.website; var _t = openerp._t; - website.EditorBar.include({ - start: function () { - this.registerTour(new website.EventTour(this)); - return this._super(); - }, - }); - - website.EventTour = website.Tour.extend({ - id: 'event', - name: "Create an event", - testPath: '/event(/[0-9]+/register)?', - init: function (editor) { - var self = this; - self.steps = [ - { - title: _t("Create an Event"), - content: _t("Let's go through the first steps to publish a new event."), - popover: { next: _t("Start Tutorial"), end: _t("Skip It") }, - }, - { - element: '#content-menu-button', - placement: 'left', - title: _t("Add Content"), - content: _t("The Content menu allows you to create new pages, events, menus, etc."), - popover: { fixed: true }, - }, - { - element: 'a[data-action=new_event]', - placement: 'left', - title: _t("New Event"), - content: _t("Click here to create a new event."), - popover: { fixed: true }, - }, - { - element: '.modal #editor_new_event input[type=text]', - sampleText: 'Advanced Technical Training', - placement: 'right', - title: _t("Create an Event Name"), - content: _t("Create a name for your new event and click 'Continue'. e.g: Technical Training"), - }, - { - waitNot: '.modal input[type=text]:not([value!=""])', - element: '.modal button.btn-primary', - placement: 'right', - title: _t("Create Event"), - content: _t("Click Continue to create the event."), - }, - { - waitFor: 'body:has(button[data-action=save]:visible):has(.js_event)', - title: _t("New Event Created"), - content: _t("This is your new event page. We will edit the event presentation page."), - popover: { next: _t("Continue") }, - }, - { - element: 'button[data-action=snippet]', - placement: 'bottom', - title: _t("Layout your event"), - content: _t("Insert blocks to layout the body of your event."), - popover: { fixed: true }, - }, - { - snippet: '#snippet_structure .oe_snippet:eq(2)', - placement: 'bottom', - title: _t("Drag & Drop a block"), - content: _t("Drag the 'Image-Text' block and drop it in your page."), - popover: { fixed: true }, - }, - { - - element: 'button[data-action=snippet]', - placement: 'bottom', - title: _t("Layout your event"), - content: _t("Insert another block to your event."), - popover: { fixed: true }, - }, - { - snippet: '#snippet_structure .oe_snippet:eq(4)', - placement: 'bottom', - title: _t("Drag & Drop a block"), - content: _t("Drag the 'Text Block' in your event page."), - popover: { fixed: true }, - }, - { - element: 'button[data-action=save]', - placement: 'right', - title: _t("Save your modifications"), - content: _t("Once you click on save, your event is updated."), - popover: { fixed: true }, - }, - { - waitFor: 'button[data-action=edit]:visible', - element: 'button.btn-danger.js_publish_btn', - placement: 'top', - title: _t("Publish your event"), - content: _t("Click to publish your event."), - }, - { - waitFor: '.js_publish_management button.js_publish_btn.btn-success:visible', - element: '.js_publish_management button[data-toggle="dropdown"]', - placement: 'left', - title: _t("Customize your event"), - content: _t("Click here to customize your event further."), - }, - { - element: '.js_publish_management ul>li>a:last:visible', - }, - ]; - return this._super(); - } + website.Tour.register({ + id: 'event', + name: _t("Create an event"), + steps: [ + { + title: _t("Create an Event"), + content: _t("Let's go through the first steps to publish a new event."), + popover: { next: _t("Start Tutorial"), end: _t("Skip It") }, + }, + { + element: '#content-menu-button', + placement: 'left', + title: _t("Add Content"), + content: _t("The Content menu allows you to create new pages, events, menus, etc."), + popover: { fixed: true }, + }, + { + element: 'a[data-action=new_event]', + placement: 'left', + title: _t("New Event"), + content: _t("Click here to create a new event."), + popover: { fixed: true }, + }, + { + element: '.modal #editor_new_event input[type=text]', + sampleText: 'Advanced Technical Training', + placement: 'right', + title: _t("Create an Event Name"), + content: _t("Create a name for your new event and click 'Continue'. e.g: Technical Training"), + }, + { + waitNot: '.modal input[type=text]:not([value!=""])', + element: '.modal button.btn-primary', + placement: 'right', + title: _t("Create Event"), + content: _t("Click Continue to create the event."), + }, + { + waitFor: 'body:has(button[data-action=save]:visible):has(.js_event)', + title: _t("New Event Created"), + content: _t("This is your new event page. We will edit the event presentation page."), + popover: { next: _t("Continue") }, + }, + { + element: 'button[data-action=snippet]', + placement: 'bottom', + title: _t("Layout your event"), + content: _t("Insert blocks to layout the body of your event."), + popover: { fixed: true }, + }, + { + snippet: '#snippet_structure .oe_snippet:eq(2)', + placement: 'bottom', + title: _t("Drag & Drop a block"), + content: _t("Drag the 'Image-Text' block and drop it in your page."), + popover: { fixed: true }, + }, + { + + element: 'button[data-action=snippet]', + placement: 'bottom', + title: _t("Layout your event"), + content: _t("Insert another block to your event."), + popover: { fixed: true }, + }, + { + snippet: '#snippet_structure .oe_snippet:eq(4)', + placement: 'bottom', + title: _t("Drag & Drop a block"), + content: _t("Drag the 'Text Block' in your event page."), + popover: { fixed: true }, + }, + { + element: 'button[data-action=save]', + placement: 'right', + title: _t("Save your modifications"), + content: _t("Once you click on save, your event is updated."), + popover: { fixed: true }, + }, + { + waitFor: 'button[data-action=edit]:visible', + element: 'button.btn-danger.js_publish_btn', + placement: 'top', + title: _t("Publish your event"), + content: _t("Click to publish your event."), + }, + { + waitFor: '.js_publish_management button.js_publish_btn.btn-success:visible', + element: '.js_publish_management button[data-toggle="dropdown"]', + placement: 'left', + title: _t("Customize your event"), + content: _t("Click here to customize your event further."), + }, + { + element: '.js_publish_management ul>li>a:last:visible', + }, + ] }); }()); diff --git a/addons/website_event/tests/test_ui.py b/addons/website_event/tests/test_ui.py index c4e884c0325..96a17a91563 100644 --- a/addons/website_event/tests/test_ui.py +++ b/addons/website_event/tests/test_ui.py @@ -2,5 +2,5 @@ import openerp.tests class TestUi(openerp.tests.HttpCase): def test_admin(self): - self.phantom_js("/", "openerp.website.Tour.run_test('event')", "openerp.website.Tour") + self.phantom_js("/", "openerp.website.Tour.run('event', 'test')", "openerp.website.Tour.tours.event") diff --git a/addons/website_event_sale/static/src/js/website.tour.event_sale.js b/addons/website_event_sale/static/src/js/website.tour.event_sale.js index 48b9b62b349..333481bc349 100644 --- a/addons/website_event_sale/static/src/js/website.tour.event_sale.js +++ b/addons/website_event_sale/static/src/js/website.tour.event_sale.js @@ -3,77 +3,63 @@ var website = openerp.website; - website.Tour.EventSaleTest = website.Tour.extend({ - id: 'event_buy_tickets', + website.Tour.register({ + id: 'event_buy_tickets', name: "Try to buy tickets for event", path: '/event', - init: function () { - var self = this; - self.steps = [ - { - title: "select event", - element: 'a[href*="/event"]:contains("Open Days in Los Angeles")', + mode: 'test', + steps: [ + { + title: "select event", + element: 'a[href*="/event"]:contains("Conference on Business Applications"):first', + }, + { + waitNot: 'a[href*="/event"]:contains("Conference on Business Applications")', + title: "select 2 Standard tickets", + element: 'select:eq(0)', + sampleText: '2', + }, + { + title: "select 3 VIP tickets", + waitFor: 'select:eq(0) option:contains(2):selected', + element: 'select:eq(1)', + sampleText: '3', + }, + { + title: "Order Now", + waitFor: 'select:eq(1) option:contains(3):selected', + element: '.btn-primary:contains("Order Now")', + }, + { + title: "Complete checkout", + waitFor: '#top_menu .my_cart_quantity:contains(5)', + element: 'form[action="/shop/confirm_order"] .btn:contains("Confirm")', + autoComplete: function (tour) { + if ($("input[name='name']").val() === "") + $("input[name='name']").val("website_sale-test-shoptest"); + if ($("input[name='email']").val() === "") + $("input[name='email']").val("website_event_sale_test_shoptest@websiteeventsaletest.optenerp.com"); + $("input[name='phone']").val("123"); + $("input[name='street']").val("123"); + $("input[name='city']").val("123"); + $("input[name='zip']").val("123"); + $("select[name='country_id']").val("21"); }, - { - title: "go to register page", - waitNot: 'a[href*="/event"]:contains("Functional Webinar")', - onload: function () { - // use onload if website_event_track is installed - if (!$('form:contains("Ticket Type")').size()) { - window.location.href = $('a[href*="/event"][href*="/register"]').attr("href"); - } - }, - }, - { - title: "select 2 Standard tickets", - element: 'select[name="ticket-1"]', - sampleText: '2', - }, - { - title: "select 3 VIP tickets", - waitFor: 'select[name="ticket-1"] option:contains(2):selected', - element: 'select[name="ticket-2"]', - sampleText: '3', - }, - { - title: "Order Now", - waitFor: 'select[name="ticket-2"] option:contains(3):selected', - element: '.btn-primary:contains("Order Now")', - }, - { - title: "Complete checkout", - waitFor: '#top_menu .my_cart_quantity:contains(5)', - element: 'form[action="/shop/confirm_order"] .btn:contains("Confirm")', - onload: function (tour) { - if ($("input[name='name']").val() === "") - $("input[name='name']").val("website_sale-test-shoptest"); - if ($("input[name='email']").val() === "") - $("input[name='email']").val("website_event_sale_test_shoptest@websiteeventsaletest.optenerp.com"); - $("input[name='phone']").val("123"); - $("input[name='street']").val("123"); - $("input[name='city']").val("123"); - $("input[name='zip']").val("123"); - $("select[name='country_id']").val("21"); - }, - }, - { - title: "select payment", - element: '#payment_method label:has(img[title="transfer"]) input', - }, - { - title: "Pay Now", - waitFor: '#payment_method label:has(input:checked):has(img[title="transfer"])', - element: '.oe_sale_acquirer_button .btn[name="submit"]:visible', - }, - { - title: "finish", - waitFor: '.oe_website_sale:contains("Thank you for your order")', - } - ]; - return this._super(); - }, + }, + { + title: "select payment", + element: '#payment_method label:has(img[title="Wire Transfer"]) input', + }, + { + title: "Pay Now", + waitFor: '#payment_method label:has(input:checked):has(img[title="Wire Transfer"])', + element: '.oe_sale_acquirer_button .btn[name="submit"]:visible', + }, + { + title: "finish", + waitFor: '.oe_website_sale:contains("Thank you for your order")', + } + ] }); - // for test without editor bar - website.Tour.add(website.Tour.EventSaleTest); }()); diff --git a/addons/website_event_sale/tests/__init__.py b/addons/website_event_sale/tests/__init__.py index c9d4e3399ba..bf8ba6321ad 100644 --- a/addons/website_event_sale/tests/__init__.py +++ b/addons/website_event_sale/tests/__init__.py @@ -1 +1 @@ -#import test_ui +import test_ui diff --git a/addons/website_event_sale/tests/test_ui.py b/addons/website_event_sale/tests/test_ui.py index b5950aaec54..3c3e643912a 100644 --- a/addons/website_event_sale/tests/test_ui.py +++ b/addons/website_event_sale/tests/test_ui.py @@ -1,19 +1,21 @@ +import os + import openerp.tests inject = [ - "./../../../website/static/src/js/website.tour.test.js", - "./../../../website_event_sale/static/src/js/website.tour.event_sale.js", + ("openerp.website.Tour", os.path.join(os.path.dirname(__file__), '../../website/static/src/js/website.tour.js')), + ("openerp.website.Tour.ShopTest", os.path.join(os.path.dirname(__file__), "../static/src/js/website.tour.event_sale.js")), ] @openerp.tests.common.at_install(False) @openerp.tests.common.post_install(True) class TestUi(openerp.tests.HttpCase): def test_admin(self): - self.phantom_js("/", "openerp.website.Tour.run_test('event_buy_tickets')", "openerp.website.Tour", inject=inject) + self.phantom_js("/", "openerp.website.Tour.run('event_buy_tickets', 'test')", "openerp.website.Tour.tours.event_buy_tickets", inject=inject) def test_demo(self): - self.phantom_js("/", "openerp.website.Tour.run_test('event_buy_tickets')", "openerp.website.Tour", login="demo", password="demo", inject=inject); + self.phantom_js("/", "openerp.website.Tour.run('event_buy_tickets', 'test')", "openerp.website.Tour.tours.event_buy_tickets", login="demo", password="demo", inject=inject); def test_public(self): - self.phantom_js("/", "openerp.website.Tour.run_test('event_buy_tickets')", "openerp.website.Tour", login=None, inject=inject); + self.phantom_js("/", "openerp.website.Tour.run('event_buy_tickets', 'test')", "openerp.website.Tour.tours.event_buy_tickets", login=None, inject=inject); diff --git a/addons/website_report/views/layouts.xml b/addons/website_report/views/layouts.xml index eb8683c9eb7..9952cdc46e1 100644 --- a/addons/website_report/views/layouts.xml +++ b/addons/website_report/views/layouts.xml @@ -38,7 +38,6 @@ - @@ -50,7 +49,6 @@ - diff --git a/addons/website_sale/static/src/js/website.tour.sale.js b/addons/website_sale/static/src/js/website.tour.sale.js index 0fa01addede..a957747c91b 100644 --- a/addons/website_sale/static/src/js/website.tour.sale.js +++ b/addons/website_sale/static/src/js/website.tour.sale.js @@ -3,92 +3,87 @@ var website = openerp.website; - website.Tour.ShopTest = website.Tour.extend({ - id: 'shop_buy_product', + website.Tour.register({ + id: 'shop_buy_product', name: "Try to buy products", path: '/shop', - init: function () { - var self = this; - self.steps = [ - { - title: "select ipod", - element: '.oe_product_cart a:contains("iPod")', + mode: 'test', + steps: [ + { + title: "select ipod", + element: '.oe_product_cart a:contains("iPod")', + }, + { + title: "select ipod 32Go", + element: 'input[name="product_id"]:not([checked])', + }, + { + title: "click on add to cart", + waitFor: 'input[name="product_id"]:eq(1)[checked]', + element: 'form[action="/shop/add_cart"] .btn', + }, + { + title: "add suggested", + element: 'form[action="/shop/add_cart"] .btn-link:contains("Add to Cart")', + }, + { + title: "add one more iPod", + waitFor: '.my_cart_quantity:contains(2)', + element: '#mycart_products tr:contains("iPod: 32 Gb") a.js_add_cart_json:eq(1)', + }, + { + title: "remove Headphones", + waitFor: '#mycart_products tr:contains("iPod: 32 Gb") input.js_quantity[value=2]', + element: '#mycart_products tr:contains("Apple In-Ear Headphones") a.js_add_cart_json:first', + }, + { + title: "set one iPod", + waitNot: '#mycart_products tr:contains("Apple In-Ear Headphones")', + element: '#mycart_products input.js_quantity', + sampleText: '1', + }, + { + title: "go to checkout", + waitFor: '#mycart_products input.js_quantity[value=1]', + element: 'a[href="/shop/checkout"]', + }, + { + title: "test with input error", + element: 'form[action="/shop/confirm_order"] .btn:contains("Confirm")', + onload: function (tour) { + $("input[name='phone']").val(""); }, - { - title: "select ipod 32Go", - element: 'input[name="product_id"]:not([checked])', + }, + { + title: "test without input error", + waitFor: 'form[action="/shop/confirm_order"] .has-error', + element: 'form[action="/shop/confirm_order"] .btn:contains("Confirm")', + onload: function (tour) { + if ($("input[name='name']").val() === "") + $("input[name='name']").val("website_sale-test-shoptest"); + if ($("input[name='email']").val() === "") + $("input[name='email']").val("website_sale_test_shoptest@websitesaletest.optenerp.com"); + $("input[name='phone']").val("123"); + $("input[name='street']").val("123"); + $("input[name='city']").val("123"); + $("input[name='zip']").val("123"); + $("select[name='country_id']").val("21"); }, - { - title: "click on add to cart", - waitFor: 'input[name="product_id"]:eq(1)[checked]', - element: 'form[action="/shop/add_cart"] .btn', - }, - { - title: "add suggested", - element: 'form[action="/shop/add_cart"] .btn-link:contains("Add to Cart")', - }, - { - title: "add one more iPod", - waitFor: '.my_cart_quantity:contains(2)', - element: '#mycart_products tr:contains("iPod: 32 Gb") a.js_add_cart_json:eq(1)', - }, - { - title: "remove Headphones", - waitFor: '#mycart_products tr:contains("iPod: 32 Gb") input.js_quantity[value=2]', - element: '#mycart_products tr:contains("Apple In-Ear Headphones") a.js_add_cart_json:first', - }, - { - title: "set one iPod", - waitNot: '#mycart_products tr:contains("Apple In-Ear Headphones")', - element: '#mycart_products input.js_quantity', - sampleText: '1', - }, - { - title: "go to checkout", - waitFor: '#mycart_products input.js_quantity[value=1]', - element: 'a[href="/shop/checkout"]', - }, - { - title: "test with input error", - element: 'form[action="/shop/confirm_order"] .btn:contains("Confirm")', - onload: function (tour) { - $("input[name='phone']").val(""); - }, - }, - { - title: "test without input error", - waitFor: 'form[action="/shop/confirm_order"] .has-error', - element: 'form[action="/shop/confirm_order"] .btn:contains("Confirm")', - onload: function (tour) { - if ($("input[name='name']").val() === "") - $("input[name='name']").val("website_sale-test-shoptest"); - if ($("input[name='email']").val() === "") - $("input[name='email']").val("website_sale_test_shoptest@websitesaletest.optenerp.com"); - $("input[name='phone']").val("123"); - $("input[name='street']").val("123"); - $("input[name='city']").val("123"); - $("input[name='zip']").val("123"); - $("select[name='country_id']").val("21"); - }, - }, - { - title: "select payment", - element: '#payment_method label:has(img[title="Wire Transfer"]) input', - }, - { - title: "Pay Now", - waitFor: '#payment_method label:has(input:checked):has(img[title="Wire Transfer"])', - element: '.oe_sale_acquirer_button .btn[name="submit"]:visible', - }, - { - title: "finish", - waitFor: '.oe_website_sale:contains("Thank you for your order")', - } - ]; - return this._super(); - }, + }, + { + title: "select payment", + element: '#payment_method label:has(img[title="Wire Transfer"]) input', + }, + { + title: "Pay Now", + waitFor: '#payment_method label:has(input:checked):has(img[title="Wire Transfer"])', + element: '.oe_sale_acquirer_button .btn[name="submit"]:visible', + }, + { + title: "finish", + waitFor: '.oe_website_sale:contains("Thank you for your order")', + } + ] }); - // for test without editor bar - website.Tour.add(website.Tour.ShopTest); }()); diff --git a/addons/website_sale/static/src/js/website.tour.shop.js b/addons/website_sale/static/src/js/website.tour.shop.js index 6291f2fc54e..3dd5b54b357 100644 --- a/addons/website_sale/static/src/js/website.tour.shop.js +++ b/addons/website_sale/static/src/js/website.tour.shop.js @@ -4,125 +4,114 @@ var website = openerp.website; var _t = openerp._t; - website.EditorBar.include({ - start: function () { - this.registerTour(new website.Tour.Shop(this)); - return this._super(); - }, - }); - - website.Tour.Shop = website.Tour.extend({ + website.Tour.register({ id: 'shop', - name: "Create a product", - testPath: '/shop', - init: function () { - var self = this; - self.steps = [ - { - title: _t("Welcome to your shop"), - content: _t("You successfully installed the e-commerce. This guide will help you to create your product and promote your sales."), - popover: { next: _t("Start Tutorial"), end: _t("Skip It") }, - }, - { - element: '#content-menu-button', - placement: 'left', - title: _t("Create your first product"), - content: _t("Click here to add a new product."), - popover: { fixed: true }, - }, - { - element: 'a[data-action=new_product]', - placement: 'left', - title: _t("Create a new product"), - content: _t("Select 'New Product' to create it and manage its properties to boost your sales."), - popover: { fixed: true }, - }, - { - element: '.modal #editor_new_product input[type=text]', - sampleText: 'New Product', - placement: 'right', - title: _t("Choose name"), - content: _t("Enter a name for your new product then click 'Continue'."), - }, - { - waitNot: '.modal input[type=text]:not([value!=""])', - element: '.modal button.btn-primary', - placement: 'right', - title: _t("Create Product"), - content: _t("Click Continue to create the product."), - }, - { - waitFor: 'body:has(button[data-action=save]:visible):has(.js_sale)', - title: _t("New product created"), - content: _t("This page contains all the information related to the new product."), - popover: { next: _t("Continue") }, - }, - { - element: '.product_price .oe_currency_value', - sampleText: '20.50', - placement: 'left', - title: _t("Change the price"), - content: _t("Edit the price of this product by clicking on the amount."), - }, - { - waitNot: '.product_price .oe_currency_value:containsExact(1.00)', - element: '#wrap img.product_detail_img', - placement: 'top', - title: _t("Update image"), - content: _t("Click here to set an image describing your product."), - }, - { - element: 'img[alt=ipad]', - placement: 'top', - title: _t("Select an Image"), - content: _t("Let's select an ipad image."), - }, - { - waitFor: '.media_selected img[alt=ipad]', - element: '.modal-content button.save', - placement: 'top', - title: _t("Save this Image"), - content: _t("Click on save to add the image to the product decsription."), - }, - { - waitNot: '.modal-content:visible', - element: 'button[data-action=snippet]', - placement: 'bottom', - title: _t("Describe the Product"), - content: _t("Insert blocks like text-image, or gallery to fully describe the product."), - popover: { fixed: true }, - }, - { - snippet: '#snippet_structure .oe_snippet:eq(7)', - placement: 'bottom', - title: _t("Drag & Drop a block"), - content: _t("Drag the 'Big Picture' block and drop it in your page."), - popover: { fixed: true }, - }, - { - element: 'button[data-action=save]', - placement: 'right', - title: _t("Save your modifications"), - content: _t("Once you click on save, your product is updated."), - popover: { fixed: true }, + name: _t("Create a product"), + steps: [ + { + title: _t("Welcome to your shop"), + content: _t("You successfully installed the e-commerce. This guide will help you to create your product and promote your sales."), + popover: { next: _t("Start Tutorial"), end: _t("Skip It") }, + }, + { + element: '#content-menu-button', + placement: 'left', + title: _t("Create your first product"), + content: _t("Click here to add a new product."), + popover: { fixed: true }, + }, + { + element: 'a[data-action=new_product]', + placement: 'left', + title: _t("Create a new product"), + content: _t("Select 'New Product' to create it and manage its properties to boost your sales."), + popover: { fixed: true }, + }, + { + element: '.modal #editor_new_product input[type=text]', + sampleText: 'New Product', + placement: 'right', + title: _t("Choose name"), + content: _t("Enter a name for your new product then click 'Continue'."), + }, + { + waitNot: '.modal input[type=text]:not([value!=""])', + element: '.modal button.btn-primary', + placement: 'right', + title: _t("Create Product"), + content: _t("Click Continue to create the product."), + }, + { + waitFor: 'body:has(button[data-action=save]:visible):has(.js_sale)', + title: _t("New product created"), + content: _t("This page contains all the information related to the new product."), + popover: { next: _t("Continue") }, + }, + { + element: '.product_price .oe_currency_value', + sampleText: '20.50', + placement: 'left', + title: _t("Change the price"), + content: _t("Edit the price of this product by clicking on the amount."), + }, - }, - { - waitFor: '#website-top-navbar button[data-action="edit"]:visible', - element: '.js_publish_management button.js_publish_btn.btn-danger', - placement: 'top', - title: _t("Publish your product"), - content: _t("Click to publish your product so your customers can see it."), - }, - { - waitFor: '.js_publish_management button.js_publish_btn.btn-success:visible', - title: _t("Congratulations"), - content: _t("Congratulations! You just created and published your first product."), - popover: { next: _t("Close Tutorial") }, - }, - ]; - return this._super(); - } + + { + waitNot: '.product_price .oe_currency_value:containsExact(1.00)', + element: '#wrap img.product_detail_img', + placement: 'top', + title: _t("Update image"), + content: _t("Click here to set an image describing your product."), + }, + { + element: 'img[alt=ipad]', + placement: 'top', + title: _t("Select an Image"), + content: _t("Let's select an ipad image."), + }, + { + waitFor: '.media_selected img[alt=ipad]', + element: '.modal-content button.save', + placement: 'top', + title: _t("Save this Image"), + content: _t("Click on save to add the image to the product decsription."), + }, + { + waitNot: '.modal-content:visible', + element: 'button[data-action=snippet]', + placement: 'bottom', + title: _t("Describe the Product"), + content: _t("Insert blocks like text-image, or gallery to fully describe the product."), + popover: { fixed: true }, + }, + { + snippet: '#snippet_structure .oe_snippet:eq(7)', + placement: 'bottom', + title: _t("Drag & Drop a block"), + content: _t("Drag the 'Big Picture' block and drop it in your page."), + popover: { fixed: true }, + }, + { + element: 'button[data-action=save]', + placement: 'right', + title: _t("Save your modifications"), + content: _t("Once you click on save, your product is updated."), + popover: { fixed: true }, + }, + { + waitFor: '#website-top-navbar button[data-action="edit"]:visible', + element: '.js_publish_management button.js_publish_btn.btn-danger', + placement: 'top', + title: _t("Publish your product"), + content: _t("Click to publish your product so your customers can see it."), + }, + { + waitFor: '.js_publish_management button.js_publish_btn.btn-success:visible', + title: _t("Congratulations"), + content: _t("Congratulations! You just created and published your first product."), + popover: { next: _t("Close Tutorial") }, + }, + ] }); }()); diff --git a/addons/website_sale/tests/test_ui.py b/addons/website_sale/tests/test_ui.py index 0eb5daae97a..33e3a3c2ae8 100644 --- a/addons/website_sale/tests/test_ui.py +++ b/addons/website_sale/tests/test_ui.py @@ -11,13 +11,13 @@ inject = [ @openerp.tests.common.post_install(True) class TestUi(openerp.tests.HttpCase): def test_01_admin_shop_tour(self): - self.phantom_js("/", "openerp.website.Tour.run_test('shop')", "openerp.website.Tour.Shop", login="admin") + self.phantom_js("/", "openerp.website.Tour.run('shop', 'test')", "openerp.website.Tour.tours.shop", login="admin") def test_02_admin_checkout(self): - self.phantom_js("/", "openerp.website.Tour.run_test('shop_buy_product')", "openerp.website.Tour.ShopTest", login="admin", inject=inject) + self.phantom_js("/", "openerp.website.Tour.run('shop_buy_product', 'test')", "openerp.website.Tour.tours.shop_buy_product", login="admin", inject=inject) def test_03_demo_checkout(self): - self.phantom_js("/", "openerp.website.Tour.run_test('shop_buy_product')", "openerp.website.Tour.ShopTest", login="demo", inject=inject) + self.phantom_js("/", "openerp.website.Tour.run('shop_buy_product', 'test')", "openerp.website.Tour.tours.shop_buy_product", login="demo", inject=inject) def test_04_public_checkout(self): - self.phantom_js("/", "openerp.website.Tour.run_test('shop_buy_product')", "openerp.website.Tour.ShopTest", inject=inject) + self.phantom_js("/", "openerp.website.Tour.run('shop_buy_product', 'test')", "openerp.website.Tour.tours.shop_buy_product", inject=inject)