diff --git a/addons/web/static/src/views/kanban/kanban_column_examples_dialog.js b/addons/web/static/src/views/kanban/kanban_column_examples_dialog.js
index cae9b37b6ff..b9e59b56162 100644
--- a/addons/web/static/src/views/kanban/kanban_column_examples_dialog.js
+++ b/addons/web/static/src/views/kanban/kanban_column_examples_dialog.js
@@ -9,10 +9,15 @@ import { Component, useRef } from "@odoo/owl";
const random = (min, max) => Math.floor(Math.random() * (max - min) + min);
class KanbanExamplesNotebookTemplate extends Component {
+ static defaultProps = {
+ columns: [],
+ foldedColumns: [],
+ };
setup() {
this.columns = [];
const hasBullet = this.props.bullets && this.props.bullets.length;
- for (const title of this.props.columns) {
+ const allColumns = [...this.props.columns, ...this.props.foldedColumns];
+ for (const title of allColumns) {
const col = { title, records: [] };
this.columns.push(col);
for (let i = 0; i < random(1, 5); i++) {
diff --git a/addons/web/static/src/views/kanban/kanban_column_quick_create.js b/addons/web/static/src/views/kanban/kanban_column_quick_create.js
index e32bbb7fcf7..b123e23d824 100644
--- a/addons/web/static/src/views/kanban/kanban_column_quick_create.js
+++ b/addons/web/static/src/views/kanban/kanban_column_quick_create.js
@@ -76,9 +76,14 @@ export class KanbanColumnQuickCreate extends Component {
applyExamplesText:
this.props.exampleData.applyExamplesText || this.env._t("Use This For My Kanban"),
applyExamples: (index) => {
- for (const groupName of this.props.exampleData.examples[index].columns) {
+ const { examples, foldField } = this.props.exampleData;
+ const { columns, foldedColumns = [] } = examples[index];
+ for (const groupName of columns) {
this.props.onValidate(groupName);
}
+ for (const groupName of foldedColumns) {
+ this.props.onValidate(groupName, { [foldField]: true }, true);
+ }
},
});
}
diff --git a/addons/web/static/src/views/kanban/kanban_renderer.js b/addons/web/static/src/views/kanban/kanban_renderer.js
index 71166c13d4f..aed78412b8c 100644
--- a/addons/web/static/src/views/kanban/kanban_renderer.js
+++ b/addons/web/static/src/views/kanban/kanban_renderer.js
@@ -51,13 +51,17 @@ export function canQuickCreate(list) {
}
function validateColumnQuickCreateExamples(data) {
- const { allowedGroupBys = [], examples = [] } = data;
+ const { allowedGroupBys = [], examples = [], foldField = "" } = data;
if (!allowedGroupBys.length) {
throw new Error("The example data must contain an array of allowed groupbys");
}
if (!examples.length) {
throw new Error("The example data must contain an array of examples");
}
+ const someHasFoldedColumns = examples.some(({ foldedColumns = [] }) => foldedColumns.length);
+ if (!foldField && someHasFoldedColumns) {
+ throw new Error("The example data must contain a fold field if there are folded columns");
+ }
}
export class KanbanRenderer extends Component {
diff --git a/addons/web/static/src/views/kanban/kanban_renderer.xml b/addons/web/static/src/views/kanban/kanban_renderer.xml
index 203b853ec30..27662d43979 100644
--- a/addons/web/static/src/views/kanban/kanban_renderer.xml
+++ b/addons/web/static/src/views/kanban/kanban_renderer.xml
@@ -116,7 +116,7 @@
diff --git a/addons/web/static/src/views/relational_model.js b/addons/web/static/src/views/relational_model.js
index d01eeb74228..9ff6d31c0b9 100644
--- a/addons/web/static/src/views/relational_model.js
+++ b/addons/web/static/src/views/relational_model.js
@@ -2272,8 +2272,8 @@ export class DynamicGroupList extends DynamicList {
/**
* @see {_createGroup}
*/
- async createGroup(groupName) {
- await this.model.mutex.exec(() => this._createGroup(groupName));
+ async createGroup(groupName, groupData, isFolded) {
+ await this.model.mutex.exec(() => this._createGroup(groupName, groupData, isFolded));
}
/**
@@ -2413,27 +2413,27 @@ export class DynamicGroupList extends DynamicList {
/**
* @param {string} groupName
+ * @param {{ [relatedFieldName: string]: any }} [groupData={}]
+ * @param {boolean} [isFolded=false]
* @returns {Promise}
*/
- async _createGroup(groupName) {
- const [id, displayName] = await this.model.orm.call(
- this.groupByField.relation,
- "name_create",
- [groupName],
- { context: this.context }
- );
+ async _createGroup(groupName, groupData = {}, isFolded = false) {
+ groupData = { ...groupData, name: groupName };
+ const [id] = await this.model.orm.create(this.groupByField.relation, [groupData], {
+ context: this.context,
+ });
const [lastGroup] = this.groups.slice(-1);
const group = this.model.createDataPoint("group", {
...this.commonGroupParams,
count: 0,
value: id,
- displayName,
+ displayName: groupName,
aggregates: {},
groupByField: this.groupByField,
groupDomain: Domain.and([this.domain, [[this.groupByField.name, "=", id]]]).toList(),
+ isFolded,
rawContext: this.rawContext,
});
- group.isFolded = false;
this.addGroup(group);
if (lastGroup) {
diff --git a/addons/web/static/tests/views/kanban_view_tests.js b/addons/web/static/tests/views/kanban_view_tests.js
index e121af48a5d..a5bb2b8d733 100644
--- a/addons/web/static/tests/views/kanban_view_tests.js
+++ b/addons/web/static/tests/views/kanban_view_tests.js
@@ -2249,7 +2249,7 @@ QUnit.module("Views", (hooks) => {
"web_search_read", // initial search_read (second column)
"get_views", // get form view
"onchange", // quick create
- "create", // should perform a name_create to create the record
+ "create", // should perform a create to create the record
"onchange", // reopen the quick create automatically
"read", // read the created record
]);
@@ -4292,7 +4292,7 @@ QUnit.module("Views", (hooks) => {
"",
groupBy: ["product_id"],
async mockRPC(route, { method, model }) {
- if (method === "name_create" && model === "product") {
+ if (method === "create" && model === "product") {
await prom;
}
},
@@ -5687,7 +5687,7 @@ QUnit.module("Views", (hooks) => {
"",
groupBy: ["product_id"],
async mockRPC(route, { method }) {
- if (method === "name_create" || route === "/web/dataset/resequence") {
+ if (method === "create" || route === "/web/dataset/resequence") {
assert.step(method || route);
}
},
@@ -5735,7 +5735,7 @@ QUnit.module("Views", (hooks) => {
"o_column_folded",
"the created column should not be folded"
);
- assert.verifySteps(["name_create", "/web/dataset/resequence"]);
+ assert.verifySteps(["create", "/web/dataset/resequence"]);
// fold and unfold the created column, and check that no RPCs are done (as there are no records)
const clickColumnAction = await toggleColumnActions(2);
@@ -6124,7 +6124,7 @@ QUnit.module("Views", (hooks) => {
);
assert.deepEqual(resequencedIDs, [4, 3], "moved column should be resequenced accordingly");
- assert.verifySteps(["name_create"]);
+ assert.verifySteps(["create"]);
});
QUnit.test("create a column, delete it and create another one", async (assert) => {
@@ -6552,6 +6552,66 @@ QUnit.module("Views", (hooks) => {
);
});
+ QUnit.test("quick create column and examples: with folded columns", async (assert) => {
+ serverData.models.partner.records = [];
+ serverData.models.product.fields.folded = { string: "Folded", type: "boolean" };
+ serviceRegistry.add("dialog", dialogService, { force: true });
+ registry.category("kanban_examples").add("test", {
+ allowedGroupBys: ["product_id"],
+ foldField: "folded",
+ examples: [
+ {
+ name: "A first example",
+ columns: ["not folded"],
+ foldedColumns: ["folded"],
+ description: "A weak description.",
+ },
+ ],
+ });
+
+ const expectedGroups = ['[[{"name":"not folded"}]]', '[[{"folded":true,"name":"folded"}]]'];
+ await makeView({
+ type: "kanban",
+ resModel: "partner",
+ serverData,
+ arch: /* xml */ `
+
+
+
+
+
+
+ `,
+ groupBy: ["product_id"],
+ mockRPC(route, args) {
+ if (args?.method === "create") {
+ assert.step(`${args.method} (model: ${args.model})`);
+ assert.strictEqual(JSON.stringify(args.args), expectedGroups.shift());
+ }
+ },
+ });
+
+ // the quick create should already be unfolded as there are no records
+ assert.containsOnce(target, ".o_column_quick_create .o_quick_create_unfolded");
+
+ // click to see the examples
+ await click(target, ".o_column_quick_create .o_kanban_examples");
+
+ // apply the examples
+ assert.verifySteps([]);
+ await click(document.body, ".modal .modal-footer .btn.btn-primary");
+ assert.verifySteps(["create (model: product)", "create (model: product)"]);
+
+ // the applied examples should be visible
+ assert.containsN(target, ".o_kanban_group", 2);
+ assert.containsOnce(target, ".o_kanban_group:not(.o_column_folded)");
+ assert.containsOnce(target, ".o_kanban_group.o_column_folded");
+ assert.deepEqual(
+ [...target.querySelectorAll(".o_kanban_group")].map((e) => e.textContent),
+ ["not folded", "folded (0)"]
+ );
+ });
+
QUnit.test("quick create column's apply button's display text", async (assert) => {
serviceRegistry.add("dialog", dialogService, { force: true });
const applyExamplesText = "Use This For My Test";