From e7268c201ea98108fdb1bf0c8af3c413b3d5a3a4 Mon Sep 17 00:00:00 2001 From: jem-odoo Date: Mon, 15 Oct 2018 09:43:34 +0000 Subject: [PATCH 1/7] [IMP] web: make kanban create button jump This commit makes the create button of a kanban view jumping when the user click on some zone on the kanban background. The purpose here is to educate the user, so he can learn how to create its first kanban card. Task-1893021 --- .../src/js/views/kanban/kanban_controller.js | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/addons/web/static/src/js/views/kanban/kanban_controller.js b/addons/web/static/src/js/views/kanban/kanban_controller.js index 2383a0ac730..0f07ea6d565 100644 --- a/addons/web/static/src/js/views/kanban/kanban_controller.js +++ b/addons/web/static/src/js/views/kanban/kanban_controller.js @@ -33,6 +33,9 @@ var KanbanController = BasicController.extend({ column_toggle_fold: '_onToggleColumn', kanban_column_records_toggle_active: '_onToggleActiveRecords', }), + events: _.extend({}, BasicController.prototype.events, { + click: '_onClick', + }), /** * @override * @param {Object} params @@ -302,6 +305,23 @@ var KanbanController = BasicController.extend({ this.$('.o_kanban_record:first').focus(); } }, + /** + * Bounce the 'Create' button. + * + * @private + * @param {MouseEvent} ev + **/ + _onClick: function (ev) { + var state = this.model.get(this.handle, {raw: true}); + if (!state.count && this.buttons) { + var classesList = ['o_kanban_view', 'o_kanban_group', 'o_column_quick_create', 'o_view_nocontent_smiling_face']; + var $target = $(ev.target); + var hasClassList = _.map(classesList, function(klass){ return $target.hasClass(klass) }); + if (_.some(hasClassList)) { + this.$buttons.find('.o-kanban-button-new').odooBounce(); + } + } + }, /** * @private * @param {OdooEvent} ev From aa33c815351688513de74b5d947d46d1df7bee68 Mon Sep 17 00:00:00 2001 From: jem-odoo Date: Mon, 15 Oct 2018 11:13:28 +0000 Subject: [PATCH 2/7] [IMP] project: hide email field on task form view Since this field is not very usefull, we prefer hide it to avoid saturating the UI. Task-1893021 --- addons/project/views/project_views.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/project/views/project_views.xml b/addons/project/views/project_views.xml index fb4ace2f093..51ab5ad4f1d 100644 --- a/addons/project/views/project_views.xml +++ b/addons/project/views/project_views.xml @@ -467,7 +467,7 @@ - + From eca54926dcd8cb6b4d9328ee865f0db33c9fc040 Mon Sep 17 00:00:00 2001 From: jem-odoo Date: Mon, 15 Oct 2018 11:14:32 +0000 Subject: [PATCH 3/7] [IMP] project: better labels The privacy field labels are not clear for users: they bring confusion and hesitation. Replacing them tries to solve this problem. Tasl-1893021 --- addons/project/models/project.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/addons/project/models/project.py b/addons/project/models/project.py index 8bf82cc5328..d8f697261e1 100644 --- a/addons/project/models/project.py +++ b/addons/project/models/project.py @@ -203,17 +203,17 @@ class Project(models.Model): help="Internal email associated with this project. Incoming emails are automatically synchronized " "with Tasks (or optionally Issues if the Issue Tracker module is installed).") privacy_visibility = fields.Selection([ - ('followers', 'On invitation only'), - ('employees', 'Visible by all employees'), - ('portal', 'Visible by following customers'), + ('followers', 'Visible by invited employees'), + ('employees', 'Visible by employees'), + ('portal', 'Visible by portal users and employees'), ], string='Privacy', required=True, default='portal', help="Defines the visibility of the tasks of the project:\n" - "- On invitation only: employees may only see the followed project and tasks.\n" - "- Visible by all employees: employees may see all project and tasks.\n" - "- Visible by following customers: employees may see everything." - " if website is activated, portal users may see project and tasks followed by.\n" + "- Visible by invited employees: employees may only see the followed project and tasks.\n" + "- Visible by employees: employees may see all project and tasks.\n" + "- Visible by portal users and employees: employees may see everything." + " Portal users may see project and tasks followed by.\n" " them or by someone of their company.") doc_count = fields.Integer(compute='_compute_attached_docs_count', string="Number of documents attached") date_start = fields.Date(string='Start Date') @@ -428,9 +428,9 @@ class Task(models.Model): name = fields.Char(string='Title', tracking=True, required=True, index=True) description = fields.Html(string='Description') priority = fields.Selection([ - ('0', 'Low'), - ('1', 'Normal'), - ], default='0', index=True, string="Priority") + ('0', 'Normal'), + ('1', 'Important'), + ], default='0', index=True, string="Priority") sequence = fields.Integer(string='Sequence', index=True, default=10, help="Gives the sequence order when displaying a list of tasks.") stage_id = fields.Many2one('project.task.type', string='Stage', ondelete='restrict', tracking=True, index=True, From 4669c524db49ff4a204ddd5a29033d874938df88 Mon Sep 17 00:00:00 2001 From: jem-odoo Date: Mon, 15 Oct 2018 07:33:38 +0000 Subject: [PATCH 4/7] [IMP] project: not create project from task Prevent user to create project on the fly when editing task. This will avoid user to create bad project (typo, ...) and will force then to be more organized: create a project first, then populate it with tasks. Task-1893021 --- addons/project/views/project_views.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/project/views/project_views.xml b/addons/project/views/project_views.xml index 51ab5ad4f1d..73d2de26495 100644 --- a/addons/project/views/project_views.xml +++ b/addons/project/views/project_views.xml @@ -444,7 +444,7 @@ - + From 4b4e8508ef9da82516a96f1dd4b4b0eb4b01afe1 Mon Sep 17 00:00:00 2001 From: jem-odoo Date: Tue, 23 Oct 2018 07:33:12 +0000 Subject: [PATCH 5/7] [IMP] project: improve kanban example sentences This commit improves the sentences used in the kanban example modal in order to be more concrete and precised for the users Task-1893021 --- .../static/src/js/project_task_kanban_examples.js | 11 ++++++++--- addons/web/static/src/xml/kanban.xml | 2 +- 2 files changed, 9 insertions(+), 4 deletions(-) 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 a9d24ce2994..85a21fa4ab1 100644 --- a/addons/project/static/src/js/project_task_kanban_examples.js +++ b/addons/project/static/src/js/project_task_kanban_examples.js @@ -27,9 +27,9 @@ function escFormat() { 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), + 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), }, { name: _t('Agile'), columns: [_t('Backlog'), _t('Analysis'), _t('Development'), _t('Testing'), _t('Done')], @@ -56,12 +56,17 @@ kanbanExamplesRegistry.add('project', [{ }, { 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')], diff --git a/addons/web/static/src/xml/kanban.xml b/addons/web/static/src/xml/kanban.xml index 220395fef02..3acc0bceac5 100644 --- a/addons/web/static/src/xml/kanban.xml +++ b/addons/web/static/src/xml/kanban.xml @@ -57,7 +57,7 @@ - + Esc to discard From 92b6ea64ab0847e932fff9eb657ae2b72dd9cdbf Mon Sep 17 00:00:00 2001 From: jem-odoo Date: Fri, 26 Oct 2018 13:12:27 +0000 Subject: [PATCH 6/7] [IMP] web: make kanban example support state bullets --- addons/project/static/src/js/project_task_kanban_examples.js | 5 +++++ addons/web/static/src/xml/kanban.xml | 5 +++++ 2 files changed, 10 insertions(+) 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 85a21fa4ab1..fb65b30445d 100644 --- a/addons/project/static/src/js/project_task_kanban_examples.js +++ b/addons/project/static/src/js/project_task_kanban_examples.js @@ -30,22 +30,26 @@ kanbanExamplesRegistry.add('project', [{ 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')], @@ -73,6 +77,7 @@ kanbanExamplesRegistry.add('project', [{ 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/xml/kanban.xml b/addons/web/static/src/xml/kanban.xml index 3acc0bceac5..8a37bef9277 100644 --- a/addons/web/static/src/xml/kanban.xml +++ b/addons/web/static/src/xml/kanban.xml @@ -158,6 +158,11 @@
+ + + + + Avatar
From 958342bf165bb9b6982e2eaa49d0c8daec7bbb7a Mon Sep 17 00:00:00 2001 From: jem-odoo Date: Wed, 24 Oct 2018 13:03:30 +0000 Subject: [PATCH 7/7] [IMP] web: add example kanban background The background example is a set of random fake column and card, directly inspired from the kanban example modal. We want to toggle this background depending on the kanban state; the background will be displayed when there is no column yet, and the quick create column is shown. To do so, we need to update the state of the kanban when deleting a column to (re)display the background in case of removal of the last column. Now, on column deletion, the entire kanban is updated and so entirely rerender (with aab's benediction). Task-1893021 --- .../src/js/views/kanban/kanban_controller.js | 7 +- .../src/js/views/kanban/kanban_renderer.js | 37 +++++++--- .../src/scss/kanban_examples_dialog.scss | 73 +++++++++++++------ addons/web/static/src/xml/kanban.xml | 28 ++++++- 4 files changed, 104 insertions(+), 41 deletions(-) diff --git a/addons/web/static/src/js/views/kanban/kanban_controller.js b/addons/web/static/src/js/views/kanban/kanban_controller.js index 0f07ea6d565..15c804f5a8e 100644 --- a/addons/web/static/src/js/views/kanban/kanban_controller.js +++ b/addons/web/static/src/js/views/kanban/kanban_controller.js @@ -341,12 +341,7 @@ var KanbanController = BasicController.extend({ this.model .deleteRecords([column.db_id], relatedModelName) .done(function () { - if (column.isEmpty()) { - self.renderer.removeWidget(column); - self._updateButtons(); - } else { - self.reload(); - } + self.update({}, {reload: !column.isEmpty()}); }); }, /** 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 316fb9114cd..51d75a167c7 100644 --- a/addons/web/static/src/js/views/kanban/kanban_renderer.js +++ b/addons/web/static/src/js/views/kanban/kanban_renderer.js @@ -166,15 +166,6 @@ var KanbanRenderer = BasicRenderer.extend({ this.quickCreate.toggleFold(); this._toggleNoContentHelper(); }, - /** - * Removes a widget (record if ungrouped, column if grouped) from the view. - * - * @param {Widget} widget the instance of the widget to remove - */ - removeWidget: function (widget) { - this.widgets.splice(this.widgets.indexOf(widget), 1); - widget.destroy(); - }, /** * Updates a given column with its new state. * @@ -275,6 +266,16 @@ var KanbanRenderer = BasicRenderer.extend({ previousCard.focus(); } }, + /** + * Render the Example Ghost Kanban card on the background + * + * @private + * @param {DocumentFragment} fragment + */ + _renderExampleBackground: function (fragment) { + var $background = $(qweb.render('KanbanView.ExamplesBackground')); + $background.appendTo(fragment); + }, /** * Renders empty invisible divs in a document fragment. * @@ -351,9 +352,9 @@ var KanbanRenderer = BasicRenderer.extend({ // Open it directly if there is no column yet if (!self.state.data.length) { self.quickCreate.toggleFold(); + self._renderExampleBackground(fragment); } }); - } } }, @@ -546,6 +547,7 @@ var KanbanRenderer = BasicRenderer.extend({ _onQuickCreateColumnUpdated: function (ev) { ev.stopPropagation(); this._toggleNoContentHelper(); + this._updateExampleBackground(); }, /** * @private @@ -596,6 +598,21 @@ var KanbanRenderer = BasicRenderer.extend({ _onStartQuickCreate: function () { this._toggleNoContentHelper(true); }, + /** + * Hide or display the background example: + * - displayed when quick create column is display and there is no column else + * - hidden otherwise + * + * @private + **/ + _updateExampleBackground: function () { + var $elem = this.$('.o_kanban_example_background_container'); + if (!this.state.data.length && !$elem.length) { + this._renderExampleBackground(this.$el); + } else { + $elem.remove(); + } + }, }); return KanbanRenderer; diff --git a/addons/web/static/src/scss/kanban_examples_dialog.scss b/addons/web/static/src/scss/kanban_examples_dialog.scss index 65eadc9e0b4..2251896e3a0 100644 --- a/addons/web/static/src/scss/kanban_examples_dialog.scss +++ b/addons/web/static/src/scss/kanban_examples_dialog.scss @@ -1,3 +1,4 @@ +// container ghost card in modal .o_kanban_examples_dialog { display: flex; padding: 0px; @@ -37,35 +38,59 @@ padding: 16px 16px 0; text-align: justify; } + } +} + +// container ghost card in background +.o_kanban_example_background_container { + display: flex; + padding: 0px; + opacity: 0.4; + + // content + .o_kanban_example_background { + flex: 1 1 100%; + .o_kanban_examples { - display: flex; - padding: 0 6px; - .o_kanban_examples_group { - flex: 1 1 100%; - margin: 10px; - .o_kanban_examples_ghost { - padding: 5px; - margin-top: -1px; - border: thin solid gray('300'); - background-color: white; - .o_ghost_content { - height: 12px; - background: gray('300'); - &.o_ghost_tag { - display: inline-block; - width: 40%; - margin-top: 10px; - } - } - .o_ghost_avatar { - height: 20px; - width: 20px; - margin-top: 6px; - } + width: 224px; + margin-bottom: 10px; } } } } } + + +// kanban ghost card +.o_kanban_examples { + display: flex; + padding: 0 6px; + + .o_kanban_examples_group { + flex: 1 1 100%; + margin: 10px; + + .o_kanban_examples_ghost { + padding: 5px; + margin-top: -1px; + border: thin solid gray('300'); + background-color: white; + .o_ghost_content { + height: 12px; + background: gray('300'); + &.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/xml/kanban.xml b/addons/web/static/src/xml/kanban.xml index 8a37bef9277..06ba6b71eb6 100644 --- a/addons/web/static/src/xml/kanban.xml +++ b/addons/web/static/src/xml/kanban.xml @@ -56,10 +56,10 @@
+ Esc to discard - Esc to discard
@@ -167,6 +167,32 @@
+ + +
+
+
+ +
+
Column
+ + + +
+
+
+
+
+
+ +
+
+
+ Avatar +
+ + +