summaryrefslogtreecommitdiff
path: root/addons
diff options
context:
space:
mode:
authorJigar Patel <jat@openerp.com>2017-05-09 15:02:17 +0530
committerYannick Tivisse <yti@odoo.com>2017-08-09 15:11:53 +0200
commit2adc9d50321d58fa7f33a0231a5594d338a3ffa4 (patch)
tree5ed676b1be7eb33ce50120825550dd091e087ae9 /addons
parentdd427405e2f1683a1b46d5fba1d271e77ea34e93 (diff)
[IMP] account: Add a new boolean_favorite widget
Purpose ======= Projects and soon sales teams have a manual "favorite" button that calls a toggle_favorite method It should actually be a widget on a boolean field Specifications ============== Develop a favorite widget for kanban view that allows to toggle a boolean field Probably update boolean field to allow inverse method on it Functionally nothing changed.
Diffstat (limited to 'addons')
-rw-r--r--addons/account/models/account_journal_dashboard.py5
-rw-r--r--addons/account/views/account_journal_dashboard_view.xml2
-rw-r--r--addons/project/models/project.py27
-rw-r--r--addons/project/static/src/less/project_dashboard.less14
-rw-r--r--addons/project/views/project_views.xml3
-rw-r--r--addons/sales_team/models/crm_team.py17
-rw-r--r--addons/sales_team/views/sales_team_dashboard.xml6
-rw-r--r--addons/web/static/src/js/fields/basic_fields.js53
-rw-r--r--addons/web/static/src/js/fields/field_registry.js1
-rw-r--r--addons/web/static/src/less/fields.less16
-rw-r--r--addons/web/static/tests/fields/basic_fields_tests.js123
11 files changed, 217 insertions, 50 deletions
diff --git a/addons/account/models/account_journal_dashboard.py b/addons/account/models/account_journal_dashboard.py
index 82828965d52..361962fa29f 100644
--- a/addons/account/models/account_journal_dashboard.py
+++ b/addons/account/models/account_journal_dashboard.py
@@ -26,11 +26,6 @@ class account_journal(models.Model):
kanban_dashboard_graph = fields.Text(compute='_kanban_dashboard_graph')
show_on_dashboard = fields.Boolean(string='Show journal on dashboard', help="Whether this journal should be displayed on the dashboard or not", default=True)
- @api.multi
- def toggle_favorite(self):
- self.write({'show_on_dashboard': False if self.show_on_dashboard else True})
- return False
-
def _graph_title_and_key(self):
if self.type == 'sale':
return ['', _('Sales: Untaxed Total')]
diff --git a/addons/account/views/account_journal_dashboard_view.xml b/addons/account/views/account_journal_dashboard_view.xml
index 4b07b8a7010..024dd725bbf 100644
--- a/addons/account/views/account_journal_dashboard_view.xml
+++ b/addons/account/views/account_journal_dashboard_view.xml
@@ -209,7 +209,7 @@
<div groups="account.group_account_manager" class="row o_kanban_card_settings">
<div class="col-xs-6">
- <a type="object" name="toggle_favorite"><i t-attf-class="fa o_dashboard_star #{record.show_on_dashboard.raw_value ? 'fa-star' : 'fa-star-o'}" title="Click to add/remove from favorite"/> Favorite</a>
+ <field name="show_on_dashboard" widget="boolean_favorite" />
</div>
<div class="col-xs-6 text-right">
<a t-if="widget.editable" type="edit">Settings</a>
diff --git a/addons/project/models/project.py b/addons/project/models/project.py
index 7d46b94393d..49014a07481 100644
--- a/addons/project/models/project.py
+++ b/addons/project/models/project.py
@@ -151,6 +151,18 @@ class Project(models.Model):
for project in self:
project.is_favorite = self.env.user in project.favorite_user_ids
+ def _inverse_is_favorite(self):
+ favorite_projects = not_fav_projects = self.env['project.project'].sudo()
+ for project in self:
+ if self.env.user in project.favorite_user_ids:
+ favorite_projects |= project
+ else:
+ not_fav_projects |= project
+
+ # Project User has no write access for project.
+ not_fav_projects.write({'favorite_user_ids': [(4, self.env.uid)]})
+ favorite_projects.write({'favorite_user_ids': [(3, self.env.uid)]})
+
def _get_default_favorite_user_ids(self):
return [(6, 0, [self.env.uid])]
@@ -172,7 +184,7 @@ class Project(models.Model):
'res.users', 'project_favorite_user_rel', 'project_id', 'user_id',
default=_get_default_favorite_user_ids,
string='Members')
- is_favorite = fields.Boolean(compute='_compute_is_favorite', string='Show Project on dashboard',
+ is_favorite = fields.Boolean(compute='_compute_is_favorite', inverse='_inverse_is_favorite', string='Show Project on dashboard',
help="Whether this project should be displayed on the dashboard or not")
label_tasks = fields.Char(string='Use Tasks as', default='Tasks', help="Gives label to tasks on project's kanban view.")
tasks = fields.One2many('project.task', 'project_id', string="Task Activities")
@@ -279,19 +291,6 @@ class Project(models.Model):
return super(Project, self).message_unsubscribe(partner_ids=partner_ids, channel_ids=channel_ids)
@api.multi
- def toggle_favorite(self):
- favorite_projects = not_fav_projects = self.env['project.project'].sudo()
- for project in self:
- if self.env.user in project.favorite_user_ids:
- favorite_projects |= project
- else:
- not_fav_projects |= project
-
- # Project User has no write access for project.
- not_fav_projects.write({'favorite_user_ids': [(4, self.env.uid)]})
- favorite_projects.write({'favorite_user_ids': [(3, self.env.uid)]})
-
- @api.multi
def close_dialog(self):
return {'type': 'ir.actions.act_window_close'}
diff --git a/addons/project/static/src/less/project_dashboard.less b/addons/project/static/src/less/project_dashboard.less
index b1e966c8f87..54851046a27 100644
--- a/addons/project/static/src/less/project_dashboard.less
+++ b/addons/project/static/src/less/project_dashboard.less
@@ -38,20 +38,6 @@
}
}
- .o_dashboard_star {
- font-size: 16px;
-
- &.fa-star-o {
- color: @odoo-main-color-muted;
- &:hover {
- color: gold;
- }
- }
- &.fa-star {
- color: gold;
- }
- }
-
.o_project_kanban_boxes {
width: 30%;
.o-flex(0, 0, auto);
diff --git a/addons/project/views/project_views.xml b/addons/project/views/project_views.xml
index 23397729a79..84bfe4b4338 100644
--- a/addons/project/views/project_views.xml
+++ b/addons/project/views/project_views.xml
@@ -263,7 +263,6 @@
<field name="alias_id"/>
<field name="alias_name"/>
<field name="alias_domain"/>
- <field name="is_favorite"/>
<templates>
<t t-name="kanban-box">
<div t-attf-class="#{kanban_color(record.color.raw_value)} oe_kanban_global_click">
@@ -296,7 +295,7 @@
</div>
<div class="o_project_kanban_manage">
<a class="o_kanban_manage_toggle_button o_left" href="#"><i class="fa fa-ellipsis-v" /></a>
- <a type="object" name="toggle_favorite" class="o_right"><i t-attf-class="oe_inline fa o_dashboard_star #{record.is_favorite.raw_value ? 'fa-star' : 'fa-star-o'}" title="Add/remove from favorite"/></a>
+ <span class="o_right"><field name="is_favorite" widget="boolean_favorite" nolabel="1" /></span>
</div>
</div>
diff --git a/addons/sales_team/models/crm_team.py b/addons/sales_team/models/crm_team.py
index 99333bc52c5..5aeaba6aeec 100644
--- a/addons/sales_team/models/crm_team.py
+++ b/addons/sales_team/models/crm_team.py
@@ -55,7 +55,7 @@ class CrmTeam(models.Model):
default=_get_default_favorite_user_ids)
is_favorite = fields.Boolean(
string='Show on dashboard',
- compute='_compute_is_favorite', inverse='_set_is_favorite',
+ compute='_compute_is_favorite', inverse='_inverse_is_favorite',
help="Favorite teams to display them in the dashboard and access them easily.")
reply_to = fields.Char(string='Reply-To',
help="The email address put in the 'Reply-To' of all emails sent by Odoo about cases in this sales channel")
@@ -95,6 +95,13 @@ class CrmTeam(models.Model):
for team in self:
team.is_favorite = self.env.user in team.favorite_user_ids
+ def _inverse_is_favorite(self):
+ sudoed_self = self.sudo()
+ to_fav = sudoed_self.filtered(lambda team: self.env.user not in team.favorite_user_ids)
+ to_fav.write({'favorite_user_ids': [(4, self.env.uid)]})
+ (sudoed_self - to_fav).write({'favorite_user_ids': [(3, self.env.uid)]})
+ return True
+
def _graph_get_dates(self, today):
""" return a coherent start and end date for the dashboard graph according to the graph settings.
"""
@@ -286,14 +293,6 @@ class CrmTeam(models.Model):
self._add_members_to_favorites()
return res
- @api.multi
- def toggle_favorite(self):
- sudoed_self = self.sudo()
- to_fav = sudoed_self.filtered(lambda team: self.env.user not in team.favorite_user_ids)
- to_fav.write({'favorite_user_ids': [(4, self.env.uid)]})
- (sudoed_self - to_fav).write({'favorite_user_ids': [(3, self.env.uid)]})
- return True
-
def _add_members_to_favorites(self):
for team in self:
team.favorite_user_ids = [(4, member.id) for member in team.member_ids]
diff --git a/addons/sales_team/views/sales_team_dashboard.xml b/addons/sales_team/views/sales_team_dashboard.xml
index 246029b70a1..a89c050dcaa 100644
--- a/addons/sales_team/views/sales_team_dashboard.xml
+++ b/addons/sales_team/views/sales_team_dashboard.xml
@@ -70,11 +70,7 @@
</div>
<div class="row mb16">
<div class="col-xs-6">
- <a type="object" name="toggle_favorite">
- <i t-attf-class="fa o_dashboard_star #{record.is_favorite.raw_value ? 'fa-star' : 'fa-star-o'}" title="Click to add/remove from favorite"/>
- <l t-if="record.is_favorite.raw_value"> Remove from My Favorites</l>
- <l t-elif="!record.is_favorite.raw_value"> Add to My Favorites</l>
- </a>
+ <field name="is_favorite" widget="boolean_favorite" />
</div>
</div>
</div>
diff --git a/addons/web/static/src/js/fields/basic_fields.js b/addons/web/static/src/js/fields/basic_fields.js
index 2de5a73802d..2d18a0ddb56 100644
--- a/addons/web/static/src/js/fields/basic_fields.js
+++ b/addons/web/static/src/js/fields/basic_fields.js
@@ -1449,6 +1449,58 @@ var StateSelectionWidget = AbstractField.extend({
},
});
+var FavoriteWidget = AbstractField.extend({
+ className: 'o_favorite',
+ events: {
+ 'click': '_setFavorite'
+ },
+ supportedFieldTypes: ['boolean'],
+
+ //--------------------------------------------------------------------------
+ // Public
+ //--------------------------------------------------------------------------
+
+ /**
+ * A boolean field is always set since false is a valid value.
+ *
+ * @override
+ */
+ isSet: function () {
+ return true;
+ },
+
+ //--------------------------------------------------------------------------
+ // Private
+ //--------------------------------------------------------------------------
+
+ /**
+ * Render favorite icon based on state
+ *
+ * @override
+ * @private
+ */
+ _render: function () {
+ var template = this.attrs.nolabel ? '<a href="#"><i class="fa %s" title="%s"></i></a>' : '<a href="#"><i class="fa %s"></i> %s</a>';
+ this.$el.empty().append(_.str.sprintf(template, this.value ? 'fa-star' : 'fa-star-o', this.value ? _t('Remove from Favorites') : _t('Add to Favorites')));
+ },
+
+ //--------------------------------------------------------------------------
+ // Handlers
+ //--------------------------------------------------------------------------
+
+ /**
+ * Toggle favorite state
+ *
+ * @private
+ * @param {MouseEvent} event
+ */
+ _setFavorite: function (event) {
+ event.preventDefault();
+ event.stopPropagation();
+ this._setValue(!this.value);
+ },
+});
+
var LabelSelection = AbstractField.extend({
supportedFieldTypes: ['selection'],
@@ -2350,6 +2402,7 @@ return {
AttachmentImage: AttachmentImage,
LabelSelection: LabelSelection,
StateSelectionWidget: StateSelectionWidget,
+ FavoriteWidget: FavoriteWidget,
PriorityWidget: PriorityWidget,
StatInfo: StatInfo,
UrlWidget: UrlWidget,
diff --git a/addons/web/static/src/js/fields/field_registry.js b/addons/web/static/src/js/fields/field_registry.js
index 91bba587117..019a98e51f1 100644
--- a/addons/web/static/src/js/fields/field_registry.js
+++ b/addons/web/static/src/js/fields/field_registry.js
@@ -40,6 +40,7 @@ registry
.add('label_selection', basic_fields.LabelSelection)
.add('state_selection', basic_fields.StateSelectionWidget)
.add('kanban_state_selection', basic_fields.StateSelectionWidget)
+ .add('boolean_favorite', basic_fields.FavoriteWidget)
.add('boolean_button', basic_fields.FieldBooleanButton)
.add('boolean_toggle', basic_fields.BooleanToggle)
.add('statinfo', basic_fields.StatInfo)
diff --git a/addons/web/static/src/less/fields.less b/addons/web/static/src/less/fields.less
index 02885ef3514..8463dd312cc 100644
--- a/addons/web/static/src/less/fields.less
+++ b/addons/web/static/src/less/fields.less
@@ -180,6 +180,22 @@
}
}
+ // Favorite
+ &.o_favorite {
+ i.fa {
+ font-size: 16px;
+ }
+ i.fa-star-o {
+ color: @odoo-main-color-muted;
+ &:hover {
+ color: gold;
+ }
+ }
+ i.fa-star {
+ color: gold;
+ }
+ }
+
// Specific success color for toggle_button widget
.fa.o_toggle_button_success {
color: @brand-success;
diff --git a/addons/web/static/tests/fields/basic_fields_tests.js b/addons/web/static/tests/fields/basic_fields_tests.js
index 508e86d9cd3..c2ab8121c16 100644
--- a/addons/web/static/tests/fields/basic_fields_tests.js
+++ b/addons/web/static/tests/fields/basic_fields_tests.js
@@ -2997,6 +2997,129 @@ QUnit.module('basic_fields', {
});
+ QUnit.module('FavoriteWidget');
+
+ QUnit.test('favorite widget in kanban view', function (assert) {
+ assert.expect(4);
+
+ var kanban = createView({
+ View: KanbanView,
+ model: 'partner',
+ data: this.data,
+ arch: '<kanban class="o_kanban_test">' +
+ '<templates>' +
+ '<t t-name="kanban-box">' +
+ '<div>' +
+ '<field name="bar" widget="boolean_favorite" />' +
+ '</div>' +
+ '</t>' +
+ '</templates>' +
+ '</kanban>',
+ domain: [['id', '=', 1]],
+ });
+
+ assert.strictEqual(kanban.$('.o_kanban_record .o_field_widget.o_favorite > a i.fa.fa-star').length, 1,
+ 'should be favorite');
+ assert.strictEqual(kanban.$('.o_kanban_record .o_field_widget.o_favorite > a').text(), ' Remove from Favorites',
+ 'the label should say "Remove from Favorites"');
+
+ // click on favorite
+ kanban.$('.o_field_widget.o_favorite').click();
+ assert.strictEqual(kanban.$('.o_kanban_record .o_field_widget.o_favorite > a i.fa.fa-star').length, 0,
+ 'should not be favorite');
+ assert.strictEqual(kanban.$('.o_kanban_record .o_field_widget.o_favorite > a').text(), ' Add to Favorites',
+ 'the label should say "Add to Favorites"');
+
+ kanban.destroy();
+ });
+
+ QUnit.test('favorite widget in form view', function (assert) {
+ assert.expect(10);
+
+ var form = createView({
+ View: FormView,
+ model: 'partner',
+ data: this.data,
+ arch: '<form string="Partners">' +
+ '<sheet>' +
+ '<group>' +
+ '<field name="bar" widget="boolean_favorite" />' +
+ '</group>' +
+ '</sheet>' +
+ '</form>',
+ res_id: 1,
+ });
+
+ assert.strictEqual(form.$('.o_field_widget.o_favorite > a i.fa.fa-star').length, 1,
+ 'should be favorite');
+ assert.strictEqual(form.$('.o_field_widget.o_favorite > a').text(), ' Remove from Favorites',
+ 'the label should say "Remove from Favorites"');
+
+ // click on favorite
+ form.$('.o_field_widget.o_favorite').click();
+ assert.strictEqual(form.$('.o_field_widget.o_favorite > a i.fa.fa-star').length, 0,
+ 'should not be favorite');
+ assert.strictEqual(form.$('.o_field_widget.o_favorite > a').text(), ' Add to Favorites',
+ 'the label should say "Add to Favorites"');
+
+ // switch to edit mode
+ form.$buttons.find('.o_form_button_edit').click();
+ assert.strictEqual(form.$('.o_field_widget.o_favorite > a i.fa.fa-star-o').length, 1,
+ 'should not be favorite');
+ assert.strictEqual(form.$('.o_field_widget.o_favorite > a').text(), ' Add to Favorites',
+ 'the label should say "Add to Favorites"');
+
+ // click on favorite
+ form.$('.o_field_widget.o_favorite').click();
+ assert.strictEqual(form.$('.o_field_widget.o_favorite > a i.fa.fa-star').length, 1,
+ 'should be favorite');
+ assert.strictEqual(form.$('.o_field_widget.o_favorite > a').text(), ' Remove from Favorites',
+ 'the label should say "Remove from Favorites"');
+
+ // save
+ form.$buttons.find('.o_form_button_save').click();
+ assert.strictEqual(form.$('.o_field_widget.o_favorite > a i.fa.fa-star').length, 1,
+ 'should be favorite');
+ assert.strictEqual(form.$('.o_field_widget.o_favorite > a').text(), ' Remove from Favorites',
+ 'the label should say "Remove from Favorites"');
+
+ form.destroy();
+ });
+
+ QUnit.test('favorite widget in editable list view without label', function (assert) {
+ assert.expect(4);
+
+ var list = createView({
+ View: ListView,
+ model: 'partner',
+ data: this.data,
+ arch: '<tree editable="bottom">' +
+ '<field name="bar" widget="boolean_favorite" nolabel="1" />' +
+ '</tree>',
+ });
+
+ assert.strictEqual(list.$('.o_data_row:first .o_field_widget.o_favorite > a i.fa.fa-star').length, 1,
+ 'should be favorite');
+
+ // switch to edit mode
+ list.$('tbody td:not(.o_list_record_selector)').first().click();
+ assert.strictEqual(list.$('.o_data_row:first .o_field_widget.o_favorite > a i.fa.fa-star').length, 1,
+ 'should be favorite');
+
+ // click on favorite
+ list.$('.o_data_row:first .o_field_widget.o_favorite').click();
+ assert.strictEqual(list.$('.o_data_row:first .o_field_widget.o_favorite > a i.fa.fa-star').length, 0,
+ 'should not be favorite');
+
+ // save
+ list.$buttons.find('.o_list_button_save').click();
+ assert.strictEqual(list.$('.o_data_row:first .o_field_widget.o_favorite > a i.fa.fa-star-o').length, 1,
+ 'should not be favorite');
+
+ list.destroy();
+ });
+
+
QUnit.module('LabelSelectionWidget');
QUnit.test('label_selection widget in form view', function (assert) {