diff --git a/addons/project/static/src/js/project_task_kanban_examples.js b/addons/project/static/src/js/project_task_kanban_examples.js index fb65b30445d..390be680d84 100644 --- a/addons/project/static/src/js/project_task_kanban_examples.js +++ b/addons/project/static/src/js/project_task_kanban_examples.js @@ -24,60 +24,63 @@ function escFormat() { 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('Prioritize Tasks by using the %s icon.'+ - '%s Use the %s button to signalize to your colleagues that a task is ready for the next stage.'+ - '%s Use the %s to signalize a problem or a need for discussion on a task.'), star, '
', greenBullet, '
', redBullet), - bullets: [greenBullet, redBullet, 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), - 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), - bullets: [greenBullet, redBullet], -}, { - 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), - bullets: [greenBullet, redBullet], -}, { - 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')], - description: escFormat(_t('Manage the lifecycle of your project using the kanban view. Add newly acquired project, assign them and use the %s and %s to define if the project is ready for the next step.'), greenBullet, redBullet), - bullets: [greenBullet, redBullet], -}, { - name: _t('Research Project'), - columns: [_t('Brainstorm'), _t('Research'), _t('Draft'), _t('Final Document')], - description: escFormat(_t('Handle your idea gahtering within Tasks of your new Project and discuss them in the chatter of the tasks. Use the %s and %s to signalize what is the current status of your Idea'), greenBullet, redBullet), - bullets: [greenBullet, redBullet], -}, { - name: _t('Website Redesign'), - columns: [_t('Page Ideas'), _t('Copywriting'), _t('Design'), _t('Live')], - description: escFormat(_t('Handle your idea gahtering within Tasks of your new Project and discuss them in the chatter of the tasks. Use the %s and %s to signalize what is the current status of your Idea'), greenBullet, redBullet), -}, { - 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), - bullets: [star], -}]); +kanbanExamplesRegistry.add('project', { + ghostColumns: [_t('New'), _t('Assigned'), _t('In Progress'), _t('Done')], + examples:[{ + name: _t('Software Development'), + columns: [_t('Backlog'), _t('Specifications'), _t('Development'), _t('Tests'), _t('Delivered')], + description: escFormat(_t('Prioritize Tasks by using the %s icon.'+ + '%s Use the %s button to signalize to your colleagues that a task is ready for the next stage.'+ + '%s Use the %s to signalize a problem or a need for discussion on a task.'), star, '
', greenBullet, '
', redBullet), + bullets: [greenBullet, redBullet, 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), + 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), + bullets: [greenBullet, redBullet], + }, { + 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), + bullets: [greenBullet, redBullet], + }, { + 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')], + description: escFormat(_t('Manage the lifecycle of your project using the kanban view. Add newly acquired project, assign them and use the %s and %s to define if the project is ready for the next step.'), greenBullet, redBullet), + bullets: [greenBullet, redBullet], + }, { + name: _t('Research Project'), + columns: [_t('Brainstorm'), _t('Research'), _t('Draft'), _t('Final Document')], + description: escFormat(_t('Handle your idea gahtering within Tasks of your new Project and discuss them in the chatter of the tasks. Use the %s and %s to signalize what is the current status of your Idea'), greenBullet, redBullet), + bullets: [greenBullet, redBullet], + }, { + name: _t('Website Redesign'), + columns: [_t('Page Ideas'), _t('Copywriting'), _t('Design'), _t('Live')], + description: escFormat(_t('Handle your idea gahtering within Tasks of your new Project and discuss them in the chatter of the tasks. Use the %s and %s to signalize what is the current status of your Idea'), greenBullet, redBullet), + }, { + 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), + bullets: [star], + }], +}); }); 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 bd6c00a6802..5be98e4de52 100644 --- a/addons/web/static/src/js/views/kanban/kanban_renderer.js +++ b/addons/web/static/src/js/views/kanban/kanban_renderer.js @@ -13,6 +13,7 @@ var utils = require('web.utils'); var viewUtils = require('web.viewUtils'); var qweb = core.qweb; +var _t = core._t; function findInNode(node, predicate) { if (predicate(node)) { @@ -281,6 +282,20 @@ var KanbanRenderer = BasicRenderer.extend({ previousCard.focus(); } }, + /** + * Returns the default columns for the kanban view example background. + * You can override this method to easily customize the column names. + * + * @private + */ + _getGhostColumns: function () { + if (this.examples && this.examples.ghostColumns) { + return this.examples.ghostColumns; + } + return _.map(_.range(1, 5), function (num) { + return _.str.sprintf(_t("Column %s"), num); + }); + }, /** * Render the Example Ghost Kanban card on the background * @@ -288,7 +303,7 @@ var KanbanRenderer = BasicRenderer.extend({ * @param {DocumentFragment} fragment */ _renderExampleBackground: function (fragment) { - var $background = $(qweb.render('KanbanView.ExamplesBackground')); + var $background = $(qweb.render('KanbanView.ExamplesBackground', {ghostColumns: this._getGhostColumns()})); $background.appendTo(fragment); }, /** @@ -358,10 +373,9 @@ var KanbanRenderer = BasicRenderer.extend({ }, }); - // Enable column quickcreate if (this.createColumnEnabled) { this.quickCreate = new ColumnQuickCreate(this, { - examples: this.examples, + examples: this.examples && this.examples.examples, }); this.defs.push(this.quickCreate.appendTo(fragment).then(function () { // Open it directly if there is no column yet diff --git a/addons/web/static/src/xml/kanban.xml b/addons/web/static/src/xml/kanban.xml index 3a01370443f..424408f9340 100644 --- a/addons/web/static/src/xml/kanban.xml +++ b/addons/web/static/src/xml/kanban.xml @@ -191,9 +191,9 @@
- +
-
Column
+
diff --git a/addons/web/static/tests/views/kanban_tests.js b/addons/web/static/tests/views/kanban_tests.js index 5e2c4e0a8f6..7284caeae21 100644 --- a/addons/web/static/tests/views/kanban_tests.js +++ b/addons/web/static/tests/views/kanban_tests.js @@ -3355,14 +3355,16 @@ QUnit.module('Views', { QUnit.test('quick create column and examples', async 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"], - }]); + kanbanExamplesRegistry.add('test', { + examples:[{ + 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 = await createView({ View: KanbanView, @@ -3417,6 +3419,78 @@ QUnit.module('Views', { kanban.destroy(); }); + QUnit.test('quick create column and examples background with ghostColumns titles', async function (assert) { + assert.expect(4); + + this.data.partner.records = []; + + kanbanExamplesRegistry.add('test', { + ghostColumns: ["Ghost 1", "Ghost 2", "Ghost 3", "Ghost 4"], + examples:[{ + 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 = await createView({ + View: KanbanView, + model: 'partner', + data: this.data, + arch: '' + + '' + + '' + + '
' + + '
' + + '
', + groupBy: ['product_id'], + }); + + assert.containsOnce(kanban, '.o_kanban_example_background', + "should have ExamplesBackground when no data"); + assert.strictEqual(kanban.$('.o_kanban_examples_group h6').text(), 'Ghost 1Ghost 2Ghost 3Ghost 4', + "ghost title should be correct"); + assert.containsOnce(kanban, '.o_column_quick_create', + "should have a ColumnQuickCreate widget"); + assert.containsOnce(kanban, '.o_column_quick_create .o_kanban_examples:visible', + "should not have a link to see examples as there is no examples registered"); + + kanban.destroy(); + }); + + QUnit.test('quick create column and examples background without ghostColumns titles', async function (assert) { + assert.expect(4); + + this.data.partner.records = []; + + var kanban = await createView({ + View: KanbanView, + model: 'partner', + data: this.data, + arch: '' + + '' + + '' + + '
' + + '
' + + '
', + groupBy: ['product_id'], + }); + + assert.containsOnce(kanban, '.o_kanban_example_background', + "should have ExamplesBackground when no data"); + assert.strictEqual(kanban.$('.o_kanban_examples_group h6').text(), 'Column 1Column 2Column 3Column 4', + "ghost title should be correct"); + assert.containsOnce(kanban, '.o_column_quick_create', + "should have a ColumnQuickCreate widget"); + assert.containsNone(kanban, '.o_column_quick_create .o_kanban_examples:visible', + "should not have a link to see examples as there is no examples registered"); + + kanban.destroy(); + }); + QUnit.test('if view was not grouped at start, it can be grouped and ungrouped', async function (assert) { assert.expect(3); diff --git a/doc/reference/views.rst b/doc/reference/views.rst index 12c0615d9b7..999839da2d0 100644 --- a/doc/reference/views.rst +++ b/doc/reference/views.rst @@ -1023,6 +1023,8 @@ attributes: the list view) ``class`` adds HTML classes to the root HTML element of the Kanban view +``examples`` + if set to a key in the `KanbanExamplesRegistry`_, examples on column setups will be available in the grouped kanban view. `Here `_ is an example of how to define those setups. ``group_create`` whether the "Add a new column" bar is visible or not. Default: true. ``group_delete`` @@ -2095,3 +2097,4 @@ The main additions of qweb-as-view to the basic qweb-as-template are: .. _kanban board: http://en.wikipedia.org/wiki/Kanban_board .. _pivot table: http://en.wikipedia.org/wiki/Pivot_table .. _XPath: http://en.wikipedia.org/wiki/XPath +.. _KanbanExamplesRegistry: https://github.com/odoo/odoo/blob/99821fdcf89aa66ac9561a972c6823135ebf65c0/addons/web/static/src/js/views/kanban/kanban_examples_registry.js