[REF] spreadsheet: move list dataSources to UI
Before this commit, the list's dataSources were managed by the core plugin `ListCorePlugin`. This didn't make sense since dataSources aren't core data: - they are neither exported nor imported - they can be different for each user (their ids were generated via uuidv4 at import) - managing them required to handle local command in the core plugin Moved the dataSources management to the UI plugin `ListUIPlugin` and moved the relevant getters inside this plugin. Changed the ids of the dataSources to be the same as the list's id + a prefix, to avoid having to maintain a mapping `listId` <=> `dataSourceId` . This commit also removes the dataSourceId from the INSERT_ODOO_LIST command, which have no place here since this is a core command and the dataSources are now a pure UI concept. Task: 3293491 Part-of: odoo/odoo#120136
This commit is contained in:
@@ -3,13 +3,11 @@
|
||||
import * as spreadsheet from "@odoo/o-spreadsheet";
|
||||
import CommandResult from "../../o_spreadsheet/cancelled_reason";
|
||||
import { getMaxObjectId } from "../../helpers/helpers";
|
||||
import ListDataSource from "../list_data_source";
|
||||
import { TOP_LEVEL_STYLE } from "../../helpers/constants";
|
||||
import { _t } from "@web/core/l10n/translation";
|
||||
import { globalFiltersFieldMatchers } from "@spreadsheet/global_filters/plugins/global_filters_core_plugin";
|
||||
import { sprintf } from "@web/core/utils/strings";
|
||||
import { checkFilterFieldMatching } from "@spreadsheet/global_filters/helpers";
|
||||
import { getFirstListFunction, getNumberOfListFormulas } from "../list_helpers";
|
||||
|
||||
/**
|
||||
* @typedef {Object} ListDefinition
|
||||
@@ -35,7 +33,6 @@ const { CorePlugin } = spreadsheet;
|
||||
export default class ListCorePlugin extends CorePlugin {
|
||||
constructor(config) {
|
||||
super(config);
|
||||
this.dataSources = config.custom.dataSources;
|
||||
|
||||
this.nextId = 1;
|
||||
/** @type {Object.<string, List>} */
|
||||
@@ -46,9 +43,7 @@ export default class ListCorePlugin extends CorePlugin {
|
||||
getDisplayName: (listId) => this.getters.getListName(listId),
|
||||
getTag: (listId) => sprintf(_t("List #%s"), listId),
|
||||
getFieldMatching: (listId, filterId) => this.getListFieldMatching(listId, filterId),
|
||||
waitForReady: () => this.getListsWaitForReady(),
|
||||
getModel: (listId) => this.getListDefinition(listId).model,
|
||||
getFields: (listId) => this.getListDataSource(listId).getFields(),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -87,10 +82,9 @@ export default class ListCorePlugin extends CorePlugin {
|
||||
handle(cmd) {
|
||||
switch (cmd.type) {
|
||||
case "INSERT_ODOO_LIST": {
|
||||
const { sheetId, col, row, id, definition, dataSourceId, linesNumber, columns } =
|
||||
cmd;
|
||||
const { sheetId, col, row, id, definition, linesNumber, columns } = cmd;
|
||||
const anchor = [col, row];
|
||||
this._addList(id, definition, dataSourceId, linesNumber);
|
||||
this._addList(id, definition);
|
||||
this._insertList(sheetId, anchor, id, linesNumber, columns);
|
||||
this.history.update("nextId", parseInt(id, 10) + 1);
|
||||
break;
|
||||
@@ -120,19 +114,6 @@ export default class ListCorePlugin extends CorePlugin {
|
||||
"domain",
|
||||
cmd.domain
|
||||
);
|
||||
const list = this.lists[cmd.listId];
|
||||
this.dataSources.add(list.dataSourceId, ListDataSource, list.definition);
|
||||
break;
|
||||
}
|
||||
case "UNDO":
|
||||
case "REDO": {
|
||||
const domainEditionCommands = cmd.commands.filter(
|
||||
(cmd) => cmd.type === "UPDATE_ODOO_LIST_DOMAIN"
|
||||
);
|
||||
for (const cmd of domainEditionCommands) {
|
||||
const list = this.lists[cmd.listId];
|
||||
this.dataSources.add(list.dataSourceId, ListDataSource, list.definition);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "ADD_GLOBAL_FILTER":
|
||||
@@ -144,64 +125,13 @@ export default class ListCorePlugin extends CorePlugin {
|
||||
case "REMOVE_GLOBAL_FILTER":
|
||||
this._onFilterDeletion(cmd.id);
|
||||
break;
|
||||
|
||||
case "START":
|
||||
for (const sheetId of this.getters.getSheetIds()) {
|
||||
const cells = this.getters.getCells(sheetId);
|
||||
for (const cell of Object.values(cells)) {
|
||||
if (cell.isFormula) {
|
||||
this._addListPositionToDataSource(cell.content);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "UPDATE_CELL":
|
||||
if (cmd.content) {
|
||||
this._addListPositionToDataSource(cmd.content);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the position of the records asked in the given formula and
|
||||
* increase the max position of the corresponding data source.
|
||||
*
|
||||
* @param {string} content Odoo list formula
|
||||
*/
|
||||
_addListPositionToDataSource(content) {
|
||||
if (getNumberOfListFormulas(content) !== 1) {
|
||||
return;
|
||||
}
|
||||
const { functionName, args } = getFirstListFunction(content);
|
||||
if (functionName !== "ODOO.LIST") {
|
||||
return;
|
||||
}
|
||||
const [listId, positionArg] = args.map((arg) => arg.value.toString());
|
||||
if (!(listId in this.lists)) {
|
||||
return;
|
||||
}
|
||||
const position = parseInt(positionArg, 10);
|
||||
if (isNaN(position)) {
|
||||
return;
|
||||
}
|
||||
const dataSourceId = this.lists[listId].dataSourceId;
|
||||
this.dataSources.get(dataSourceId).increaseMaxPosition(position);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Getters
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @param {string} id
|
||||
* @returns {import("@spreadsheet/list/list_data_source").default|undefined}
|
||||
*/
|
||||
getListDataSource(id) {
|
||||
const dataSourceId = this.lists[id].dataSourceId;
|
||||
return this.dataSources.get(dataSourceId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} id
|
||||
* @returns {string}
|
||||
@@ -226,16 +156,6 @@ export default class ListCorePlugin extends CorePlugin {
|
||||
return this.lists[id].fieldMatching;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} id
|
||||
* @returns {Promise<import("@spreadsheet/list/list_data_source").default>}
|
||||
*/
|
||||
async getAsyncListDataSource(id) {
|
||||
const dataSourceId = this.lists[id].dataSourceId;
|
||||
await this.dataSources.load(dataSourceId);
|
||||
return this.getListDataSource(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve all the list ids
|
||||
*
|
||||
@@ -271,6 +191,10 @@ export default class ListCorePlugin extends CorePlugin {
|
||||
};
|
||||
}
|
||||
|
||||
getListModelDefinition(id) {
|
||||
return this.lists[id].definition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if an id is an id of an existing list
|
||||
*
|
||||
@@ -286,14 +210,6 @@ export default class ListCorePlugin extends CorePlugin {
|
||||
// Private
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
*
|
||||
* @return {Promise[]}
|
||||
*/
|
||||
getListsWaitForReady() {
|
||||
return this.getListIds().map((ListId) => this.getListDataSource(ListId).loadMetadata());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current FieldMatching on a list
|
||||
*
|
||||
@@ -325,21 +241,14 @@ export default class ListCorePlugin extends CorePlugin {
|
||||
}
|
||||
}
|
||||
|
||||
_addList(id, definition, dataSourceId, limit, fieldMatching = {}) {
|
||||
_addList(id, definition, fieldMatching = {}) {
|
||||
const lists = { ...this.lists };
|
||||
lists[id] = {
|
||||
id,
|
||||
definition,
|
||||
dataSourceId,
|
||||
fieldMatching,
|
||||
};
|
||||
|
||||
if (!this.dataSources.contains(dataSourceId)) {
|
||||
this.dataSources.add(dataSourceId, ListDataSource, {
|
||||
...definition,
|
||||
limit,
|
||||
});
|
||||
}
|
||||
this.history.update("lists", lists);
|
||||
}
|
||||
|
||||
@@ -471,7 +380,7 @@ export default class ListCorePlugin extends CorePlugin {
|
||||
},
|
||||
name: list.name,
|
||||
};
|
||||
this._addList(id, definition, this.uuidGenerator.uuidv4(), 0, list.fieldMatching);
|
||||
this._addList(id, definition, list.fieldMatching);
|
||||
}
|
||||
}
|
||||
this.nextId = data.listNextId || getMaxObjectId(this.lists) + 1;
|
||||
@@ -492,10 +401,9 @@ export default class ListCorePlugin extends CorePlugin {
|
||||
}
|
||||
|
||||
ListCorePlugin.getters = [
|
||||
"getListDataSource",
|
||||
"getListDisplayName",
|
||||
"getAsyncListDataSource",
|
||||
"getListDefinition",
|
||||
"getListModelDefinition",
|
||||
"getListIds",
|
||||
"getListName",
|
||||
"getNextListId",
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
/** @odoo-module */
|
||||
|
||||
import * as spreadsheet from "@odoo/o-spreadsheet";
|
||||
import { getFirstListFunction } from "../list_helpers";
|
||||
import { getFirstListFunction, getNumberOfListFormulas } from "../list_helpers";
|
||||
import { Domain } from "@web/core/domain";
|
||||
import ListDataSource from "../list_data_source";
|
||||
import { globalFiltersFieldMatchers } from "@spreadsheet/global_filters/plugins/global_filters_core_plugin";
|
||||
|
||||
const { astToFormula } = spreadsheet;
|
||||
|
||||
@@ -16,11 +18,23 @@ export default class ListUIPlugin extends spreadsheet.UIPlugin {
|
||||
/** @type {string} */
|
||||
this.selectedListId = undefined;
|
||||
this.env = config.custom.env;
|
||||
|
||||
this.dataSources = config.custom.dataSources;
|
||||
|
||||
globalFiltersFieldMatchers["list"] = {
|
||||
...globalFiltersFieldMatchers["list"],
|
||||
getFields: (listId) => this.getListDataSource(listId).getFields(),
|
||||
waitForReady: () => this.getListsWaitForReady(),
|
||||
};
|
||||
}
|
||||
|
||||
beforeHandle(cmd) {
|
||||
switch (cmd.type) {
|
||||
case "START":
|
||||
for (const listId of this.getters.getListIds()) {
|
||||
this._setupListDataSource(listId, 0);
|
||||
}
|
||||
|
||||
// make sure the domains are correctly set before
|
||||
// any evaluation
|
||||
this._addDomains();
|
||||
@@ -34,6 +48,21 @@ export default class ListUIPlugin extends spreadsheet.UIPlugin {
|
||||
*/
|
||||
handle(cmd) {
|
||||
switch (cmd.type) {
|
||||
case "START":
|
||||
for (const sheetId of this.getters.getSheetIds()) {
|
||||
const cells = this.getters.getCells(sheetId);
|
||||
for (const cell of Object.values(cells)) {
|
||||
if (cell.isFormula) {
|
||||
this._addListPositionToDataSource(cell.content);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "INSERT_ODOO_LIST": {
|
||||
const { id, linesNumber } = cmd;
|
||||
this._setupListDataSource(id, linesNumber);
|
||||
break;
|
||||
}
|
||||
case "SELECT_ODOO_LIST":
|
||||
this._selectList(cmd.listId);
|
||||
break;
|
||||
@@ -50,8 +79,19 @@ export default class ListUIPlugin extends spreadsheet.UIPlugin {
|
||||
case "CLEAR_GLOBAL_FILTER_VALUE":
|
||||
this._addDomains();
|
||||
break;
|
||||
case "UPDATE_ODOO_LIST_DOMAIN": {
|
||||
const listDefinition = this.getters.getListModelDefinition(cmd.listId);
|
||||
const dataSourceId = this._getListDataSourceId(cmd.listId);
|
||||
this.dataSources.add(dataSourceId, ListDataSource, listDefinition);
|
||||
break;
|
||||
}
|
||||
case "UPDATE_CELL":
|
||||
if (cmd.content) {
|
||||
this._addListPositionToDataSource(cmd.content);
|
||||
}
|
||||
break;
|
||||
case "UNDO":
|
||||
case "REDO":
|
||||
case "REDO": {
|
||||
if (
|
||||
cmd.commands.find((command) =>
|
||||
[
|
||||
@@ -63,7 +103,22 @@ export default class ListUIPlugin extends spreadsheet.UIPlugin {
|
||||
) {
|
||||
this._addDomains();
|
||||
}
|
||||
|
||||
const domainEditionCommands = cmd.commands.filter(
|
||||
(cmd) =>
|
||||
cmd.type === "UPDATE_ODOO_LIST_DOMAIN" || cmd.type === "INSERT_ODOO_LIST"
|
||||
);
|
||||
for (const cmd of domainEditionCommands) {
|
||||
if (!this.getters.isExistingList(cmd.listId)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const listDefinition = this.getters.getListModelDefinition(cmd.listId);
|
||||
const dataSourceId = this._getListDataSourceId(cmd.listId);
|
||||
this.dataSources.add(dataSourceId, ListDataSource, listDefinition);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,6 +126,17 @@ export default class ListUIPlugin extends spreadsheet.UIPlugin {
|
||||
// Handlers
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
_setupListDataSource(listId, limit, definition) {
|
||||
const dataSourceId = this._getListDataSourceId(listId);
|
||||
definition = definition || this.getters.getListModelDefinition(listId);
|
||||
if (!this.dataSources.contains(dataSourceId)) {
|
||||
this.dataSources.add(dataSourceId, ListDataSource, {
|
||||
...definition,
|
||||
limit,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an additional domain to a list
|
||||
*
|
||||
@@ -128,6 +194,40 @@ export default class ListUIPlugin extends spreadsheet.UIPlugin {
|
||||
this.selectedListId = listId;
|
||||
}
|
||||
|
||||
_getListDataSourceId(listId) {
|
||||
return `list-${listId}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the position of the records asked in the given formula and
|
||||
* increase the max position of the corresponding data source.
|
||||
*
|
||||
* @param {string} content Odoo list formula
|
||||
*/
|
||||
_addListPositionToDataSource(content) {
|
||||
if (getNumberOfListFormulas(content) !== 1) {
|
||||
return;
|
||||
}
|
||||
const { functionName, args } = getFirstListFunction(content);
|
||||
if (functionName !== "ODOO.LIST") {
|
||||
return;
|
||||
}
|
||||
const [listId, positionArg] = args.map((arg) => arg.value.toString());
|
||||
|
||||
if (!this.getters.getListIds().includes(listId)) {
|
||||
return;
|
||||
}
|
||||
const position = parseInt(positionArg, 10);
|
||||
if (isNaN(position)) {
|
||||
return;
|
||||
}
|
||||
const dataSourceId = this._getListDataSourceId(listId);
|
||||
if (!this.dataSources.get(dataSourceId)) {
|
||||
this._setupListDataSource(listId, 0);
|
||||
}
|
||||
this.dataSources.get(dataSourceId).increaseMaxPosition(position);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Getters
|
||||
// -------------------------------------------------------------------------
|
||||
@@ -191,6 +291,35 @@ export default class ListUIPlugin extends spreadsheet.UIPlugin {
|
||||
getSelectedListId() {
|
||||
return this.selectedListId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} id
|
||||
* @returns {import("@spreadsheet/list/list_data_source").default|undefined}
|
||||
*/
|
||||
getListDataSource(id) {
|
||||
const dataSourceId = this._getListDataSourceId(id);
|
||||
return this.dataSources.get(dataSourceId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} id
|
||||
* @returns {Promise<import("@spreadsheet/list/list_data_source").default>}
|
||||
*/
|
||||
async getAsyncListDataSource(id) {
|
||||
const dataSourceId = this._getListDataSourceId(id);
|
||||
await this.dataSources.load(dataSourceId);
|
||||
return this.getListDataSource(id);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return {Promise[]}
|
||||
*/
|
||||
getListsWaitForReady() {
|
||||
return this.getters
|
||||
.getListIds()
|
||||
.map((listId) => this.getListDataSource(listId).loadMetadata());
|
||||
}
|
||||
}
|
||||
|
||||
ListUIPlugin.getters = [
|
||||
@@ -199,4 +328,6 @@ ListUIPlugin.getters = [
|
||||
"getListIdFromPosition",
|
||||
"getListCellValue",
|
||||
"getSelectedListId",
|
||||
"getListDataSource",
|
||||
"getAsyncListDataSource",
|
||||
];
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
/** @odoo-module */
|
||||
|
||||
import * as spreadsheet from "@odoo/o-spreadsheet";
|
||||
import { generateListDefinition } from "./data";
|
||||
import { createModelWithDataSource, waitForDataSourcesLoaded } from "./model";
|
||||
|
||||
const uuidGenerator = new spreadsheet.helpers.UuidGenerator();
|
||||
|
||||
/** @typedef {import("@spreadsheet/o_spreadsheet/o_spreadsheet").Model} Model */
|
||||
|
||||
/**
|
||||
@@ -31,7 +28,6 @@ export function insertListInSpreadsheet(model, params) {
|
||||
id: model.getters.getNextListId(),
|
||||
col,
|
||||
row,
|
||||
dataSourceId: uuidGenerator.uuidv4(),
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user