[IMP] web: Kanban: quick create record with more fields
This rev. improves the QuickCreate widget for grouped Kanban views.
It allows specifying in the Kanban arch a form view xmlid, e.g.:
<kanban quick_create_view="some_form_view_xmlid">
...
</kanban>
When this attribute is set, the referenced form view is loaded and
rendered inside the QuickCreate widget. A real FormView widget is
instantiated, meaning that all form view mechanisms are available
in the QuickCreate (modifiers, default_get, onchanges, widgets...).
Task #27475.
This commit is contained in:
@@ -68,7 +68,7 @@ var BasicController = AbstractController.extend(FieldManagerMixin, {
|
||||
* rejected otherwise
|
||||
*/
|
||||
canBeDiscarded: function (recordID) {
|
||||
if (!this.model.isDirty(recordID || this.handle)) {
|
||||
if (!this.isDirty(recordID)) {
|
||||
return $.when(false);
|
||||
}
|
||||
|
||||
@@ -120,6 +120,15 @@ var BasicController = AbstractController.extend(FieldManagerMixin, {
|
||||
getSelectedIds: function () {
|
||||
return [];
|
||||
},
|
||||
/**
|
||||
* Returns true iff the given recordID (or the main recordID) is dirty.
|
||||
*
|
||||
* @param {string} [recordID] - default to main recordID
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isDirty: function (recordID) {
|
||||
return this.model.isDirty(recordID || this.handle);
|
||||
},
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
|
||||
@@ -18,10 +18,19 @@ var FormRenderer = BasicRenderer.extend({
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
init: function (parent, state, params) {
|
||||
init: function () {
|
||||
this._super.apply(this, arguments);
|
||||
this.idsForLabels = {};
|
||||
},
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
start: function () {
|
||||
if (config.device.size_class <= config.device.SIZES.XXS) {
|
||||
this.$el.addClass('o_xxs_form_view');
|
||||
}
|
||||
return this._super.apply(this, arguments);
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Public
|
||||
|
||||
@@ -47,6 +47,8 @@ var KanbanColumn = Widget.extend({
|
||||
this.modelName = data.model;
|
||||
|
||||
this.quick_create = options.quick_create;
|
||||
this.quickCreateView = options.quickCreateView;
|
||||
this.groupedBy = options.groupedBy;
|
||||
this.grouped_by_m2o = options.grouped_by_m2o;
|
||||
this.editable = options.editable;
|
||||
this.deletable = options.deletable;
|
||||
@@ -156,6 +158,18 @@ var KanbanColumn = Widget.extend({
|
||||
|
||||
return $.when.apply($, defs);
|
||||
},
|
||||
/**
|
||||
* Called when a record has been quick created, as a new column is rendered
|
||||
* and appended into a fragment, before replacing the old column in the DOM.
|
||||
* When this happens, the quick create widget is inserted into the new
|
||||
* column directly, and it should be focused. However, as it is rendered
|
||||
* into a fragment, the focus has to be set manually once in the DOM.
|
||||
*/
|
||||
on_attach_callback: function () {
|
||||
if (this.quickCreateWidget) {
|
||||
this.quickCreateWidget.on_attach_callback();
|
||||
}
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Public
|
||||
@@ -163,6 +177,8 @@ var KanbanColumn = Widget.extend({
|
||||
|
||||
/**
|
||||
* Adds the quick create record to the top of the column.
|
||||
*
|
||||
* @returns {Deferred}
|
||||
*/
|
||||
addQuickCreate: function () {
|
||||
if (this.folded) {
|
||||
@@ -173,11 +189,25 @@ var KanbanColumn = Widget.extend({
|
||||
return;
|
||||
}
|
||||
if (this.quickCreateWidget) {
|
||||
return;
|
||||
return $.Deferred().reject();
|
||||
}
|
||||
this.trigger_up('close_quick_create'); // close other quick create widgets
|
||||
var context = this.data.getContext();
|
||||
context['default_' + this.groupedBy] = this.id;
|
||||
this.quickCreateWidget = new RecordQuickCreate(this, {
|
||||
context: context,
|
||||
formViewRef: this.quickCreateView,
|
||||
model: this.modelName,
|
||||
});
|
||||
return this.quickCreateWidget.insertAfter(this.$header);
|
||||
},
|
||||
/**
|
||||
* Closes the quick create widget if it isn't dirty.
|
||||
*/
|
||||
cancelQuickCreate: function () {
|
||||
if (this.quickCreateWidget) {
|
||||
this.quickCreateWidget.cancel();
|
||||
}
|
||||
var width = this.records.length ? this.records[0].$el.innerWidth() : this.$el.width() - 8;
|
||||
this.quickCreateWidget = new RecordQuickCreate(this, width);
|
||||
this.quickCreateWidget.insertAfter(this.$header);
|
||||
},
|
||||
/**
|
||||
* @returns {Boolean} true iff the column is empty
|
||||
|
||||
@@ -297,52 +297,51 @@ var KanbanController = BasicController.extend({
|
||||
/**
|
||||
* @private
|
||||
* @param {OdooEvent} event
|
||||
* @param {KanbanColumn} event.target the column in which the record should
|
||||
* be added
|
||||
* @param {Object} event.data.values the field values of the record to
|
||||
* create; if values only contains the value of the 'display_name', a
|
||||
* 'name_create' is performed instead of 'create'
|
||||
*/
|
||||
_onQuickCreateRecord: function (event) {
|
||||
var self = this;
|
||||
var values = event.data.values;
|
||||
var column = event.target;
|
||||
var name = event.data.value;
|
||||
var state = this.model.get(this.handle, {raw: true});
|
||||
var columnState = this.model.get(column.db_id, {raw: true});
|
||||
var context = columnState.getContext();
|
||||
context['default_' + state.groupedBy[0]] = columnState.res_id;
|
||||
|
||||
this._rpc({
|
||||
model: state.model,
|
||||
method: 'name_create',
|
||||
args: [name],
|
||||
context: context,
|
||||
})
|
||||
.then(add_record)
|
||||
// function that updates the kanban view once the record has been added
|
||||
// it receives the local id of the created record in arguments
|
||||
var update = function (db_id) {
|
||||
self._updateEnv();
|
||||
|
||||
var columnState = self.model.getColumn(db_id);
|
||||
return self.renderer
|
||||
.updateColumn(columnState.id, columnState, {openQuickCreate: true})
|
||||
.then(function () {
|
||||
if (event.data.openRecord) {
|
||||
self.trigger_up('open_record', {id: db_id, mode: 'edit'});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
this.model.createRecordInGroup(column.db_id, values)
|
||||
.then(update)
|
||||
.fail(function (error, event) {
|
||||
event.preventDefault();
|
||||
var columnState = self.model.get(column.db_id, {raw: true});
|
||||
var context = columnState.getContext();
|
||||
var state = self.model.get(self.handle, {raw: true});
|
||||
context['default_' + state.groupedBy[0]] = columnState.res_id;
|
||||
new view_dialogs.FormViewDialog(self, {
|
||||
res_model: state.model,
|
||||
context: _.extend({default_name: name}, context),
|
||||
title: _t("Create"),
|
||||
disable_multiple_selection: true,
|
||||
on_saved: function (record) {
|
||||
add_record([record.res_id]);
|
||||
self.model.addRecordToGroup(column.db_id, record.res_id)
|
||||
.then(update);
|
||||
},
|
||||
}).open();
|
||||
});
|
||||
|
||||
function add_record(records) {
|
||||
return self.model
|
||||
.addRecordToGroup(columnState.id, records[0])
|
||||
.then(function (db_id) {
|
||||
self._updateEnv();
|
||||
|
||||
var columnState = self.model.getColumn(db_id);
|
||||
return self.renderer
|
||||
.updateColumn(columnState.id, columnState, {openQuickCreate: true})
|
||||
.then(function () {
|
||||
if (event.data.openRecord) {
|
||||
self.trigger_up('open_record', {id: db_id, mode: 'edit'});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
|
||||
@@ -33,7 +33,7 @@ var KanbanModel = BasicModel.extend({
|
||||
parentID: groupID,
|
||||
});
|
||||
|
||||
return this._fetchRecord(new_record).then(function (result) {
|
||||
var def = this._fetchRecord(new_record).then(function (result) {
|
||||
group.data.unshift(new_record.id);
|
||||
group.res_ids.unshift(resId);
|
||||
group.count++;
|
||||
@@ -44,6 +44,7 @@ var KanbanModel = BasicModel.extend({
|
||||
|
||||
return result.id;
|
||||
});
|
||||
return this._reloadProgressBarGroupFromRecord(new_record.id, def);
|
||||
},
|
||||
/**
|
||||
* Creates a new group from a name (performs a name_create).
|
||||
@@ -93,6 +94,43 @@ var KanbanModel = BasicModel.extend({
|
||||
return newGroup.id;
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Creates a new record from the given value, and add it to the given group.
|
||||
*
|
||||
* @param {string} groupID
|
||||
* @param {Object} values
|
||||
* @returns {Deferred} resolved with the local id of the created record
|
||||
*/
|
||||
createRecordInGroup: function (groupID, values) {
|
||||
var self = this;
|
||||
var group = this.localData[groupID];
|
||||
var context = this._getContext(group);
|
||||
var parent = this.localData[group.parentID];
|
||||
context['default_' + parent.groupedBy[0]] = group.res_id;
|
||||
var def;
|
||||
if (Object.keys(values).length === 1 && 'display_name' in values) {
|
||||
// only 'display_name is given, perform a 'name_create'
|
||||
def = this._rpc({
|
||||
model: parent.model,
|
||||
method: 'name_create',
|
||||
args: [values.display_name],
|
||||
context: context,
|
||||
}).then(function (records) {
|
||||
return records[0];
|
||||
});
|
||||
} else {
|
||||
// other fields are specified, perform a classical 'create'
|
||||
def = this._rpc({
|
||||
model: parent.model,
|
||||
method: 'create',
|
||||
args: [values],
|
||||
context: context,
|
||||
});
|
||||
}
|
||||
return def.then(function (resID) {
|
||||
return self.addRecordToGroup(group.id, resID);
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Add the key `tooltipData` (kanban specific) when performing a `geŧ`.
|
||||
*
|
||||
|
||||
@@ -6,17 +6,121 @@ odoo.define('web.kanban_quick_create', function (require) {
|
||||
* kanban records, and one to quick create kanban columns.
|
||||
*/
|
||||
|
||||
var core = require('web.core');
|
||||
var QuickCreateFormView = require('web.QuickCreateFormView');
|
||||
var Widget = require('web.Widget');
|
||||
|
||||
var AbstractQuickCreate = Widget.extend({
|
||||
var qweb = core.qweb;
|
||||
|
||||
var RecordQuickCreate = Widget.extend({
|
||||
className: 'o_kanban_quick_create',
|
||||
custom_events: {
|
||||
add: '_onAdd',
|
||||
cancel: '_onCancel',
|
||||
},
|
||||
events: {
|
||||
'click .o_kanban_add': '_onAddClicked',
|
||||
'click .o_kanban_edit': '_onEditClicked',
|
||||
'click .o_kanban_cancel': '_onCancelClicked',
|
||||
'keydown': '_onKeydown',
|
||||
'keypress input': '_onKeypress',
|
||||
'mousedown .o_kanban_add': '_onMousedown',
|
||||
'mousedown .o_kanban_cancel': '_onMousedown',
|
||||
'focusout': '_onFocusOut',
|
||||
},
|
||||
|
||||
/**
|
||||
* @override
|
||||
* @param {Widget} parent
|
||||
* @param {Object} options
|
||||
* @param {Object} options.context
|
||||
* @param {string|null} options.formViewRef
|
||||
* @param {string} options.model
|
||||
*/
|
||||
init: function (parent, options) {
|
||||
this._super.apply(this, arguments);
|
||||
this.context = options.context;
|
||||
this.formViewRef = options.formViewRef;
|
||||
this.model = options.model;
|
||||
},
|
||||
/**
|
||||
* Loads the form fieldsView (if not provided), instantiates the form view
|
||||
* and starts the form controller.
|
||||
*
|
||||
* @override
|
||||
*/
|
||||
willStart: function () {
|
||||
var self = this;
|
||||
var def1 = this._super.apply(this, arguments);
|
||||
var def2;
|
||||
if (this.formViewRef) {
|
||||
var views = [[false, 'form']];
|
||||
var context = _.extend({}, this.context, {
|
||||
form_view_ref: this.formViewRef,
|
||||
});
|
||||
def2 = this.loadViews(this.model, context, views);
|
||||
} else {
|
||||
var fieldsView = {};
|
||||
fieldsView.arch = '<form>' +
|
||||
'<field name="display_name" placeholder="Title" modifiers=\'{"required": true}\'/>' +
|
||||
'</form>';
|
||||
var fields = {
|
||||
display_name: {string: 'Display name', type: 'char'},
|
||||
};
|
||||
fieldsView.fields = fields;
|
||||
fieldsView.viewFields = fields;
|
||||
def2 = $.when({form: fieldsView});
|
||||
}
|
||||
def2 = def2.then(function (fieldsViews) {
|
||||
var formView = new QuickCreateFormView(fieldsViews.form, {
|
||||
context: self.context,
|
||||
modelName: self.model,
|
||||
userContext: self.getSession().user_context,
|
||||
});
|
||||
return formView.getController(self).then(function (controller) {
|
||||
self.controller = controller;
|
||||
return self.controller.appendTo(document.createDocumentFragment());
|
||||
});
|
||||
});
|
||||
return $.when(def1, def2);
|
||||
},
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
start: function () {
|
||||
this.$el.append(this.controller.$el);
|
||||
this.$el.append(qweb.render('KanbanView.RecordQuickCreate.buttons'));
|
||||
|
||||
// focus the first field
|
||||
this.controller.autofocus();
|
||||
|
||||
// destroy the quick create when the user clicks outside
|
||||
core.bus.on('click', this, this._onWindowClicked);
|
||||
|
||||
return this._super.apply(this, arguments);
|
||||
},
|
||||
/**
|
||||
* Called when the quick create is appended into the DOM.
|
||||
*/
|
||||
on_attach_callback: function () {
|
||||
if (this.controller) {
|
||||
this.controller.autofocus();
|
||||
}
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Public
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Cancels the quick creation if the record isn't dirty, i.e. if no changes
|
||||
* have been made yet
|
||||
*
|
||||
* @private
|
||||
* @returns {Deferred}
|
||||
*/
|
||||
cancel: function () {
|
||||
var self = this;
|
||||
return this.controller.commitChanges().then(function () {
|
||||
if (!self.controller.isDirty()) {
|
||||
self._cancel();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
@@ -24,37 +128,210 @@ var AbstractQuickCreate = Widget.extend({
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Clears the input value and notify the environment that a quick create
|
||||
* has been done
|
||||
*
|
||||
* @override
|
||||
* @private
|
||||
* @param {Object} [options] dict of options to pass to call to '_notifyAdd'
|
||||
* @param {Object} [options]
|
||||
* @param {boolean} [options.openRecord] set to true to directly open the
|
||||
* newly created record in a form view (in edit mode)
|
||||
* @returns {Deferred}
|
||||
*/
|
||||
_add: function (options) {
|
||||
var value = this.$input.val();
|
||||
this.$input.val('');
|
||||
if (/^\s*$/.test(value)) {
|
||||
var self = this;
|
||||
return this.controller.commitChanges().then(function () {
|
||||
var canBeSaved = self.controller.canBeSaved();
|
||||
if (canBeSaved) {
|
||||
self.trigger_up('quick_create_add_record', {
|
||||
openRecord: options && options.openRecord || false,
|
||||
values: self.controller.getChanges(),
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Notifies the environment that the quick creation must be cancelled
|
||||
*
|
||||
* @private
|
||||
* @returns {Deferred}
|
||||
*/
|
||||
_cancel: function () {
|
||||
this.trigger_up('cancel_quick_create');
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Handlers
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {OdooEvent} ev
|
||||
*/
|
||||
_onAdd: function (ev) {
|
||||
ev.stopPropagation();
|
||||
this._add();
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
* @param {MouseEvent} ev
|
||||
*/
|
||||
_onAddClicked: function (ev) {
|
||||
ev.stopPropagation();
|
||||
this._add();
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
* @param {OdooEvent} ev
|
||||
*/
|
||||
_onCancel: function (ev) {
|
||||
ev.stopPropagation();
|
||||
this._cancel();
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
* @param {MouseEvent} ev
|
||||
*/
|
||||
_onCancelClicked: function (ev) {
|
||||
ev.stopPropagation();
|
||||
this._cancel();
|
||||
},
|
||||
/**
|
||||
* Validates the quick creation and directly opens the record in a form
|
||||
* view in edit mode.
|
||||
*
|
||||
* @private
|
||||
* @param {MouseEvent} ev
|
||||
*/
|
||||
_onEditClicked: function (ev) {
|
||||
ev.stopPropagation();
|
||||
this._add({openRecord: true});
|
||||
},
|
||||
/**
|
||||
* When a click happens outside the quick create, we want to close the quick
|
||||
* create.
|
||||
*
|
||||
* This is quite tricky, because in some cases a click is performed outside
|
||||
* the quick create, but is still related to it (e.g. click in a dialog
|
||||
* opened from the quick create).
|
||||
*
|
||||
* @param {MouseEvent} ev
|
||||
*/
|
||||
_onWindowClicked: function (ev) {
|
||||
// ignore clicks if the quick create is not in the dom
|
||||
if (!document.contains(this.el)) {
|
||||
return;
|
||||
}
|
||||
this._notifyAdd(value, options);
|
||||
|
||||
// ignore clicks on elements that open the quick create widget, to
|
||||
// prevent from closing quick create widget that has just been opened
|
||||
if ($(ev.target).closest('.o-kanban-button-new, .o_kanban_quick_add').length) {
|
||||
return;
|
||||
}
|
||||
|
||||
// ignore clicks in autocomplete dropdowns
|
||||
if ($(ev.target).parents('.ui-autocomplete').length) {
|
||||
return;
|
||||
}
|
||||
|
||||
// ignore clicks in modals
|
||||
if ($(ev.target).closest('.modal').length) {
|
||||
return;
|
||||
}
|
||||
|
||||
// ignore clicks if target is no longer in dom (e.g., a click on the
|
||||
// 'delete' trash icon of a m2m tag)
|
||||
if (!document.contains(ev.target)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// ignore clicks if target is inside the quick create
|
||||
if (this.el.contains(ev.target) && this.el !== ev.target) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.cancel();
|
||||
},
|
||||
});
|
||||
|
||||
var ColumnQuickCreate = Widget.extend({
|
||||
template: 'KanbanView.ColumnQuickCreate',
|
||||
events: {
|
||||
'click': 'toggleFold',
|
||||
'click input': '_onInputClicked',
|
||||
'click .o_kanban_add': '_onAddClicked',
|
||||
'focusout': '_onFocusout',
|
||||
'keydown': '_onKeydown',
|
||||
'keypress input': '_onKeypress',
|
||||
'mousedown .o_kanban_add': '_onMousedown',
|
||||
},
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
init: function () {
|
||||
this._super.apply(this, arguments);
|
||||
this.folded = true;
|
||||
},
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
start: function () {
|
||||
this.$header = this.$('.o_column_header');
|
||||
this.$quick_create = this.$('.o_kanban_quick_create');
|
||||
this.$input = this.$('input');
|
||||
return this._super.apply(this, arguments);
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Public
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Folds/unfolds the Column quick create widget
|
||||
*/
|
||||
toggleFold: function () {
|
||||
this.folded = !this.folded;
|
||||
this._update();
|
||||
if (!this.folded) {
|
||||
this.$input.focus();
|
||||
this.trigger_up('scrollTo', {selector: '.o_column_quick_create'});
|
||||
}
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Private
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Clears the input value and notify the environment to create a column
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_add: function () {
|
||||
var value = this.$input.val().trim();
|
||||
if (!value.length) {
|
||||
return;
|
||||
}
|
||||
this.$input.val('');
|
||||
this.trigger_up('quick_create_add_column', {value: value});
|
||||
this.$input.focus();
|
||||
},
|
||||
/**
|
||||
* Should implement what to do when the quick creation has been cancelled
|
||||
* Cancels the quick creation
|
||||
*
|
||||
* @abstract
|
||||
* @private
|
||||
*/
|
||||
_cancel: function () {
|
||||
this.folded = true;
|
||||
this.$input.val('');
|
||||
this._update();
|
||||
},
|
||||
/**
|
||||
* Should implement what to do to notify the environment that a quick
|
||||
* create has been done
|
||||
* Updates the rendering according to the current state (folded/unfolded)
|
||||
*
|
||||
* @abstract
|
||||
* @private
|
||||
*/
|
||||
_notifyAdd: function (name, options) {
|
||||
_update: function () {
|
||||
this.$header.toggle(this.folded);
|
||||
this.$quick_create.toggle(!this.folded);
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
@@ -70,21 +347,26 @@ var AbstractQuickCreate = Widget.extend({
|
||||
this._add();
|
||||
},
|
||||
/**
|
||||
* Cancels the quick creation when the input loses the focus
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_onCancelClicked: function () {
|
||||
_onFocusout: function () {
|
||||
var hasFocus = this.$(':focus').length > 0;
|
||||
if (hasFocus) {
|
||||
return;
|
||||
}
|
||||
this._cancel();
|
||||
},
|
||||
/**
|
||||
* Cancels quick creation on focusout input event
|
||||
* Stops the propagation of the event to prevent the quick create from
|
||||
* toggling when the user clicks in the input
|
||||
*
|
||||
* @private
|
||||
* @param {KeyEvent} ev
|
||||
* @param {MouseEvent} event
|
||||
*/
|
||||
_onFocusOut: function (ev) {
|
||||
if (!this.$input.val()) {
|
||||
this._cancel();
|
||||
}
|
||||
_onInputClicked: function (event) {
|
||||
event.stopPropagation();
|
||||
},
|
||||
/**
|
||||
* Cancels quick creation on escape keydown event
|
||||
@@ -111,11 +393,10 @@ var AbstractQuickCreate = Widget.extend({
|
||||
/**
|
||||
* In all browsers the 'focus/blur' event is triggered before a button's
|
||||
* 'click' (it's actually triggered by mousedown).
|
||||
* The quick create is destroyed on blur of its input but still needs
|
||||
* to create the data when the "Add" button is clicked.
|
||||
* The quick create is hidden on blur of its input but still needs to create
|
||||
* the data when the "Add" button is clicked.
|
||||
* This problem is adressed by suppressing the 'focus/blur' event from the
|
||||
* relevant buttons (Add and Cancel) entirely by preventing the browser's
|
||||
* default mousedown handler.
|
||||
* Add button entirely by preventing the browser's default mousedown handler.
|
||||
*
|
||||
* @private
|
||||
* @param {MouseEvent} event
|
||||
@@ -125,202 +406,6 @@ var AbstractQuickCreate = Widget.extend({
|
||||
},
|
||||
});
|
||||
|
||||
var RecordQuickCreate = AbstractQuickCreate.extend({
|
||||
template: "KanbanView.QuickCreate",
|
||||
events: _.extend({}, AbstractQuickCreate.prototype.events, {
|
||||
'click .o_kanban_edit': '_onEditClicked',
|
||||
'mousedown .o_kanban_edit': '_onMousedown',
|
||||
}),
|
||||
/**
|
||||
* @override
|
||||
* @param {Widget} parent
|
||||
* @param {Object} options
|
||||
* @param {string|number} options.width defines the element's width
|
||||
* @param {string} [options.defaultName] the record's default name
|
||||
*/
|
||||
init: function (parent, options) {
|
||||
this._super.apply(this, arguments);
|
||||
this.width = options.width;
|
||||
this.defaultName = options.defaultName;
|
||||
},
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
start: function () {
|
||||
this.$el.css({width: this.width});
|
||||
this.$input = this.$('input');
|
||||
this._addDefaultName();
|
||||
this.$input.focus();
|
||||
return this._super.apply(this, arguments);
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Private
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Set the default value for the record name.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_addDefaultName: function () {
|
||||
if (this.defaultName) {
|
||||
this.$input.val(this.defaultName);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Triggers up an event to cancel the quick creation
|
||||
*
|
||||
* @override
|
||||
* @private
|
||||
*/
|
||||
_cancel: function () {
|
||||
this.trigger_up('cancel_quick_create');
|
||||
},
|
||||
/**
|
||||
* Triggers up an event to quick create a record with the given value
|
||||
*
|
||||
* @override
|
||||
* @private
|
||||
* @param {string} value
|
||||
* @param {Object} [options]
|
||||
* @param {boolean} [options.openRecord] set to true to directly open the
|
||||
* newly created record in a form view (in edit mode)
|
||||
*/
|
||||
_notifyAdd: function (value, options) {
|
||||
this.trigger_up('quick_create_add_record', {
|
||||
value: value,
|
||||
openRecord: options && options.openRecord || false,
|
||||
});
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Handlers
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Add the default value for the record name again after creating
|
||||
* the previous record.
|
||||
*
|
||||
* @override
|
||||
* @private
|
||||
*/
|
||||
_onAddClicked: function () {
|
||||
this._super.apply(this, arguments);
|
||||
this._addDefaultName();
|
||||
},
|
||||
/**
|
||||
* Validates the quick creation and directly opens the record in a form
|
||||
* view in edit mode.
|
||||
*
|
||||
* @private
|
||||
* @param {MouseEvent} event
|
||||
*/
|
||||
_onEditClicked: function (event) {
|
||||
event.stopPropagation();
|
||||
this._add({openRecord: true});
|
||||
},
|
||||
});
|
||||
|
||||
var ColumnQuickCreate = AbstractQuickCreate.extend({
|
||||
template: 'KanbanView.ColumnQuickCreate',
|
||||
events: _.extend({}, AbstractQuickCreate.prototype.events, {
|
||||
'click': 'toggleFold',
|
||||
'click input': '_onInputClicked',
|
||||
'focusout': '_onFocusout',
|
||||
}),
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
init: function () {
|
||||
this._super.apply(this, arguments);
|
||||
this.folded = true;
|
||||
},
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
start: function () {
|
||||
this.$header = this.$('.o_column_header');
|
||||
this.$quick_create = this.$('.o_kanban_quick_create');
|
||||
this.$input = this.$('input');
|
||||
return this._super.apply(this, arguments);
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Public
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Toggle fold/unfold the Column quick create widget
|
||||
*/
|
||||
toggleFold: function () {
|
||||
this.folded = !this.folded;
|
||||
this._update();
|
||||
if (!this.folded) {
|
||||
this.$input.focus();
|
||||
this.trigger_up('scrollTo', {selector: '.o_column_quick_create'});
|
||||
}
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Private
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @override
|
||||
* @private
|
||||
*/
|
||||
_cancel: function () {
|
||||
this.folded = true;
|
||||
this.$input.val('');
|
||||
this._update();
|
||||
},
|
||||
/**
|
||||
* Triggers up an event to quick create a column with the given value
|
||||
*
|
||||
* @override
|
||||
* @private
|
||||
* @param {string} value
|
||||
*/
|
||||
_notifyAdd: function (value) {
|
||||
this.trigger_up('quick_create_add_column', {value: value});
|
||||
},
|
||||
/**
|
||||
* Updates the rendering according to the current state
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_update: function () {
|
||||
this.$header.toggle(this.folded);
|
||||
this.$quick_create.toggle(!this.folded);
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Handlers
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_onFocusout: function () {
|
||||
var hasFocus = this.$(':focus').length > 0;
|
||||
if (hasFocus) {
|
||||
return;
|
||||
}
|
||||
this._cancel();
|
||||
},
|
||||
/**
|
||||
* Stops the propagation of the event to prevent the quick create from
|
||||
* toggling when the user clicks in the input
|
||||
*
|
||||
* @private
|
||||
* @param {MouseEvent} event
|
||||
*/
|
||||
_onInputClicked: function (event) {
|
||||
event.stopPropagation();
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
RecordQuickCreate: RecordQuickCreate,
|
||||
ColumnQuickCreate: ColumnQuickCreate,
|
||||
|
||||
@@ -84,7 +84,8 @@ function transformQwebTemplate(node, fields) {
|
||||
var KanbanRenderer = BasicRenderer.extend({
|
||||
className: 'o_kanban_view',
|
||||
custom_events: _.extend({}, BasicRenderer.prototype.custom_events || {}, {
|
||||
'set_progress_bar_state': '_onSetProgressBarState',
|
||||
close_quick_create: '_onCloseQuickCreate',
|
||||
set_progress_bar_state: '_onSetProgressBarState',
|
||||
}),
|
||||
|
||||
/**
|
||||
@@ -117,9 +118,11 @@ var KanbanRenderer = BasicRenderer.extend({
|
||||
|
||||
/**
|
||||
* Displays the quick create record in the first column.
|
||||
*
|
||||
* @returns {Deferred}
|
||||
*/
|
||||
addQuickCreate: function () {
|
||||
this.widgets[0].addQuickCreate();
|
||||
return this.widgets[0].addQuickCreate();
|
||||
},
|
||||
/**
|
||||
* Toggle fold/unfold the Column quick create widget
|
||||
@@ -152,11 +155,21 @@ var KanbanRenderer = BasicRenderer.extend({
|
||||
var index = _.findIndex(this.widgets, {db_id: localID});
|
||||
var column = this.widgets[index];
|
||||
this.widgets[index] = newColumn;
|
||||
return newColumn.insertAfter(column.$el).then(function () {
|
||||
return newColumn.appendTo(document.createDocumentFragment()).then(function () {
|
||||
var def;
|
||||
if (options && options.openQuickCreate) {
|
||||
newColumn.addQuickCreate();
|
||||
def = newColumn.addQuickCreate();
|
||||
}
|
||||
column.destroy();
|
||||
return $.when(def).then(function () {
|
||||
newColumn.$el.insertAfter(column.$el);
|
||||
// When a record has been quick created, the new column directly
|
||||
// renders the quick create widget (to allow quick creating several
|
||||
// records in a row). However, as we render this column in a
|
||||
// fragment, the quick create widget can't be correctly focused. So
|
||||
// we manually call on_attach_callback to focus it once in the DOM.
|
||||
newColumn.on_attach_callback();
|
||||
column.destroy();
|
||||
});
|
||||
});
|
||||
},
|
||||
/**
|
||||
@@ -334,8 +347,9 @@ var KanbanRenderer = BasicRenderer.extend({
|
||||
_setState: function (state) {
|
||||
this.state = state;
|
||||
|
||||
var groupByFieldAttrs = state.fields[state.groupedBy[0]];
|
||||
var groupByFieldInfo = state.fieldsInfo.kanban[state.groupedBy[0]];
|
||||
var groupByField = state.groupedBy[0];
|
||||
var groupByFieldAttrs = state.fields[groupByField];
|
||||
var groupByFieldInfo = state.fieldsInfo.kanban[groupByField];
|
||||
// Deactivate the drag'n'drop if the groupedBy field:
|
||||
// - is a date or datetime since we group by month or
|
||||
// - is readonly (on the field attrs or in the view)
|
||||
@@ -353,13 +367,14 @@ var KanbanRenderer = BasicRenderer.extend({
|
||||
}
|
||||
}
|
||||
this.groupedByM2O = groupByFieldAttrs && (groupByFieldAttrs.type === 'many2one');
|
||||
var grouped_by_field = this.groupedByM2O && groupByFieldAttrs.relation;
|
||||
var relation = this.groupedByM2O && groupByFieldAttrs.relation;
|
||||
var groupByTooltip = groupByFieldInfo && groupByFieldInfo.options.group_by_tooltip;
|
||||
this.columnOptions = _.extend(this.columnOptions, {
|
||||
draggable: draggable,
|
||||
group_by_tooltip: groupByTooltip,
|
||||
groupedBy: groupByField,
|
||||
grouped_by_m2o: this.groupedByM2O,
|
||||
relation: grouped_by_field,
|
||||
relation: relation,
|
||||
});
|
||||
this.createColumnEnabled = this.groupedByM2O && this.columnOptions.group_creatable;
|
||||
},
|
||||
@@ -368,6 +383,16 @@ var KanbanRenderer = BasicRenderer.extend({
|
||||
// Handlers
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Closes the opened quick create widgets in columns
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_onCloseQuickCreate: function () {
|
||||
if (this.state.groupedBy.length) {
|
||||
_.invoke(this.widgets, 'cancelQuickCreate');
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Updates progressbar internal states (necessary for animations) with
|
||||
* received data.
|
||||
|
||||
@@ -38,9 +38,11 @@ KanbanRenderer.include({
|
||||
|
||||
/**
|
||||
* Displays the quick create record in the active column
|
||||
*
|
||||
* @returns {Deferred}
|
||||
*/
|
||||
addQuickCreate: function () {
|
||||
this.widgets[this.activeColumnIndex].addQuickCreate();
|
||||
return this.widgets[this.activeColumnIndex].addQuickCreate();
|
||||
},
|
||||
/**
|
||||
* Overrides to restore the left property and the scrollTop on the updated
|
||||
|
||||
@@ -62,6 +62,7 @@ var KanbanView = BasicView.extend({
|
||||
deletable: activeActions.group_delete,
|
||||
group_creatable: activeActions.group_create && !config.device.isMobile,
|
||||
quick_create: params.isQuickCreateEnabled || this._isQuickCreateEnabled(),
|
||||
quickCreateView: this.arch.attrs.quick_create_view || null,
|
||||
hasProgressBar: !!progressBar,
|
||||
};
|
||||
this.rendererParams.record_options = {
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
odoo.define('web.QuickCreateFormView', function (require) {
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* This file defines the QuickCreateFormView, an extension of the FormView that
|
||||
* is used by the RecordQuickCreate in Kanban views.
|
||||
*/
|
||||
|
||||
var FormController = require('web.FormController');
|
||||
var BasicModel = require('web.BasicModel');
|
||||
var FormRenderer = require('web.FormRenderer');
|
||||
var FormView = require('web.FormView');
|
||||
|
||||
var QuickCreateFormRenderer = FormRenderer.extend({
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
start: function () {
|
||||
this.$el.addClass('o_xxs_form_view');
|
||||
return this._super.apply(this, arguments);
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Handlers
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @override
|
||||
* @private
|
||||
* @param {OdooEvent} ev
|
||||
*/
|
||||
_onNavigationMove: function (ev) {
|
||||
var direction = ev.data.direction;
|
||||
if (direction === 'cancel' || direction === 'next_line') {
|
||||
ev.stopPropagation();
|
||||
this.trigger_up(direction === 'cancel' ? 'cancel' : 'add');
|
||||
} else {
|
||||
this._super.apply(this, arguments);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
var QuickCreateFormModel = BasicModel.extend({
|
||||
//--------------------------------------------------------------------------
|
||||
// Public
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @returns {Object} the changes of the given resource (server commands for
|
||||
* x2manys)
|
||||
*/
|
||||
getChanges: function (localID) {
|
||||
var record = this.localData[localID];
|
||||
return this._generateChanges(record, {changesOnly: false});
|
||||
},
|
||||
});
|
||||
|
||||
var QuickCreateFormController = FormController.extend({
|
||||
custom_events: _.extend({}, FormController.prototype.custom_events, {
|
||||
env_updated: '_onEnvUpdated',
|
||||
}),
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Public
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Asks all field widgets to notify the environment with their current value
|
||||
* (useful for instance for input fields that still have the focus and that
|
||||
* could have not notified the environment of their changes yet).
|
||||
*
|
||||
* @return {Deferred}
|
||||
*/
|
||||
commitChanges: function () {
|
||||
return this.mutex
|
||||
.exec(this.renderer.commitChanges.bind(this.renderer, this.handle));
|
||||
},
|
||||
/**
|
||||
* @returns {Object} the changes done on the current record
|
||||
*/
|
||||
getChanges: function () {
|
||||
return this.model.getChanges(this.handle);
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Handlers
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Stops the propagation of the 'env_updated' event to prevent interferences
|
||||
* with the kanban controller.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_onEnvUpdated: function (ev) {
|
||||
ev.stopPropagation();
|
||||
},
|
||||
});
|
||||
|
||||
var QuickCreateFormView = FormView.extend({
|
||||
config: _.extend({}, FormView.prototype.config, {
|
||||
Model: QuickCreateFormModel,
|
||||
Renderer: QuickCreateFormRenderer,
|
||||
Controller: QuickCreateFormController,
|
||||
}),
|
||||
});
|
||||
|
||||
return QuickCreateFormView;
|
||||
|
||||
});
|
||||
@@ -649,6 +649,57 @@ label.o_light_label, .o_light_label label {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
// XXS form view specific rules
|
||||
.form-break-table() {
|
||||
display: block;
|
||||
margin-bottom: @odoo-form-spacing-unit * 4;
|
||||
|
||||
> tbody {
|
||||
display: block;
|
||||
|
||||
> tr {
|
||||
.o-flex-display();
|
||||
.o-flex-flow(row, wrap);
|
||||
|
||||
> td {
|
||||
.o-flex(1, 0, auto);
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
padding: 0;
|
||||
|
||||
width: auto!important; // !important is required to override the width computed in JS
|
||||
&.o_td_label {
|
||||
width: 94%!important; // The label must be on its own line except if the form field is small enough (checkbox)
|
||||
line-height: @odoo-label-font-size-factor;
|
||||
}
|
||||
|
||||
.o_field_widget {
|
||||
margin-bottom: @odoo-form-spacing-unit * 2;
|
||||
&.o_field_boolean {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.o_input_dropdown {
|
||||
width: auto;
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.o_form_view.o_xxs_form_view {
|
||||
.oe_title {
|
||||
word-break: break-all;
|
||||
}
|
||||
.o_group {
|
||||
&.o_inner_group {
|
||||
.form-break-table();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Settings form views
|
||||
.o_settings_container {
|
||||
.o-flex-display();
|
||||
.o-flex(0, 1, auto);
|
||||
|
||||
@@ -181,3 +181,10 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// XXS form view specific rules
|
||||
.o_form_view.o_xxs_form_view {
|
||||
.o_group .o_td_label {
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,12 +161,11 @@
|
||||
box-shadow: 0 0 20px -10px;
|
||||
margin: 0 @o-kanban-record-margin -1px @o-kanban-record-margin;
|
||||
|
||||
input {
|
||||
width: 100%;
|
||||
margin: 2px 0 8px;
|
||||
padding: 3px 6px;
|
||||
color: @headings-color;
|
||||
font-weight: 500;
|
||||
.o_form_view {
|
||||
padding: 0;
|
||||
.o_group.o_inner_group {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -54,9 +54,8 @@
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<t t-name="KanbanView.QuickCreate">
|
||||
<div class="o_kanban_quick_create">
|
||||
<input type="text" class="o_input" placeholder="Title"/>
|
||||
<t t-name="KanbanView.RecordQuickCreate.buttons">
|
||||
<div>
|
||||
<button class="btn btn-sm btn-primary o_kanban_add">Add</button>
|
||||
<button class="btn btn-sm btn-primary o_kanban_edit">Edit</button>
|
||||
<button class="btn btn-sm btn-default o_kanban_cancel ml8">Discard</button>
|
||||
|
||||
@@ -485,6 +485,12 @@ var MockServer = Class.extend({
|
||||
_.each(kwargs.views, function (view_descr) {
|
||||
var viewID = view_descr[0] || false;
|
||||
var viewType = view_descr[1];
|
||||
if (!viewID) {
|
||||
var contextKey = viewType + '_view_ref';
|
||||
if (contextKey in kwargs.context) {
|
||||
viewID = kwargs.context[contextKey];
|
||||
}
|
||||
}
|
||||
var key = [model, viewID, viewType].join(',');
|
||||
var arch = self.archs[key];
|
||||
if (!arch) {
|
||||
|
||||
@@ -329,7 +329,367 @@ QUnit.module('Views', {
|
||||
kanban.destroy();
|
||||
});
|
||||
|
||||
QUnit.test('quick create and change state in grouped mode', function (assert) {
|
||||
QUnit.test('quick create record without quick_create_view', function (assert) {
|
||||
assert.expect(16);
|
||||
|
||||
var kanban = createView({
|
||||
View: KanbanView,
|
||||
model: 'partner',
|
||||
data: this.data,
|
||||
arch: '<kanban on_create="quick_create">' +
|
||||
'<field name="bar"/>' +
|
||||
'<templates><t t-name="kanban-box">' +
|
||||
'<div><field name="foo"/></div>' +
|
||||
'</t></templates></kanban>',
|
||||
groupBy: ['bar'],
|
||||
mockRPC: function (route, args) {
|
||||
assert.step(args.method || route);
|
||||
if (args.method === 'name_create') {
|
||||
assert.strictEqual(args.args[0], 'new partner',
|
||||
"should send the correct value");
|
||||
}
|
||||
return this._super.apply(this, arguments);
|
||||
},
|
||||
});
|
||||
|
||||
assert.strictEqual(kanban.$('.o_kanban_group:first .o_kanban_record').length, 1,
|
||||
"first column should contain one record");
|
||||
|
||||
// click on 'Create' -> should open the quick create in the first column
|
||||
kanban.$buttons.find('.o-kanban-button-new').click();
|
||||
var $quickCreate = kanban.$('.o_kanban_group:first .o_kanban_quick_create');
|
||||
|
||||
assert.strictEqual($quickCreate.length, 1,
|
||||
"should have a quick create element in the first column");
|
||||
assert.strictEqual($quickCreate.find('.o_form_view.o_xxs_form_view').length, 1,
|
||||
"should have rendered an XXS form view");
|
||||
assert.strictEqual($quickCreate.find('input').length, 1,
|
||||
"should have only one input");
|
||||
assert.ok($quickCreate.find('input').hasClass('o_required_modifier'),
|
||||
"the field should be required");
|
||||
assert.strictEqual($quickCreate.find('input[placeholder=Title]').length, 1,
|
||||
"input placeholder should be 'Title'");
|
||||
|
||||
// fill the quick create and validate
|
||||
$quickCreate.find('input').val('new partner').trigger('input');
|
||||
$quickCreate.find('button.o_kanban_add').click();
|
||||
|
||||
assert.strictEqual(kanban.$('.o_kanban_group:first .o_kanban_record').length, 2,
|
||||
"first column should contain two records");
|
||||
|
||||
assert.verifySteps([
|
||||
'read_group', // initial read_group
|
||||
'/web/dataset/search_read', // initial search_read (first column)
|
||||
'/web/dataset/search_read', // initial search_read (second column)
|
||||
'default_get', // quick create
|
||||
'name_create', // should perform a name_create to create the record
|
||||
'read', // read the created record
|
||||
'default_get', // reopen the quick create automatically
|
||||
]);
|
||||
|
||||
kanban.destroy();
|
||||
});
|
||||
|
||||
QUnit.test('quick create record with quick_create_view', function (assert) {
|
||||
assert.expect(17);
|
||||
|
||||
var kanban = createView({
|
||||
View: KanbanView,
|
||||
model: 'partner',
|
||||
data: this.data,
|
||||
arch: '<kanban on_create="quick_create" quick_create_view="some_view_ref">' +
|
||||
'<field name="bar"/>' +
|
||||
'<templates><t t-name="kanban-box">' +
|
||||
'<div><field name="foo"/></div>' +
|
||||
'</t></templates></kanban>',
|
||||
archs: {
|
||||
'partner,some_view_ref,form': '<form>' +
|
||||
'<field name="foo"/>' +
|
||||
'<field name="int_field"/>' +
|
||||
'<field name="state" widget="priority"/>' +
|
||||
'</form>',
|
||||
},
|
||||
groupBy: ['bar'],
|
||||
mockRPC: function (route, args) {
|
||||
assert.step(args.method || route);
|
||||
if (args.method === 'create') {
|
||||
assert.deepEqual(args.args[0], {
|
||||
foo: 'new partner',
|
||||
int_field: 4,
|
||||
state: 'def',
|
||||
}, "should send the correct values");
|
||||
}
|
||||
return this._super.apply(this, arguments);
|
||||
},
|
||||
});
|
||||
|
||||
assert.strictEqual(kanban.$('.o_kanban_group:first .o_kanban_record').length, 1,
|
||||
"first column should contain one record");
|
||||
|
||||
// click on 'Create' -> should open the quick create in the first column
|
||||
kanban.$buttons.find('.o-kanban-button-new').click();
|
||||
var $quickCreate = kanban.$('.o_kanban_group:first .o_kanban_quick_create');
|
||||
|
||||
assert.strictEqual($quickCreate.length, 1,
|
||||
"should have a quick create element in the first column");
|
||||
assert.strictEqual($quickCreate.find('.o_form_view.o_xxs_form_view').length, 1,
|
||||
"should have rendered an XXS form view");
|
||||
assert.strictEqual($quickCreate.find('input').length, 2,
|
||||
"should have two inputs");
|
||||
assert.strictEqual($quickCreate.find('.o_field_widget').length, 3,
|
||||
"should have rendered three widgets");
|
||||
|
||||
// fill the quick create and validate
|
||||
$quickCreate.find('.o_field_widget[name=foo]').val('new partner').trigger('input');
|
||||
$quickCreate.find('.o_field_widget[name=int_field]').val('4').trigger('input');
|
||||
$quickCreate.find('.o_field_widget[name=state] .o_priority_star:first').click();
|
||||
$quickCreate.find('button.o_kanban_add').click();
|
||||
|
||||
assert.strictEqual(kanban.$('.o_kanban_group:first .o_kanban_record').length, 2,
|
||||
"first column should contain two records");
|
||||
|
||||
assert.verifySteps([
|
||||
'read_group', // initial read_group
|
||||
'/web/dataset/search_read', // initial search_read (first column)
|
||||
'/web/dataset/search_read', // initial search_read (second column)
|
||||
'load_views', // form view in quick create
|
||||
'default_get', // quick create
|
||||
'create', // should perform a create to create the record
|
||||
'read', // read the created record
|
||||
'load_views', // form view in quick create (is actually in cache)
|
||||
'default_get', // reopen the quick create automatically
|
||||
]);
|
||||
|
||||
kanban.destroy();
|
||||
});
|
||||
|
||||
QUnit.test('quick create record in grouped on m2o (no quick_create_view)', function (assert) {
|
||||
assert.expect(12);
|
||||
|
||||
var kanban = createView({
|
||||
View: KanbanView,
|
||||
model: 'partner',
|
||||
data: this.data,
|
||||
arch: '<kanban on_create="quick_create">' +
|
||||
'<field name="product_id"/>' +
|
||||
'<templates><t t-name="kanban-box">' +
|
||||
'<div><field name="foo"/></div>' +
|
||||
'</t></templates>' +
|
||||
'</kanban>',
|
||||
groupBy: ['product_id'],
|
||||
mockRPC: function (route, args) {
|
||||
assert.step(args.method || route);
|
||||
if (args.method === 'name_create') {
|
||||
assert.strictEqual(args.args[0], 'new partner',
|
||||
"should send the correct value");
|
||||
assert.deepEqual(args.kwargs.context, {
|
||||
default_product_id: 3,
|
||||
default_qux: 2.5,
|
||||
}, "should send the correct context");
|
||||
}
|
||||
return this._super.apply(this, arguments);
|
||||
},
|
||||
viewOptions: {
|
||||
context: {default_qux: 2.5},
|
||||
},
|
||||
});
|
||||
|
||||
assert.strictEqual(kanban.$('.o_kanban_group:first .o_kanban_record').length, 2,
|
||||
"first column should contain two records");
|
||||
|
||||
// click on 'Create', fill the quick create and validate
|
||||
kanban.$buttons.find('.o-kanban-button-new').click();
|
||||
var $quickCreate = kanban.$('.o_kanban_group:first .o_kanban_quick_create');
|
||||
$quickCreate.find('input').val('new partner').trigger('input');
|
||||
$quickCreate.find('button.o_kanban_add').click();
|
||||
|
||||
assert.strictEqual(kanban.$('.o_kanban_group:first .o_kanban_record').length, 3,
|
||||
"first column should contain three records");
|
||||
|
||||
assert.verifySteps([
|
||||
'read_group', // initial read_group
|
||||
'/web/dataset/search_read', // initial search_read (first column)
|
||||
'/web/dataset/search_read', // initial search_read (second column)
|
||||
'default_get', // quick create
|
||||
'name_create', // should perform a name_create to create the record
|
||||
'read', // read the created record
|
||||
'default_get', // reopen the quick create automatically
|
||||
]);
|
||||
|
||||
kanban.destroy();
|
||||
});
|
||||
|
||||
QUnit.test('quick create record in grouped on m2o (with quick_create_view)', function (assert) {
|
||||
assert.expect(14);
|
||||
|
||||
var kanban = createView({
|
||||
View: KanbanView,
|
||||
model: 'partner',
|
||||
data: this.data,
|
||||
arch: '<kanban on_create="quick_create" quick_create_view="some_view_ref">' +
|
||||
'<field name="product_id"/>' +
|
||||
'<templates><t t-name="kanban-box">' +
|
||||
'<div><field name="foo"/></div>' +
|
||||
'</t></templates></kanban>',
|
||||
archs: {
|
||||
'partner,some_view_ref,form': '<form>' +
|
||||
'<field name="foo"/>' +
|
||||
'<field name="int_field"/>' +
|
||||
'<field name="state" widget="priority"/>' +
|
||||
'</form>',
|
||||
},
|
||||
groupBy: ['product_id'],
|
||||
mockRPC: function (route, args) {
|
||||
assert.step(args.method || route);
|
||||
if (args.method === 'create') {
|
||||
assert.deepEqual(args.args[0], {
|
||||
foo: 'new partner',
|
||||
int_field: 4,
|
||||
state: 'def',
|
||||
}, "should send the correct values");
|
||||
assert.deepEqual(args.kwargs.context, {
|
||||
default_product_id: 3,
|
||||
default_qux: 2.5,
|
||||
}, "should send the correct context");
|
||||
}
|
||||
return this._super.apply(this, arguments);
|
||||
},
|
||||
viewOptions: {
|
||||
context: {default_qux: 2.5},
|
||||
},
|
||||
});
|
||||
|
||||
assert.strictEqual(kanban.$('.o_kanban_group:first .o_kanban_record').length, 2,
|
||||
"first column should contain two records");
|
||||
|
||||
// click on 'Create', fill the quick create and validate
|
||||
kanban.$buttons.find('.o-kanban-button-new').click();
|
||||
var $quickCreate = kanban.$('.o_kanban_group:first .o_kanban_quick_create');
|
||||
$quickCreate.find('.o_field_widget[name=foo]').val('new partner').trigger('input');
|
||||
$quickCreate.find('.o_field_widget[name=int_field]').val('4').trigger('input');
|
||||
$quickCreate.find('.o_field_widget[name=state] .o_priority_star:first').click();
|
||||
$quickCreate.find('button.o_kanban_add').click();
|
||||
|
||||
assert.strictEqual(kanban.$('.o_kanban_group:first .o_kanban_record').length, 3,
|
||||
"first column should contain three records");
|
||||
|
||||
assert.verifySteps([
|
||||
'read_group', // initial read_group
|
||||
'/web/dataset/search_read', // initial search_read (first column)
|
||||
'/web/dataset/search_read', // initial search_read (second column)
|
||||
'load_views', // form view in quick create
|
||||
'default_get', // quick create
|
||||
'create', // should perform a create to create the record
|
||||
'read', // read the created record
|
||||
'load_views', // form view in quick create (is actually in cache)
|
||||
'default_get', // reopen the quick create automatically
|
||||
]);
|
||||
|
||||
kanban.destroy();
|
||||
});
|
||||
|
||||
QUnit.test('quick create record with default values and onchanges', function (assert) {
|
||||
assert.expect(11);
|
||||
|
||||
this.data.partner.fields.int_field.default = 4;
|
||||
this.data.partner.onchanges = {
|
||||
foo: function (obj) {
|
||||
if (obj.foo) {
|
||||
obj.int_field = 8;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
var kanban = createView({
|
||||
View: KanbanView,
|
||||
model: 'partner',
|
||||
data: this.data,
|
||||
arch: '<kanban on_create="quick_create" quick_create_view="some_view_ref">' +
|
||||
'<field name="bar"/>' +
|
||||
'<templates><t t-name="kanban-box">' +
|
||||
'<div><field name="foo"/></div>' +
|
||||
'</t></templates></kanban>',
|
||||
archs: {
|
||||
'partner,some_view_ref,form': '<form>' +
|
||||
'<field name="foo"/>' +
|
||||
'<field name="int_field"/>' +
|
||||
'</form>',
|
||||
},
|
||||
groupBy: ['bar'],
|
||||
mockRPC: function (route, args) {
|
||||
assert.step(args.method || route);
|
||||
return this._super.apply(this, arguments);
|
||||
},
|
||||
});
|
||||
|
||||
// click on 'Create' -> should open the quick create in the first column
|
||||
kanban.$buttons.find('.o-kanban-button-new').click();
|
||||
var $quickCreate = kanban.$('.o_kanban_group:first .o_kanban_quick_create');
|
||||
|
||||
assert.strictEqual($quickCreate.length, 1,
|
||||
"should have a quick create element in the first column");
|
||||
assert.strictEqual($quickCreate.find('.o_field_widget[name=int_field]').val(), '4',
|
||||
"default value should be set");
|
||||
|
||||
// fill the 'foo' field -> should trigger the onchange
|
||||
$quickCreate.find('.o_field_widget[name=foo]').val('new partner').trigger('input');
|
||||
|
||||
assert.strictEqual($quickCreate.find('.o_field_widget[name=int_field]').val(), '8',
|
||||
"onchange should have been triggered");
|
||||
|
||||
assert.verifySteps([
|
||||
'read_group', // initial read_group
|
||||
'/web/dataset/search_read', // initial search_read (first column)
|
||||
'/web/dataset/search_read', // initial search_read (second column)
|
||||
'load_views', // form view in quick create
|
||||
'default_get', // quick create
|
||||
'onchange', // default_get's onchange
|
||||
'onchange', // onchange due to 'foo' field change
|
||||
]);
|
||||
|
||||
kanban.destroy();
|
||||
});
|
||||
|
||||
QUnit.test('quick create record with quick_create_view: modifiers', function (assert) {
|
||||
assert.expect(3);
|
||||
|
||||
var kanban = createView({
|
||||
View: KanbanView,
|
||||
model: 'partner',
|
||||
data: this.data,
|
||||
arch: '<kanban quick_create_view="some_view_ref">' +
|
||||
'<field name="bar"/>' +
|
||||
'<templates><t t-name="kanban-box">' +
|
||||
'<div><field name="foo"/></div>' +
|
||||
'</t></templates></kanban>',
|
||||
archs: {
|
||||
'partner,some_view_ref,form': '<form>' +
|
||||
'<field name="foo" required="1"/>' +
|
||||
'<field name="int_field" attrs=\'{"invisible": [["foo", "=", false]]}\'/>' +
|
||||
'</form>',
|
||||
},
|
||||
groupBy: ['bar'],
|
||||
});
|
||||
|
||||
// create a new record
|
||||
kanban.$('.o_kanban_group:first .o_kanban_quick_add').click();
|
||||
var $quickCreate = kanban.$('.o_kanban_group:first .o_kanban_quick_create');
|
||||
|
||||
assert.ok($quickCreate.find('.o_field_widget[name=foo]').hasClass('o_required_modifier'),
|
||||
"foo field should be required");
|
||||
assert.ok($quickCreate.find('.o_field_widget[name=int_field]').hasClass('o_invisible_modifier'),
|
||||
"int_field should be invisible");
|
||||
|
||||
// fill 'foo' field
|
||||
$quickCreate.find('.o_field_widget[name=foo]').val('new partner').trigger('input');
|
||||
|
||||
assert.notOk($quickCreate.find('.o_field_widget[name=int_field]').hasClass('o_invisible_modifier'),
|
||||
"int_field should now be visible");
|
||||
|
||||
kanban.destroy();
|
||||
});
|
||||
|
||||
QUnit.test('quick create record and change state in grouped mode', function (assert) {
|
||||
assert.expect(1);
|
||||
|
||||
this.data.partner.fields.kanban_state = {
|
||||
@@ -367,7 +727,7 @@ QUnit.module('Views', {
|
||||
kanban.destroy();
|
||||
});
|
||||
|
||||
QUnit.test('quick create in grouped mode', function (assert) {
|
||||
QUnit.test('quick create record: cancel and validate without using the buttons', function (assert) {
|
||||
assert.expect(8);
|
||||
|
||||
var nbRecords = 4;
|
||||
@@ -375,7 +735,7 @@ QUnit.module('Views', {
|
||||
View: KanbanView,
|
||||
model: 'partner',
|
||||
data: this.data,
|
||||
arch: '<kanban class="o_kanban_test" on_create="quick_create">' +
|
||||
arch: '<kanban on_create="quick_create">' +
|
||||
'<field name="bar"/>' +
|
||||
'<templates><t t-name="kanban-box">' +
|
||||
'<div><field name="foo"/></div>' +
|
||||
@@ -389,34 +749,41 @@ QUnit.module('Views', {
|
||||
}
|
||||
});
|
||||
|
||||
// click to add an element and cancel the quick creation
|
||||
// click to add an element and cancel the quick creation by pressing ESC
|
||||
kanban.$('.o_kanban_header .o_kanban_quick_add i').first().click();
|
||||
|
||||
var $quickCreate = kanban.$('.o_kanban_quick_create');
|
||||
assert.strictEqual($quickCreate.length, 1, "should have a quick create element");
|
||||
|
||||
$quickCreate.find('input').trigger($.Event('keydown', {keyCode: $.ui.keyCode.ESCAPE}));
|
||||
$quickCreate.find('input').trigger($.Event('keydown', {
|
||||
keyCode: $.ui.keyCode.ESCAPE,
|
||||
which: $.ui.keyCode.ESCAPE,
|
||||
}));
|
||||
assert.strictEqual(kanban.$('.o_kanban_quick_create').length, 0,
|
||||
"should have destroyed the quick create element");
|
||||
|
||||
//click to add and element and focus out the blank input, should cancel the quick creation
|
||||
// click to add and element and click outside, should cancel the quick creation
|
||||
kanban.$('.o_kanban_header .o_kanban_quick_add i').first().click();
|
||||
$quickCreate = kanban.$('.o_kanban_quick_create');
|
||||
$quickCreate.find('input').blur();
|
||||
kanban.$('.o_kanban_group .o_kanban_record:first').click();
|
||||
assert.strictEqual(kanban.$('.o_kanban_quick_create').length, 0,
|
||||
"Blur should have destroyed the quick create element");
|
||||
"the quick create should be destroyed when the user clicks outside");
|
||||
|
||||
// click to really add an element
|
||||
kanban.$('.o_kanban_header .o_kanban_quick_add i').first().click();
|
||||
$quickCreate = kanban.$('.o_kanban_quick_create');
|
||||
$quickCreate.find('input').val('new partner');
|
||||
$quickCreate.find('input').blur();
|
||||
$quickCreate.find('input').val('new partner').trigger('input');
|
||||
|
||||
// When focus out the input containing value, should not delete the Quick Creation
|
||||
// clicking outside should no longer destroy the quick create as it is dirty
|
||||
kanban.$('.o_kanban_group .o_kanban_record:first').click();
|
||||
assert.strictEqual(kanban.$('.o_kanban_quick_create').length, 1,
|
||||
"Blur should not have destroyed the quick create element");
|
||||
"the quick create should not have been destroyed");
|
||||
|
||||
// confirm by pressing ENTER
|
||||
nbRecords = 5;
|
||||
$quickCreate.find('button.o_kanban_add').click();
|
||||
$quickCreate.find('input').trigger($.Event('keydown', {
|
||||
keyCode: $.ui.keyCode.ENTER,
|
||||
which: $.ui.keyCode.ENTER,
|
||||
}));
|
||||
|
||||
assert.strictEqual(this.data.partner.records.length, 5,
|
||||
"should have created a partner");
|
||||
@@ -470,7 +837,128 @@ QUnit.module('Views', {
|
||||
kanban.destroy();
|
||||
});
|
||||
|
||||
QUnit.test('quick create and edit in grouped mode', function (assert) {
|
||||
QUnit.test('quick create record: cancel when not dirty', function (assert) {
|
||||
assert.expect(9);
|
||||
|
||||
var kanban = createView({
|
||||
View: KanbanView,
|
||||
model: 'partner',
|
||||
data: this.data,
|
||||
arch: '<kanban>' +
|
||||
'<field name="bar"/>' +
|
||||
'<templates><t t-name="kanban-box">' +
|
||||
'<div><field name="foo"/></div>' +
|
||||
'</t></templates></kanban>',
|
||||
groupBy: ['bar'],
|
||||
});
|
||||
|
||||
assert.strictEqual(kanban.$('.o_kanban_group:first .o_kanban_record').length, 1,
|
||||
"first column should contain one record");
|
||||
|
||||
// click to add an element
|
||||
kanban.$('.o_kanban_header .o_kanban_quick_add i').first().click();
|
||||
assert.strictEqual(kanban.$('.o_kanban_quick_create').length, 1,
|
||||
"should have open the quick create widget");
|
||||
|
||||
// click again to add an element -> should have kept the quick create open
|
||||
kanban.$('.o_kanban_header .o_kanban_quick_add i').first().click();
|
||||
assert.strictEqual(kanban.$('.o_kanban_quick_create').length, 1,
|
||||
"should have kept the quick create open");
|
||||
|
||||
// click outside: should remove the quick create
|
||||
kanban.$('.o_kanban_group .o_kanban_record:first').click();
|
||||
assert.strictEqual(kanban.$('.o_kanban_quick_create').length, 0,
|
||||
"the quick create should not have been destroyed");
|
||||
|
||||
// click to reopen the quick create
|
||||
kanban.$('.o_kanban_header .o_kanban_quick_add i').first().click();
|
||||
assert.strictEqual(kanban.$('.o_kanban_quick_create').length, 1,
|
||||
"should have open the quick create widget");
|
||||
|
||||
// press ESC: should remove the quick create
|
||||
kanban.$('.o_kanban_quick_create input').trigger($.Event('keydown', {
|
||||
keyCode: $.ui.keyCode.ESCAPE,
|
||||
which: $.ui.keyCode.ESCAPE,
|
||||
}));
|
||||
assert.strictEqual(kanban.$('.o_kanban_quick_create').length, 0,
|
||||
"quick create widget should have been removed");
|
||||
|
||||
// click to reopen the quick create
|
||||
kanban.$('.o_kanban_header .o_kanban_quick_add i').first().click();
|
||||
assert.strictEqual(kanban.$('.o_kanban_quick_create').length, 1,
|
||||
"should have open the quick create widget");
|
||||
|
||||
// click on 'Discard': should remove the quick create
|
||||
kanban.$('.o_kanban_header .o_kanban_quick_add i').first().click();
|
||||
kanban.$('.o_kanban_group .o_kanban_record:first').click();
|
||||
assert.strictEqual(kanban.$('.o_kanban_quick_create').length, 0,
|
||||
"the quick create should be destroyed when the user clicks outside");
|
||||
|
||||
assert.strictEqual(kanban.$('.o_kanban_group:first .o_kanban_record').length, 1,
|
||||
"first column should still contain one record");
|
||||
|
||||
kanban.destroy();
|
||||
});
|
||||
|
||||
QUnit.test('quick create record: cancel when dirty', function (assert) {
|
||||
assert.expect(7);
|
||||
|
||||
var kanban = createView({
|
||||
View: KanbanView,
|
||||
model: 'partner',
|
||||
data: this.data,
|
||||
arch: '<kanban>' +
|
||||
'<field name="bar"/>' +
|
||||
'<templates><t t-name="kanban-box">' +
|
||||
'<div><field name="foo"/></div>' +
|
||||
'</t></templates></kanban>',
|
||||
groupBy: ['bar'],
|
||||
});
|
||||
|
||||
assert.strictEqual(kanban.$('.o_kanban_group:first .o_kanban_record').length, 1,
|
||||
"first column should contain one record");
|
||||
|
||||
// click to add an element and edit it
|
||||
kanban.$('.o_kanban_header .o_kanban_quick_add i').first().click();
|
||||
assert.strictEqual(kanban.$('.o_kanban_quick_create').length, 1,
|
||||
"should have open the quick create widget");
|
||||
|
||||
var $quickCreate = kanban.$('.o_kanban_quick_create');
|
||||
$quickCreate.find('input').val('some value').trigger('input');
|
||||
|
||||
// click outside: should not remove the quick create
|
||||
kanban.$('.o_kanban_group .o_kanban_record:first').click();
|
||||
assert.strictEqual(kanban.$('.o_kanban_quick_create').length, 1,
|
||||
"the quick create should not have been destroyed");
|
||||
|
||||
// press ESC: should remove the quick create
|
||||
$quickCreate.find('input').trigger($.Event('keydown', {
|
||||
keyCode: $.ui.keyCode.ESCAPE,
|
||||
which: $.ui.keyCode.ESCAPE,
|
||||
}));
|
||||
assert.strictEqual(kanban.$('.o_kanban_quick_create').length, 0,
|
||||
"quick create widget should have been removed");
|
||||
|
||||
// click to reopen quick create and edit it
|
||||
kanban.$('.o_kanban_header .o_kanban_quick_add i').first().click();
|
||||
assert.strictEqual(kanban.$('.o_kanban_quick_create').length, 1,
|
||||
"should have open the quick create widget");
|
||||
|
||||
$quickCreate = kanban.$('.o_kanban_quick_create');
|
||||
$quickCreate.find('input').val('some value').trigger('input');
|
||||
|
||||
// click on 'Discard': should remove the quick create
|
||||
kanban.$('.o_kanban_quick_create .o_kanban_cancel').click();
|
||||
assert.strictEqual(kanban.$('.o_kanban_quick_create').length, 0,
|
||||
"the quick create should be destroyed when the user clicks outside");
|
||||
|
||||
assert.strictEqual(kanban.$('.o_kanban_group:first .o_kanban_record').length, 1,
|
||||
"first column should still contain one record");
|
||||
|
||||
kanban.destroy();
|
||||
});
|
||||
|
||||
QUnit.test('quick create record and edit in grouped mode', function (assert) {
|
||||
assert.expect(6);
|
||||
|
||||
var newRecordID;
|
||||
@@ -510,7 +998,7 @@ QUnit.module('Views', {
|
||||
var $quickCreate = kanban.$('.o_kanban_quick_create');
|
||||
kanban.$('.o_kanban_header .o_kanban_quick_add i').first().click();
|
||||
$quickCreate = kanban.$('.o_kanban_quick_create');
|
||||
$quickCreate.find('input').val('new partner');
|
||||
$quickCreate.find('input').val('new partner').trigger('input');
|
||||
$quickCreate.find('button.o_kanban_edit').click();
|
||||
|
||||
assert.strictEqual(this.data.partner.records.length, 5,
|
||||
@@ -549,7 +1037,8 @@ QUnit.module('Views', {
|
||||
|
||||
kanban.$('.o_kanban_quick_create input')
|
||||
.val('new partner 1')
|
||||
.trigger($.Event('keypress', {
|
||||
.trigger('input')
|
||||
.trigger($.Event('keydown', {
|
||||
which: $.ui.keyCode.ENTER,
|
||||
keyCode: $.ui.keyCode.ENTER,
|
||||
}));
|
||||
@@ -562,7 +1051,8 @@ QUnit.module('Views', {
|
||||
// create a second element in a row
|
||||
kanban.$('.o_kanban_quick_create input')
|
||||
.val('new partner 2')
|
||||
.trigger($.Event('keypress', {
|
||||
.trigger('input')
|
||||
.trigger($.Event('keydown', {
|
||||
which: $.ui.keyCode.ENTER,
|
||||
keyCode: $.ui.keyCode.ENTER,
|
||||
}));
|
||||
@@ -621,7 +1111,8 @@ QUnit.module('Views', {
|
||||
def = $.Deferred();
|
||||
kanban.$('.o_kanban_quick_create input')
|
||||
.val('new partner 1')
|
||||
.trigger($.Event('keypress', {
|
||||
.trigger('input')
|
||||
.trigger($.Event('keydown', {
|
||||
which: $.ui.keyCode.ENTER,
|
||||
keyCode: $.ui.keyCode.ENTER,
|
||||
}));
|
||||
@@ -629,7 +1120,8 @@ QUnit.module('Views', {
|
||||
def = null;
|
||||
kanban.$('.o_kanban_quick_create input')
|
||||
.val('new partner 2')
|
||||
.trigger($.Event('keypress', {
|
||||
.trigger('input')
|
||||
.trigger($.Event('keydown', {
|
||||
which: $.ui.keyCode.ENTER,
|
||||
keyCode: $.ui.keyCode.ENTER,
|
||||
}));
|
||||
@@ -649,7 +1141,7 @@ QUnit.module('Views', {
|
||||
kanban.destroy();
|
||||
});
|
||||
|
||||
QUnit.test('quick create fail in grouped', function (assert) {
|
||||
QUnit.test('quick create record fail in grouped', function (assert) {
|
||||
assert.expect(7);
|
||||
|
||||
var kanban = createView({
|
||||
@@ -690,7 +1182,11 @@ QUnit.module('Views', {
|
||||
|
||||
kanban.$('.o_kanban_quick_create input')
|
||||
.val('test')
|
||||
.trigger($.Event('keypress', {keyCode: $.ui.keyCode.ENTER}));
|
||||
.trigger('input')
|
||||
.trigger($.Event('keydown', {
|
||||
keyCode: $.ui.keyCode.ENTER,
|
||||
which: $.ui.keyCode.ENTER,
|
||||
}));
|
||||
|
||||
assert.strictEqual($('.modal .o_form_view.o_form_editable').length, 1,
|
||||
"a form view dialog should have been opened (in edit)");
|
||||
@@ -1181,37 +1677,6 @@ QUnit.module('Views', {
|
||||
kanban.destroy();
|
||||
});
|
||||
|
||||
QUnit.test('quick create record & column in grouped on m2o', function (assert) {
|
||||
assert.expect(2);
|
||||
|
||||
var kanban = createView({
|
||||
View: KanbanView,
|
||||
model: 'partner',
|
||||
data: this.data,
|
||||
arch: '<kanban on_create="quick_create">' +
|
||||
'<field name="product_id"/>' +
|
||||
'<templates><t t-name="kanban-box">' +
|
||||
'<div><field name="foo"/></div>' +
|
||||
'</t></templates>' +
|
||||
'</kanban>',
|
||||
groupBy: ['product_id'],
|
||||
});
|
||||
kanban.$('.o_kanban_group:first .o_kanban_quick_add').click();
|
||||
var $quickCreate = kanban.$('.o_kanban_quick_create');
|
||||
$quickCreate.find('input').val('new partner');
|
||||
$quickCreate.find('button.o_kanban_add').click();
|
||||
assert.strictEqual(this.data.partner.records.length, 5,
|
||||
"should have created a partner");
|
||||
|
||||
kanban.$('.o_column_quick_create').click();
|
||||
kanban.$('.o_column_quick_create input').val('new column');
|
||||
kanban.$('.o_column_quick_create button.o_kanban_add').click();
|
||||
|
||||
assert.strictEqual(kanban.$('.o_kanban_group:last span:contains(new column)').length, 1,
|
||||
"the last column should be the newly created one");
|
||||
kanban.destroy();
|
||||
});
|
||||
|
||||
QUnit.test('delete a column in grouped on m2o', function (assert) {
|
||||
assert.expect(28);
|
||||
|
||||
@@ -2172,7 +2637,7 @@ QUnit.module('Views', {
|
||||
|
||||
kanban.$('.o_kanban_group:eq(1) .o_kanban_quick_add i').click();
|
||||
var $quickCreate = kanban.$('.o_kanban_group:eq(1) .o_kanban_quick_create');
|
||||
$quickCreate.find('input').val('new partner');
|
||||
$quickCreate.find('input').val('new partner').trigger('input');
|
||||
$quickCreate.find('button.o_kanban_add').click();
|
||||
|
||||
assert.strictEqual(kanban.$('.o_kanban_group:eq(0) .o_kanban_record').length, 0,
|
||||
@@ -2232,12 +2697,12 @@ QUnit.module('Views', {
|
||||
|
||||
kanban.$('.o_kanban_group:eq(0) .o_kanban_quick_add i').click();
|
||||
var $quickCreate = kanban.$('.o_kanban_group:eq(0) .o_kanban_quick_create');
|
||||
$quickCreate.find('input').val('record1');
|
||||
$quickCreate.find('input').val('record1').trigger('input');
|
||||
$quickCreate.find('button.o_kanban_add').click();
|
||||
|
||||
kanban.$('.o_kanban_group:eq(0) .o_kanban_quick_add i').click();
|
||||
$quickCreate = kanban.$('.o_kanban_group:eq(0) .o_kanban_quick_create');
|
||||
$quickCreate.find('input').val('record2');
|
||||
$quickCreate.find('input').val('record2').trigger('input');
|
||||
$quickCreate.find('button.o_kanban_add').click();
|
||||
|
||||
assert.strictEqual(kanban.$('.o_kanban_group:eq(0) .o_kanban_record').length, 2,
|
||||
@@ -2289,7 +2754,7 @@ QUnit.module('Views', {
|
||||
// add a new column
|
||||
kanban.$('.o_kanban_group:first .o_kanban_quick_add').click();
|
||||
var $quickCreate = kanban.$('.o_kanban_quick_create');
|
||||
$quickCreate.find('input').val('new partner');
|
||||
$quickCreate.find('input').val('new partner').trigger('input');
|
||||
$quickCreate.find('button.o_kanban_add').click();
|
||||
assert.strictEqual(this.data.partner.records.length, 5,
|
||||
"should have created a 'new partner' column");
|
||||
@@ -2414,11 +2879,11 @@ QUnit.module('Views', {
|
||||
groupBy: ['bar'],
|
||||
});
|
||||
|
||||
var initialCount = parseInt(kanban.$('.o_kanban_counter_side').eq(1).text());
|
||||
kanban.$('.o_kanban_quick_add').eq(1).click();
|
||||
kanban.$('.o_input').val('Test');
|
||||
var initialCount = parseInt(kanban.$('.o_kanban_counter_side:first').text());
|
||||
kanban.$('.o_kanban_quick_add:first').click();
|
||||
kanban.$('.o_kanban_quick_create input').val('Test').trigger('input');
|
||||
kanban.$('.o_kanban_add').click();
|
||||
var lastCount = parseInt(kanban.$('.o_kanban_counter_side').eq(1).text());
|
||||
var lastCount = parseInt(kanban.$('.o_kanban_counter_side:first').text());
|
||||
assert.strictEqual(lastCount, initialCount + 1,
|
||||
"kanban counters should have updated on quick create");
|
||||
|
||||
@@ -2455,6 +2920,45 @@ QUnit.module('Views', {
|
||||
kanban.destroy();
|
||||
});
|
||||
|
||||
QUnit.test('column progressbars on quick create with quick_create_view are updated', function (assert) {
|
||||
assert.expect(1);
|
||||
|
||||
var kanban = createView({
|
||||
View: KanbanView,
|
||||
model: 'partner',
|
||||
data: this.data,
|
||||
arch: '<kanban on_create="quick_create" quick_create_view="some_view_ref">' +
|
||||
'<field name="int_field"/>' +
|
||||
'<progressbar field="foo" colors=\'{"yop": "success", "gnap": "warning", "blip": "danger"}\' sum_field="int_field"/>' +
|
||||
'<templates><t t-name="kanban-box">' +
|
||||
'<div>' +
|
||||
'<field name="name"/>' +
|
||||
'</div>' +
|
||||
'</t></templates>' +
|
||||
'</kanban>',
|
||||
archs: {
|
||||
'partner,some_view_ref,form': '<form>' +
|
||||
'<field name="int_field"/>' +
|
||||
'</form>',
|
||||
},
|
||||
groupBy: ['bar'],
|
||||
});
|
||||
|
||||
var initialCount = parseInt(kanban.$('.o_kanban_counter_side:first').text());
|
||||
|
||||
// click on 'Create', fill the quick create and validate
|
||||
kanban.$buttons.find('.o-kanban-button-new').click();
|
||||
var $quickCreate = kanban.$('.o_kanban_group:first .o_kanban_quick_create');
|
||||
$quickCreate.find('.o_field_widget[name=int_field]').val('44').trigger('input');
|
||||
$quickCreate.find('button.o_kanban_add').click();
|
||||
|
||||
var lastCount = parseInt(kanban.$('.o_kanban_counter_side:first').text());
|
||||
assert.strictEqual(lastCount, initialCount + 44,
|
||||
"kanban counters should have been updated on quick create");
|
||||
|
||||
kanban.destroy();
|
||||
});
|
||||
|
||||
QUnit.test('keep adding quickcreate in first column after a record from this column was moved', function (assert) {
|
||||
assert.expect(2);
|
||||
|
||||
|
||||
@@ -221,6 +221,7 @@
|
||||
<script type="text/javascript" src="/web/static/src/js/views/kanban/kanban_renderer.js"></script>
|
||||
<script type="text/javascript" src="/web/static/src/js/views/kanban/kanban_renderer_mobile.js"></script>
|
||||
<script type="text/javascript" src="/web/static/src/js/views/kanban/kanban_view.js"></script>
|
||||
<script type="text/javascript" src="/web/static/src/js/views/kanban/quick_create_form_view.js"></script>
|
||||
<script type="text/javascript" src="/web/static/src/js/views/list/list_editable_renderer.js"></script>
|
||||
<script type="text/javascript" src="/web/static/src/js/views/list/list_renderer.js"></script>
|
||||
<script type="text/javascript" src="/web/static/src/js/views/list/list_view.js"></script>
|
||||
|
||||
Reference in New Issue
Block a user