diff --git a/addons/project/static/src/js/project_task_kanban_examples.js b/addons/project/static/src/js/project_task_kanban_examples.js new file mode 100644 index 00000000000..a9d24ce2994 --- /dev/null +++ b/addons/project/static/src/js/project_task_kanban_examples.js @@ -0,0 +1,73 @@ +odoo.define('project.task_kanban_examples', function (require) { +'use strict'; + +var core = require('web.core'); +var kanbanExamplesRegistry = require('web.kanban_examples_registry'); + +var _t = core._t; + +var greenBullet = ''; +var redBullet = ''; +var star = ''; + + +/** + * Helper function to escape a text before formatting it. + * + * First argument is the string to format and the other arguments are the values + * to inject into the string. + * + * @returns {string} the formatted and escaped string + */ +function escFormat() { + arguments[0] = _.escape(arguments[0]); + return _.str.sprintf.apply(_.str, arguments); +} + +kanbanExamplesRegistry.add('project', [{ + name: _t('Software Development'), + columns: [_t('Backlog'), _t('Specifications'), _t('Development'), _t('Tests'), _t('Delivered')], + description: escFormat(_t('Once a task is specified, set it %s in the Specifications ' + + 'column, so that developers know they can pull it. If you work in sprints, use %s to ' + + 'mark tasks of the current sprint.'), greenBullet, star), +}, { + name: _t('Agile'), + columns: [_t('Backlog'), _t('Analysis'), _t('Development'), _t('Testing'), _t('Done')], + description: escFormat(_t('Waiting for the next stage: use %s and %s bullets.'), greenBullet, redBullet), +}, { + name: _t('Digital Marketing'), + columns: [_t('Ideas'), _t('Researching'), _t('Writing'), _t('Editing'), _t('Done')], + description: escFormat(_t('Everyone can propose ideas, and the Editor marks the best ones ' + + 'as %s. Attach all documents or links to the task directly, to have all information about ' + + 'a research centralized.'), greenBullet), +}, { + name: _t('Customer Feedback'), + columns: [_t('New'), _t('In development'), _t('Done'), _t('Refused')], + description: escFormat(_t('Customers propose feedbacks by email; Odoo creates tasks ' + + 'automatically, and you can communicate on the task directly. Your managers decide which ' + + 'feedback is accepted %s and which feedback is moved to the "Refused" column.'), greenBullet), +}, { + name: _t('Getting Things Done (GTD)'), + columns: [_t('Inbox'), _t('Today'), _t('This Week'), _t('This Month'), _t('Long Term')], + description: _t('Fill your Inbox easily with the email gateway. Periodically review your ' + + 'Inbox and schedule tasks by moving them to others columns. Every day, you review the ' + + '"This Week" column to move important tasks "Today". Every Monday, you review the "This ' + + 'Month" column.'), +}, { + name: _t('Consulting'), + columns: [_t('New Projects'), _t('Resources Allocation'), _t('In Progress'), _t('Done')], +}, { + name: _t('Research Project'), + columns: [_t('Brainstorm'), _t('Research'), _t('Draft'), _t('Final Document')], +}, { + name: _t('Website Redesign'), + columns: [_t('Page Ideas'), _t('Copywriting'), _t('Design'), _t('Live')], +}, { + name: _t('T-shirt Printing'), + columns: [_t('New Orders'), _t('Logo Design'), _t('To Print'), _t('Done')], + description: escFormat(_t('Communicate with customers on the task using the email gateway. ' + + 'Attach logo designs to the task, so that information flow from designers to the workers ' + + 'who print the t-shirt. Organize priorities amongst orders %s using the icon.'), star), +}]); + +}); diff --git a/addons/project/views/project_assets.xml b/addons/project/views/project_assets.xml index 7a2c4647984..f953c6d366c 100644 --- a/addons/project/views/project_assets.xml +++ b/addons/project/views/project_assets.xml @@ -4,6 +4,7 @@ + diff --git a/addons/project/views/project_views.xml b/addons/project/views/project_views.xml index ab2c8a957a4..ecb3f9382a1 100644 --- a/addons/project/views/project_views.xml +++ b/addons/project/views/project_views.xml @@ -521,7 +521,7 @@ project.task.kanban project.task - + diff --git a/addons/web/static/src/js/views/kanban/kanban_column_quick_create.js b/addons/web/static/src/js/views/kanban/kanban_column_quick_create.js index 66445788682..78191d3ab75 100644 --- a/addons/web/static/src/js/views/kanban/kanban_column_quick_create.js +++ b/addons/web/static/src/js/views/kanban/kanban_column_quick_create.js @@ -6,34 +6,46 @@ odoo.define('web.kanban_column_quick_create', function (require) { * create kanban columns directly from the Kanban view. */ +var core = require('web.core'); +var Dialog = require('web.Dialog'); var Widget = require('web.Widget'); +var _t = core._t; +var QWeb = core.qweb; + var ColumnQuickCreate = Widget.extend({ template: 'KanbanView.ColumnQuickCreate', events: { - 'click': 'toggleFold', - 'click input': '_onInputClicked', + 'click .o_quick_create_folded': '_onUnfold', 'click .o_kanban_add': '_onAddClicked', - 'focusout': '_onFocusout', + 'click .o_kanban_examples': '_onShowExamples', 'keydown': '_onKeydown', 'keypress input': '_onKeypress', - 'mousedown .o_kanban_add': '_onMousedown', }, /** * @override + * @param {Object} [options] + * @param {Object} [options.examples] */ - init: function () { + init: function (parent, options) { this._super.apply(this, arguments); + this.examples = options.examples; this.folded = true; }, /** * @override */ start: function () { - this.$header = this.$('.o_column_header'); - this.$quick_create = this.$('.o_kanban_quick_create'); + this.$quickCreateFolded = this.$('.o_quick_create_folded'); + this.$quickCreateUnfolded = this.$('.o_quick_create_unfolded'); this.$input = this.$('input'); + + // destroy the quick create when the user clicks outside + core.bus.on('click', this, this._onWindowClicked); + + this._update(); + return this._super.apply(this, arguments); }, /** @@ -73,6 +85,7 @@ var ColumnQuickCreate = Widget.extend({ _add: function () { var value = this.$input.val().trim(); if (!value.length) { + this._cancel(); return; } this.$input.val(''); @@ -95,8 +108,8 @@ var ColumnQuickCreate = Widget.extend({ * @private */ _update: function () { - this.$header.toggle(this.folded); - this.$quick_create.toggle(!this.folded); + this.$quickCreateFolded.toggle(this.folded); + this.$quickCreateUnfolded.toggle(!this.folded); }, //-------------------------------------------------------------------------- @@ -111,28 +124,6 @@ var ColumnQuickCreate = Widget.extend({ event.stopPropagation(); this._add(); }, - /** - * Cancels the quick creation when the input loses the focus - * - * @private - */ - _onFocusout: function () { - var hasFocus = this.$(':focus').length > 0; - if (hasFocus) { - return; - } - this._cancel(); - }, - /** - * Stops the propagation of the event to prevent the quick create from - * toggling when the user clicks in the input - * - * @private - * @param {MouseEvent} event - */ - _onInputClicked: function (event) { - event.stopPropagation(); - }, /** * Cancels quick creation on escape keydown event * @@ -140,7 +131,7 @@ var ColumnQuickCreate = Widget.extend({ * @param {KeyEvent} event */ _onKeydown: function (event) { - if (event.keyCode === 27) { // escape + if (event.keyCode === $.ui.keyCode.ESCAPE) { this._cancel(); } }, @@ -151,23 +142,64 @@ var ColumnQuickCreate = Widget.extend({ * @param {KeyEvent} event */ _onKeypress: function (event) { - if (event.keyCode === 13) { // enter + if (event.keyCode === $.ui.keyCode.ENTER) { this._add(); } }, /** - * In all browsers the 'focus/blur' event is triggered before a button's - * 'click' (it's actually triggered by mousedown). - * The quick create is hidden on blur of its input but still needs to create - * the data when the "Add" button is clicked. - * This problem is adressed by suppressing the 'focus/blur' event from the - * Add button entirely by preventing the browser's default mousedown handler. + * Opens a dialog containing examples of Kanban processes + * + * @private + */ + _onShowExamples: function () { + var self = this; + var dialog = new Dialog(this, { + $content: $(QWeb.render('KanbanView.ExamplesDialog', { + examples: this.examples, + })), + buttons: [{ + classes: 'btn-primary pull-right', + close: true, + text: _t('Got it'), + }], + size: "large", + title: "Kanban Examples", + }).open(); + dialog.on('closed', this, function () { + self.$input.focus(); + }); + }, + /** + * @private + */ + _onUnfold: function () { + if (this.folded) { + this.toggleFold(); + } + }, + /** + * When a click happens outside the quick create, we want to close it. * * @private * @param {MouseEvent} event */ - _onMousedown: function (event) { - event.preventDefault(); + _onWindowClicked: function (event) { + // ignore clicks if the quick create is not in the dom + if (!document.contains(this.el)) { + return; + } + + // ignore clicks in modals + if ($(event.target).closest('.modal').length) { + return; + } + + // ignore clicks if target is inside the quick create + if (this.el.contains(event.target)) { + return; + } + + this._cancel(); }, }); diff --git a/addons/web/static/src/js/views/kanban/kanban_examples_registry.js b/addons/web/static/src/js/views/kanban/kanban_examples_registry.js new file mode 100644 index 00000000000..effdd7ff102 --- /dev/null +++ b/addons/web/static/src/js/views/kanban/kanban_examples_registry.js @@ -0,0 +1,27 @@ +odoo.define('web.kanban_examples_registry', function (require) { +"use strict"; + +/** + * This file instantiates and exports a registry. The purpose of this registry + * is to store static data displayed in a dialog to help the end user to + * configure its columns in the grouped Kanban view. + * + * To activate a link on the ColumnQuickCreate widget on open such a dialog, the + * attribute 'examples' on the root arch node must be set to a valid key in this + * registry. + * + * Each value in this registry must be an array of Objects containing the + * following keys: + * - name (string) + * - columns (Array[string]) + * - description (string, optional) BE CAREFUL [*] + * + * [*] The description is added with a t-raw so the translated texts must be + * properly escaped. + */ + +var Registry = require('web.Registry'); + +return new Registry(); + +}); diff --git a/addons/web/static/src/js/views/kanban/kanban_renderer.js b/addons/web/static/src/js/views/kanban/kanban_renderer.js index c3a14473787..17fcabe545b 100644 --- a/addons/web/static/src/js/views/kanban/kanban_renderer.js +++ b/addons/web/static/src/js/views/kanban/kanban_renderer.js @@ -97,16 +97,15 @@ var KanbanRenderer = BasicRenderer.extend({ var templates = findInNode(this.arch, function (n) { return n.tag === 'templates';}); transformQwebTemplate(templates, state.fields); this.qweb.add_template(utils.json_node_to_xml(templates)); - + this.examples = params.examples; this.recordOptions = _.extend({}, params.record_options, { qweb: this.qweb, viewType: 'kanban', }); - this.columnOptions = _.extend({}, params.column_options, { qweb: this.qweb }); + this.columnOptions = _.extend({}, params.column_options); if (this.columnOptions.hasProgressBar) { this.columnOptions.progressBarStates = {}; } - this._setState(state); }, /** @@ -291,7 +290,9 @@ var KanbanRenderer = BasicRenderer.extend({ // Enable column quickcreate if (this.createColumnEnabled) { - this.quickCreate = new ColumnQuickCreate(this); + this.quickCreate = new ColumnQuickCreate(this, { + examples: this.examples, + }); this.quickCreate.appendTo(fragment).then(function () { // Open it directly if there is no column yet if (!self.state.data.length) { @@ -301,7 +302,6 @@ var KanbanRenderer = BasicRenderer.extend({ } } - }, /** * Renders an ungrouped kanban view in a fragment. diff --git a/addons/web/static/src/js/views/kanban/kanban_view.js b/addons/web/static/src/js/views/kanban/kanban_view.js index c5ebbf5243f..99be6175da3 100644 --- a/addons/web/static/src/js/views/kanban/kanban_view.js +++ b/addons/web/static/src/js/views/kanban/kanban_view.js @@ -7,6 +7,7 @@ var config = require('web.config'); var KanbanModel = require('web.KanbanModel'); var KanbanRenderer = require('web.KanbanRenderer'); var KanbanController = require('web.KanbanController'); +var kanbanExamplesRegistry = require('web.kanban_examples_registry'); var utils = require('web.utils'); var _lt = core._lt; @@ -70,9 +71,12 @@ var KanbanView = BasicView.extend({ deletable: activeActions.delete, read_only_mode: params.readOnlyMode, }; + var examples = this.arch.attrs.examples; + if (examples) { + this.rendererParams.examples = kanbanExamplesRegistry.get(examples); + } this.controllerParams.on_create = this.arch.attrs.on_create; - this.controllerParams.readOnlyMode = false; this.controllerParams.hasButtons = true; diff --git a/addons/web/static/src/less/kanban_examples_dialog.less b/addons/web/static/src/less/kanban_examples_dialog.less new file mode 100644 index 00000000000..35a3d914b8e --- /dev/null +++ b/addons/web/static/src/less/kanban_examples_dialog.less @@ -0,0 +1,71 @@ +.o_kanban_examples_dialog { + .o-flex-display(); + padding: 0px; + background: @odoo-color-silver; + + // sidebar + .o_kanban_examples_dialog_nav { + .o-flex(0, 0, auto); + border-right: 1px solid @gray-lighter-dark; + background: white; + + > ul > li { + margin: 0; + border-bottom: 1px solid @gray-lighter-dark; + + > a { + padding: 12px 15px; + color: @odoo-main-text-color; + border-left: 3px solid transparent; + &:focus { + outline: none; + } + } + &.active > a { + color: @headings-color; + border-left-color: @odoo-brand-optional; + font-weight: bold; + } + } + } + + // content + .o_kanban_examples_dialog_content { + .o-flex(1, 1, 100%); + + .o_kanban_examples_description { + padding: 16px 16px 0; + text-align: justify; + } + .o_kanban_examples { + .o-flex-display(); + padding: 0 6px; + + .o_kanban_examples_group { + .o-flex(1, 1, 100%); + margin: 10px; + + .o_kanban_examples_ghost { + padding: 5px; + margin-top: -1px; + border: thin solid @gray-lighter-dark; + background-color: white; + .o_ghost_content { + height: 12px; + background: @gray-lighter-dark; + &.o_ghost_tag { + display: inline-block; + width: 40%; + margin-top: 10px; + } + } + .o_ghost_avatar { + height: 20px; + width: 20px; + margin-top: 6px; + } + } + } + } + } +} diff --git a/addons/web/static/src/less/kanban_view.less b/addons/web/static/src/less/kanban_view.less index 2b5482e36ff..f04e8515ad4 100644 --- a/addons/web/static/src/less/kanban_view.less +++ b/addons/web/static/src/less/kanban_view.less @@ -547,45 +547,58 @@ // Kanban Grouped Layout - "Create new column" column .o_column_quick_create { - .o-kanban-slim-col(); - - .o_column_header { - .o-kanban-header-title(); - position: relative; - opacity: 0.5; - - .o_kanban_title { - .o-kanban-v-title(); + .o_quick_create_folded { + cursor: pointer; + padding: 12px 16px; + white-space: nowrap; + color: @text-muted; + opacity: 0.6; + &:hover { + opacity: 1; } .o_kanban_add_column { - .o-kanban-icon(1); + display: inline-block; + padding: 10px 14px; + background-color: @odoo-color-silver-dark; + } + .o_kanban_title { + margin-left: 10px; } } - .o_kanban_quick_create { - display: none; - width: @o-kanban-default-record-width; + .o_quick_create_unfolded { + padding: @o-kanban-inside-vgutter @o-kanban-inside-hgutter; + width: @o-kanban-small-record-width; height: 100%; - margin: 0 (-@o-kanban-group-padding/2); border: none; box-shadow: 0 0 20px -10px; background-color: @gray-lighter; - input, input:focus, input:hover { - font-size: 16px; - background: @gray-lighter; - outline: none; - box-shadow: none; - font-weight: 400; - margin: 0; - } - } + .o_kanban_header { + height: 50px; - &:hover { - .o_column_header, .o_kanban_add_column { - opacity: 1; + .o_kanban_examples { + cursor: pointer; + } + + input, input:focus, input:hover { + margin-top: 3px; + font-size: 16px; + background: transparent; + } + + .o_kanban_add { + margin-left: 10px; + } } + + .o_kanban_muted_record { + background: @gray-lighter-dark; + height: 70px; + margin: 10px 0px; + } + } } diff --git a/addons/web/static/src/xml/kanban.xml b/addons/web/static/src/xml/kanban.xml index 97ac827df2a..d06a39081e5 100644 --- a/addons/web/static/src/xml/kanban.xml +++ b/addons/web/static/src/xml/kanban.xml @@ -39,17 +39,25 @@
-
+
- Add new Column + Add a new Column
-
-
- - - - +
+
+
+ + + + +
+ + See Examples +
+
+
+
@@ -97,8 +105,48 @@
- + +
+ +
+
+
+ +
+ +
diff --git a/addons/web/static/tests/views/kanban_tests.js b/addons/web/static/tests/views/kanban_tests.js index e7c96525d11..aa1a9e93e4a 100644 --- a/addons/web/static/tests/views/kanban_tests.js +++ b/addons/web/static/tests/views/kanban_tests.js @@ -2,6 +2,7 @@ odoo.define('web.kanban_tests', function (require) { "use strict"; var KanbanColumnProgressBar = require('web.KanbanColumnProgressBar'); +var kanbanExamplesRegistry = require('web.kanban_examples_registry'); var KanbanRenderer = require('web.KanbanRenderer'); var KanbanView = require('web.KanbanView'); var testUtils = require('web.test_utils'); @@ -1636,17 +1637,20 @@ QUnit.module('Views', { assert.notOk(kanban.$('.o_column_quick_create input').is(':visible'), "the input should not be visible"); - kanban.$('.o_column_quick_create').click(); + kanban.$('.o_quick_create_folded').click(); assert.ok(kanban.$('.o_column_quick_create input').is(':visible'), "the input should be visible"); // discard the column creation and click it again - kanban.$('.o_column_quick_create').click(); + kanban.$('.o_column_quick_create input').trigger($.Event('keydown', { + keyCode: $.ui.keyCode.ESCAPE, + which: $.ui.keyCode.ESCAPE, + })); assert.notOk(kanban.$('.o_column_quick_create input').is(':visible'), "the input should not be visible after discard"); - kanban.$('.o_column_quick_create').click(); + kanban.$('.o_quick_create_folded').click(); assert.ok(kanban.$('.o_column_quick_create input').is(':visible'), "the input should be visible"); @@ -1915,14 +1919,14 @@ QUnit.module('Views', { kanban.destroy(); }); - QUnit.test('cancel column quick create by pressing ESCAPE', function (assert) { - assert.expect(4); + QUnit.test('quick create several columns in a row', function (assert) { + assert.expect(10); var kanban = createView({ View: KanbanView, model: 'partner', data: this.data, - arch: '' + + arch: '' + '' + '' + '
' + @@ -1931,23 +1935,100 @@ QUnit.module('Views', { groupBy: ['product_id'], }); - assert.strictEqual(kanban.$('.o_column_quick_create').length, 1, "should have a quick create column"); - assert.notOk(kanban.$('.o_column_quick_create input').is(':visible'), - "the input should not be visible"); + assert.strictEqual(kanban.$('.o_kanban_group').length, 2, + "should have two columns"); + assert.strictEqual(kanban.$('.o_column_quick_create').length, 1, + "should have a ColumnQuickCreate widget"); + assert.strictEqual(kanban.$('.o_column_quick_create .o_quick_create_folded:visible').length, 1, + "the ColumnQuickCreate should be folded"); + assert.strictEqual(kanban.$('.o_column_quick_create .o_quick_create_unfolded:visible').length, 0, + "the ColumnQuickCreate should be folded"); - kanban.$('.o_column_quick_create').click(); + // add a new column + kanban.$('.o_column_quick_create .o_quick_create_folded').click(); + assert.strictEqual(kanban.$('.o_column_quick_create .o_quick_create_folded:visible').length, 0, + "the ColumnQuickCreate should be unfolded"); + assert.strictEqual(kanban.$('.o_column_quick_create .o_quick_create_unfolded:visible').length, 1, + "the ColumnQuickCreate should be unfolded"); + kanban.$('.o_column_quick_create input').val('New Column 1'); + kanban.$('.o_column_quick_create .btn-primary').click(); + assert.strictEqual(kanban.$('.o_kanban_group').length, 3, + "should now have three columns"); - assert.ok(kanban.$('.o_column_quick_create input').is(':visible'), - "the input should be visible"); + // add another column + assert.strictEqual(kanban.$('.o_column_quick_create .o_quick_create_folded:visible').length, 0, + "the ColumnQuickCreate should still be unfolded"); + assert.strictEqual(kanban.$('.o_column_quick_create .o_quick_create_unfolded:visible').length, 1, + "the ColumnQuickCreate should still be unfolded"); + kanban.$('.o_column_quick_create input').val('New Column 2'); + kanban.$('.o_column_quick_create .btn-primary').click(); + assert.strictEqual(kanban.$('.o_kanban_group').length, 4, + "should now have four columns"); - // discard the column creation by pressing ESCAPE - kanban.$('.o_column_quick_create input').trigger($.Event('keydown', { - keyCode: $.ui.keyCode.ESCAPE, - which: $.ui.keyCode.ESCAPE, - })); + kanban.destroy(); + }); - assert.notOk(kanban.$('.o_column_quick_create input').is(':visible'), - "the input should not be visible anymore"); + QUnit.test('quick create column and examples', function (assert) { + assert.expect(12); + + kanbanExamplesRegistry.add('test', [{ + name: "A first example", + columns: ["Column 1", "Column 2", "Column 3"], + description: "Some description", + }, { + name: "A second example", + columns: ["Col 1", "Col 2"], + }]); + + var kanban = createView({ + View: KanbanView, + model: 'partner', + data: this.data, + arch: '' + + '' + + '' + + '
' + + '
' + + '
', + groupBy: ['product_id'], + }); + + assert.strictEqual(kanban.$('.o_column_quick_create').length, 1, + "should have a ColumnQuickCreate widget"); + + // open the quick create + kanban.$('.o_column_quick_create .o_quick_create_folded').click(); + + assert.strictEqual(kanban.$('.o_column_quick_create .o_kanban_examples:visible').length, 1, + "should have a link to see examples"); + + // click to see the examples + kanban.$('.o_column_quick_create .o_kanban_examples').click(); + + assert.strictEqual($('.modal .o_kanban_examples_dialog').length, 1, + "should have open the examples dialog"); + assert.strictEqual($('.modal .o_kanban_examples_dialog_nav li').length, 2, + "should have two examples (in the menu)"); + assert.strictEqual($('.modal .o_kanban_examples_dialog_nav a').text(), + ' A first example A second example ', "example names should be correct"); + assert.strictEqual($('.modal .o_kanban_examples_dialog_content .tab-pane').length, 2, + "should have two examples"); + + var $firstPane = $('.modal .o_kanban_examples_dialog_content .tab-pane:first'); + assert.strictEqual($firstPane.find('.o_kanban_examples_group').length, 3, + "there should be 3 stages in the first example"); + assert.strictEqual($firstPane.find('h6').text(), 'Column 1Column 2Column 3', + "column titles should be correct"); + assert.strictEqual($firstPane.find('.o_kanban_examples_description').text().trim(), + "Some description", "the correct description should be displayed"); + + var $secondPane = $('.modal .o_kanban_examples_dialog_content .tab-pane:nth(1)'); + assert.strictEqual($secondPane.find('.o_kanban_examples_group').length, 2, + "there should be 2 stages in the second example"); + assert.strictEqual($secondPane.find('h6').text(), 'Col 1Col 2', + "column titles should be correct"); + assert.strictEqual($secondPane.find('.o_kanban_examples_description').text().trim(), + "", "there should be no description for the second example"); kanban.destroy(); }); @@ -2762,35 +2843,6 @@ QUnit.module('Views', { kanban.destroy(); }); - QUnit.test('don\'t fold column quick create after creation', function (assert) { - assert.expect(2); - - var kanban = createView({ - View: KanbanView, - model: 'partner', - data: this.data, - arch: '' + - '' + - '' + - '
' + - '
' + - '
', - groupBy: ['product_id'], - }); - - // add a new column - kanban.$('.o_kanban_group:first .o_kanban_quick_add').click(); - var $quickCreate = kanban.$('.o_kanban_quick_create'); - $quickCreate.find('input').val('new partner').trigger('input'); - $quickCreate.find('button.o_kanban_add').click(); - assert.strictEqual(this.data.partner.records.length, 5, - "should have created a 'new partner' column"); - - assert.strictEqual(kanban.$('.o_kanban_add:visible').length, 1, - "the add button should still be visible"); - kanban.destroy(); - }); - QUnit.test('basic support for widgets', function (assert) { assert.expect(1); diff --git a/addons/web/views/webclient_templates.xml b/addons/web/views/webclient_templates.xml index f696696af20..c78b6b0ecac 100644 --- a/addons/web/views/webclient_templates.xml +++ b/addons/web/views/webclient_templates.xml @@ -122,6 +122,7 @@ + @@ -217,6 +218,7 @@ +