[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.
This commit is contained in:
committed by
Yannick Tivisse
parent
dd427405e2
commit
2adc9d5032
@@ -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')]
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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")
|
||||
@@ -278,19 +290,6 @@ class Project(models.Model):
|
||||
self.mapped('tasks').message_unsubscribe(partner_ids=partner_ids, channel_ids=channel_ids)
|
||||
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'}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user