[IMP] web_tour: add a sequence option to tours
Before this commit, tours were activated in a non deterministic way and there was no way to control the order. Now there is a `sequence` key in the options dict (i.e. the second parameters of `tour.register`) which will determine the tour sequence order, the lowest being first and going upward. Unsequenced tours will behave as before with no particular order. Task 2191192
This commit is contained in:
@@ -51,6 +51,9 @@ return core.Class.extend(mixins.EventDispatcherMixin, ServicesMixin, {
|
||||
* the url to load when manually running the tour
|
||||
* @param {boolean} [options.rainbowMan=true]
|
||||
* whether or not the rainbowman must be shown at the end of the tour
|
||||
* @param {boolean} [options.sequence=1000]
|
||||
* priority sequence of the tour (lowest is first, tours with the same
|
||||
* sequence will be executed in a non deterministic order).
|
||||
* @param {Promise} [options.wait_for]
|
||||
* indicates when the tour can be started
|
||||
* @param {Object[]} steps - steps' descriptions, each step being an object
|
||||
@@ -71,6 +74,7 @@ return core.Class.extend(mixins.EventDispatcherMixin, ServicesMixin, {
|
||||
steps: steps,
|
||||
url: options.url,
|
||||
rainbowMan: options.rainbowMan === undefined ? true : !!options.rainbowMan,
|
||||
sequence: options.sequence || 1000,
|
||||
test: options.test,
|
||||
wait_for: options.wait_for || Promise.resolve(),
|
||||
};
|
||||
@@ -113,7 +117,7 @@ return core.Class.extend(mixins.EventDispatcherMixin, ServicesMixin, {
|
||||
_register: function (do_update, tour, name) {
|
||||
if (tour.ready) return Promise.resolve();
|
||||
|
||||
var tour_is_consumed = _.contains(this.consumed_tours, name);
|
||||
const tour_is_consumed = this._isTourConsumed(name);
|
||||
|
||||
return tour.wait_for.then((function () {
|
||||
tour.current_step = parseInt(local_storage.getItem(get_step_key(name))) || 0;
|
||||
@@ -198,7 +202,10 @@ return core.Class.extend(mixins.EventDispatcherMixin, ServicesMixin, {
|
||||
self._check_for_tooltip(self.active_tooltips[tour_name], tour_name);
|
||||
});
|
||||
} else {
|
||||
for (var tourName in this.active_tooltips) {
|
||||
const sortedTooltips = Object.keys(this.active_tooltips).sort(
|
||||
(a, b) => this.tours[a].sequence - this.tours[b].sequence
|
||||
);
|
||||
for (const tourName of sortedTooltips) {
|
||||
var tip = this.active_tooltips[tourName];
|
||||
var activated = this._check_for_tooltip(tip, tourName);
|
||||
if (activated) {
|
||||
@@ -342,6 +349,14 @@ return core.Class.extend(mixins.EventDispatcherMixin, ServicesMixin, {
|
||||
}
|
||||
this.active_tooltips[tour_name] = tour.steps[tour.current_step];
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
* @param {string} tourName
|
||||
* @returns {boolean}
|
||||
*/
|
||||
_isTourConsumed(tourName) {
|
||||
return this.consumed_tours.includes(tourName);
|
||||
},
|
||||
_consume_tour: function (tour_name, error) {
|
||||
delete this.active_tooltips[tour_name];
|
||||
//display rainbow at the end of any tour
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
odoo.define('web_tour.tour_manager_tests', function (require) {
|
||||
"use strict";
|
||||
|
||||
const TourManager = require('web_tour.TourManager');
|
||||
const testUtils = require('web.test_utils');
|
||||
|
||||
/**
|
||||
* Create a widget and a TourManager instance with a list of given Tour objects.
|
||||
* @see TourManager.register() for more details on the Tours registry system.
|
||||
* @param {Object} params
|
||||
* @param {string[]} [params.consumed_tours]
|
||||
* @param {boolean} [params.debug]
|
||||
* @param {string} params.template inner HTML content of the widget
|
||||
* @param {Object[]} params.tours { {string} name, {Object} option, {Object[]} steps }
|
||||
*/
|
||||
async function createTourManager({ consumed_tours, debug, template, tours }) {
|
||||
const parent = testUtils.createParent({ debug });
|
||||
const tourManager = new TourManager(parent, consumed_tours);
|
||||
tourManager.running_step_delay = 0;
|
||||
for (const { name, options, steps } of tours) {
|
||||
tourManager.register(name, options, steps);
|
||||
}
|
||||
const _destroy = tourManager.destroy;
|
||||
tourManager.destroy = function () {
|
||||
tourManager.destroy = _destroy;
|
||||
parent.destroy();
|
||||
};
|
||||
await parent.prependTo(testUtils.prepareTarget(debug));
|
||||
parent.el.innerHTML = template;
|
||||
testUtils.mock.patch(TourManager, {
|
||||
// Since the `tour_disable.js` script automatically sets tours as consumed
|
||||
// as soon as they are registered, we override the "is consumed" to
|
||||
// assert that the tour is in the `consumed_tours` param key.
|
||||
_isTourConsumed: name => (consumed_tours || []).includes(name),
|
||||
});
|
||||
await tourManager._register_all(true);
|
||||
// Wait for possible tooltips to be loaded and appended.
|
||||
await testUtils.nextTick();
|
||||
return tourManager;
|
||||
}
|
||||
|
||||
QUnit.module("Tours", {
|
||||
afterEach() {
|
||||
testUtils.mock.unpatch(TourManager);
|
||||
},
|
||||
}, function () {
|
||||
|
||||
QUnit.module("Tour manager");
|
||||
|
||||
QUnit.test("Tours sequence", async function (assert) {
|
||||
assert.expect(2);
|
||||
|
||||
const tourManager = await createTourManager({
|
||||
template: `
|
||||
<button class="btn anchor">Anchor</button>`,
|
||||
tours: [
|
||||
{ name: "Tour 1", options: { sequence: 10 }, steps: [{ trigger: '.anchor' }] },
|
||||
{ name: "Tour 2", options: {}, steps: [{ trigger: '.anchor' }] },
|
||||
{ name: "Tour 3", options: { sequence: 5 }, steps: [{ trigger: '.anchor', content: "Oui" }] },
|
||||
],
|
||||
});
|
||||
|
||||
assert.containsOnce(document.body, '.o_tooltip');
|
||||
const tooltip = document.querySelector('.o_tooltip_content');
|
||||
assert.strictEqual(tooltip.innerHTML.trim(), "Oui",
|
||||
"content should be that of the third tour");
|
||||
|
||||
tourManager.destroy();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -25,5 +25,11 @@
|
||||
<script type="text/javascript" src="/web_tour/static/src/js/public/tour_manager.js"/>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<template id="web_tour.qunit_suite" name="tour tests" inherit_id="web.qunit_suite">
|
||||
<xpath expr="//script[last()]" position="after">
|
||||
<script type="text/javascript" src="/web_tour/static/tests/tour_manager_tests.js"/>
|
||||
</xpath>
|
||||
</template>
|
||||
</data>
|
||||
</odoo>
|
||||
|
||||
Reference in New Issue
Block a user