[IMP] web: Kanban: allow to archive/restore column records

This feature has been removed in rev. odoo/odoo@e533085 but this commit
reintroduces it. It was considered as "too dangerous" for new users.

Instead of removing the feature, a confirmation request has been added to warn
the user about his potentially harmful action.

The same warning has also been added in List view when archiving records.

Task 60393

Co-authored-by: Mohammed Shekha <msh@openerp.com>
This commit is contained in:
Hiral Bhavsar
2018-04-25 09:50:44 +02:00
committed by Martin Geubelle
co-authored by Mohammed Shekha
parent b192431aee
commit 5c651a09e1
6 changed files with 117 additions and 4 deletions
@@ -27,6 +27,8 @@ var KanbanColumn = Widget.extend({
'click .o_kanban_quick_add': '_onAddQuickCreate',
'click .o_kanban_load_more': '_onLoadMore',
'click .o_kanban_toggle_fold': '_onToggleFold',
'click .o_column_archive_records': '_onArchiveRecords',
'click .o_column_unarchive_records': '_onUnarchiveRecords'
},
/**
* @override
@@ -355,6 +357,28 @@ var KanbanColumn = Widget.extend({
ev.data.callback(record.$el, record.state.data);
});
},
/**
* @private
* @param {MouseEvent} event
*/
_onArchiveRecords: function (event) {
event.preventDefault();
Dialog.confirm(this, _t("Are you sure that you want to archive all the records from this column?"), {
confirm_callback: this.trigger_up.bind(this, 'kanban_column_records_toggle_active', {
archive: true,
}),
});
},
/**
* @private
* @param {MouseEvent} event
*/
_onUnarchiveRecords: function (event) {
event.preventDefault();
this.trigger_up('kanban_column_records_toggle_active', {
archive: false,
});
}
});
return KanbanColumn;
@@ -30,6 +30,7 @@ var KanbanController = BasicController.extend({
kanban_load_more: '_onLoadMore',
kanban_load_records: '_onLoadColumnRecords',
column_toggle_fold: '_onToggleColumn',
kanban_column_records_toggle_active: '_onToggleActiveRecords',
}),
/**
* @override
@@ -443,6 +444,27 @@ var KanbanController = BasicController.extend({
ev.data.force_save = true;
this._applyChanges(ev.target.db_id, changes, ev);
},
/**
* Allow the user to archive/restore all the records of a column.
*
* @private
* @param {OdooEvent} event
*/
_onToggleActiveRecords: function (event) {
var self = this;
var active = !event.data.archive;
var column = event.target;
var recordIds = _.pluck(column.records, 'db_id');
if (recordIds.length) {
this.model
.toggleActive(recordIds, active, column.db_id)
.then(function (dbID) {
var data = self.model.get(dbID);
self.renderer.updateColumn(dbID, data);
self._updateEnv();
});
}
},
});
return KanbanController;
@@ -10,6 +10,7 @@ odoo.define('web.ListController', function (require) {
var core = require('web.core');
var BasicController = require('web.BasicController');
var DataExport = require('web.DataExport');
var Dialog = require('web.Dialog');
var pyeval = require('web.pyeval');
var Sidebar = require('web.Sidebar');
@@ -136,6 +137,7 @@ var ListController = BasicController.extend({
* @param {jQuery Node} $node
*/
renderSidebar: function ($node) {
var self = this;
if (this.hasSidebar) {
var other = [{
label: _t("Export"),
@@ -144,7 +146,11 @@ var ListController = BasicController.extend({
if (this.archiveEnabled) {
other.push({
label: _t("Archive"),
callback: this._onToggleArchiveState.bind(this, true)
callback: function () {
Dialog.confirm(self, _t("Are you sure that you want to archive all the selected records?"), {
confirm_callback: self._onToggleArchiveState.bind(self, true),
});
}
});
other.push({
label: _t("Unarchive"),
+4
View File
@@ -22,6 +22,10 @@
<li t-if="widget.editable and widget.id"><a class="o_column_edit" href="#">Edit Stage</a></li>
<li t-if="widget.deletable and widget.id"><a class="o_column_delete" href="#">Delete</a></li>
</t>
<t t-if="widget.has_active_field">
<li><a class="o_column_archive_records" href="#">Archive All</a></li>
<li><a class="o_column_unarchive_records" href="#">Restore All</a></li>
</t>
</ul>
</span>
<span t-if="widget.quick_create" class="o_kanban_quick_add"><i class="fa fa-plus"/></span>
+53 -2
View File
@@ -97,7 +97,7 @@ QUnit.module('Views', {
});
QUnit.test('basic grouped rendering', function (assert) {
assert.expect(11);
assert.expect(13);
var kanban = createView({
View: KanbanView,
@@ -135,6 +135,8 @@ QUnit.module('Views', {
"should not be able to edit the column");
assert.ok(!kanban.$('.o_kanban_header:first .o_kanban_config .o_column_delete').length,
"should not be able to delete the column");
assert.ok(!kanban.$('.o_kanban_header:first .o_kanban_config .o_column_archive_records').length, "should not be able to archive all the records");
assert.ok(!kanban.$('.o_kanban_header:first .o_kanban_config .o_column_unarchive_records').length, "should not be able to restore all the records");
// the next line makes sure that reload works properly. It looks useless,
// but it actually test that a grouped local record can be reloaded without
@@ -145,6 +147,51 @@ QUnit.module('Views', {
kanban.destroy();
});
QUnit.test('basic grouped rendering with active field', function (assert) {
assert.expect(9);
// add active field on partner model and make all records active
this.data.partner.fields.active = {string: 'Active', type: 'char', default: true};
var envIDs = [1, 2, 3, 4]; // the ids that should be in the environment during this test
var kanban = createView({
View: KanbanView,
model: 'partner',
data: this.data,
arch: '<kanban class="o_kanban_test">' +
'<field name="active"/>' +
'<field name="bar"/>' +
'<templates><t t-name="kanban-box">' +
'<div><field name="foo"/></div>' +
'</t></templates></kanban>',
groupBy: ['bar'],
intercepts: {
env_updated: function (event) {
assert.deepEqual(event.data.env.ids, envIDs,
"should notify the environment with the correct ids");
},
},
});
// check archive/restore all actions in kanban header's config dropdown
assert.ok(kanban.$('.o_kanban_header:first .o_kanban_config .o_column_archive_records').length, "should be able to archive all the records");
assert.ok(kanban.$('.o_kanban_header:first .o_kanban_config .o_column_unarchive_records').length, "should be able to restore all the records");
// archive the records of the first column
assert.strictEqual(kanban.$('.o_kanban_group:last .o_kanban_record').length, 3,
"last column should contain 3 records");
envIDs = [4];
kanban.$('.o_kanban_group:last .o_column_archive_records').click(); // Click on 'Archive All'
assert.ok($('.modal').length, 'a confirm modal should be displayed');
$('.modal .modal-footer .btn-default').click(); // Click on 'Cancel'
assert.strictEqual(kanban.$('.o_kanban_group:last .o_kanban_record').length, 3, "still last column should contain 3 records");
kanban.$('.o_kanban_group:last .o_column_archive_records').click();
assert.ok($('.modal').length, 'a confirm modal should be displayed');
$('.modal .modal-footer .btn-primary').click(); // Click on 'Ok'
assert.strictEqual(kanban.$('.o_kanban_group:last .o_kanban_record').length, 0, "last column should not contain any records");
kanban.destroy();
});
QUnit.test('pager should be hidden in grouped mode', function (assert) {
assert.expect(1);
@@ -1684,7 +1731,7 @@ QUnit.module('Views', {
});
QUnit.test('delete a column in grouped on m2o', function (assert) {
assert.expect(29);
assert.expect(33);
testUtils.patch(KanbanRenderer, {
_renderGrouped: function () {
@@ -1741,6 +1788,8 @@ QUnit.module('Views', {
"should be able to edit the column");
assert.ok(kanban.$('.o_kanban_group:first .o_column_delete').length,
"should be able to delete the column");
assert.ok(!kanban.$('.o_kanban_group:first .o_column_archive_records').length, "should not be able to archive all the records");
assert.ok(!kanban.$('.o_kanban_group:first .o_column_unarchive_records').length, "should not be able to restore all the records");
// delete second column (first cancel the confirm request, then confirm)
kanban.$('.o_kanban_group:last .o_column_delete').click(); // click on delete
@@ -1763,6 +1812,8 @@ QUnit.module('Views', {
'Undefined column could not be deleted');
assert.ok(!kanban.$('.o_kanban_group:first .o_column_edit').length,
'Undefined column could not be edited');
assert.ok(!kanban.$('.o_kanban_group:first .o_column_archive_records').length, "Records of undefined column could not be archived");
assert.ok(!kanban.$('.o_kanban_group:first .o_column_unarchive_records').length, "Records of undefined column could not be restored");
assert.verifySteps(['read_group', 'unlink', 'read_group']);
assert.strictEqual(kanban.renderer.widgets.length, 2,
"the old widgets should have been correctly deleted");
+7 -1
View File
@@ -843,7 +843,7 @@ QUnit.module('Views', {
});
QUnit.test('archiving one record', function (assert) {
assert.expect(9);
assert.expect(12);
// add active field on foo model and make all records active
this.data.foo.fields.active = {string: 'Active', type: 'boolean', default: true};
@@ -872,7 +872,13 @@ QUnit.module('Views', {
assert.verifySteps(['/web/dataset/search_read']);
list.sidebar.$('a:contains(Archive)').click();
assert.strictEqual($('.modal').length, 1, 'a confirm modal should be displayed');
$('.modal .modal-footer .btn-default').click(); // Click on 'Cancel'
assert.strictEqual(list.$('tbody td.o_list_record_selector').length, 4, "still should have 4 records");
list.sidebar.$('a:contains(Archive)').click();
assert.strictEqual($('.modal').length, 1, 'a confirm modal should be displayed');
$('.modal .modal-footer .btn-primary').click(); // Click on 'Ok'
assert.strictEqual(list.$('tbody td.o_list_record_selector').length, 3, "should have 3 records");
assert.verifySteps(['/web/dataset/search_read', '/web/dataset/call_kw/foo/write', '/web/dataset/search_read']);
list.destroy();