From a02af5b2597a101defddcbc2df15dded4ac32cf8 Mon Sep 17 00:00:00 2001 From: Lucas Perais Date: Fri, 9 Sep 2022 08:58:09 +0000 Subject: [PATCH] [REF] web: basicRelationalModel: factorize legacyUtilities The mapping operations between the new RelationalModel API and the BasicModel is now done in its own file X-original-commit: 1202610ce6946ee4b2878e19e6ee6038edc9a71e Part-of: odoo/odoo#102153 --- .../src/views/basic_relational_model.js | 158 +----------------- addons/web/static/src/views/legacy_utils.js | 150 +++++++++++++++++ 2 files changed, 156 insertions(+), 152 deletions(-) create mode 100644 addons/web/static/src/views/legacy_utils.js diff --git a/addons/web/static/src/views/basic_relational_model.js b/addons/web/static/src/views/basic_relational_model.js index e5446e125d6..3a1f55ccd0d 100644 --- a/addons/web/static/src/views/basic_relational_model.js +++ b/addons/web/static/src/views/basic_relational_model.js @@ -3,171 +3,25 @@ import { makeContext } from "@web/core/context"; import { Domain } from "@web/core/domain"; import { WarningDialog } from "@web/core/errors/error_dialogs"; -import { - deserializeDate, - deserializeDateTime, - serializeDate, - serializeDateTime, -} from "@web/core/l10n/dates"; +import { deserializeDate, deserializeDateTime } from "@web/core/l10n/dates"; import { KeepLast } from "@web/core/utils/concurrency"; import { escape } from "@web/core/utils/strings"; import { mapDoActionOptionAPI } from "@web/legacy/backend_utils"; import { Model } from "@web/views/model"; import { evalDomain } from "@web/views/utils"; +import { + mapWowlValueToLegacy, + mapViews, + mapActiveFieldsToFieldsInfo, +} from "@web/views/legacy_utils"; import { localization } from "@web/core/l10n/localization"; import BasicModel from "web.BasicModel"; import Context from "web.Context"; -import fieldRegistry from "web.field_registry"; -import { parse } from "web.field_utils"; -import { traverse } from "web.utils"; -import { parseArch } from "web.viewUtils"; -const { date: parseDate, datetime: parseDateTime } = parse; const { markup, toRaw } = owl; const DEFAULT_HANDLE_FIELD = "sequence"; -function mapWowlValueToLegacy(value, type) { - switch (type) { - case "date": - // from luxon to moment - return value ? parseDate(serializeDate(value), null, { isUTC: true }) : false; - case "datetime": - // from luxon to moment - return value ? parseDateTime(serializeDateTime(value), null, { isUTC: true }) : false; - case "many2one": - return value ? { id: value[0], display_name: value[1] } : false; - case "reference": - return value - ? { id: value.resId, display_name: value.displayName, model: value.resModel } - : false; - case "one2many": - case "many2many": - if (value.operation === "REPLACE_WITH") { - return { operation: "REPLACE_WITH", ids: value.resIds }; - } - return value; - default: - return value; - } -} - -function mapViews(views, env) { - const res = {}; - for (const [viewType, viewDescr] of Object.entries(views || {})) { - const arch = parseArch(viewDescr.__rawArch); - traverse(arch, function (node) { - if (typeof node === "string") { - return false; - } - node.attrs.modifiers = node.attrs.modifiers ? JSON.parse(node.attrs.modifiers) : {}; - return true; - }); - // the basic model expects the former shape of load_views result, where we don't know - // all co-model fields, only those in the subview, so we filter the fields here - const fields = {}; - for (const f in viewDescr.activeFields) { - fields[f] = viewDescr.fields[f]; - } - res[viewType] = { - arch, - fields, - type: viewType, - fieldsInfo: mapActiveFieldsToFieldsInfo(viewDescr.activeFields, fields, viewType, env), - }; - for (const fieldName in res[viewType].fieldsInfo[viewType]) { - if (!res[viewType].fields[fieldName]) { - res[viewType].fields[fieldName] = { - name: fieldName, - type: res[viewType].fieldsInfo[viewType][fieldName].type, - }; - } - } - } - return res; -} - -function mapActiveFieldsToFieldsInfo(activeFields, fields, viewType, env) { - const fieldsInfo = {}; - fieldsInfo[viewType] = {}; - for (const [fieldName, fieldDescr] of Object.entries(activeFields)) { - const views = mapViews(fieldDescr.views, env); - const field = fields[fieldName]; - let Widget; - if (fieldDescr.widget) { - Widget = fieldRegistry.getAny([`${viewType}.${fieldDescr.widget}`, fieldDescr.widget]); - } else { - Widget = fieldRegistry.getAny([`${viewType}.${field.type}`, field.type]); - } - Widget = Widget || fieldRegistry.get("abstract"); - let domain; - if (fieldDescr.domain) { - domain = fieldDescr.domain.toString(); - } - let mode = fieldDescr.viewMode; - if (mode && mode.split(",").length !== 1) { - mode = env.isSmall ? "kanban" : "list"; - } - const FieldComponent = fieldDescr.FieldComponent; - const fieldInfo = { - Widget, // remove this when we no longer support legacy fields inside wowl views - specialData: FieldComponent && FieldComponent.legacySpecialData, - domain, - context: fieldDescr.context, - fieldDependencies: {}, // ?? - force_save: fieldDescr.forceSave, - mode, - modifiers: fieldDescr.modifiers, - name: fieldName, - options: fieldDescr.options, - views, - widget: fieldDescr.widget, - __WOWL_FIELD_DESCR__: fieldDescr, - }; - - if (FieldComponent && FieldComponent.limit) { - fieldInfo.limit = FieldComponent.limit; - } - - if (fieldDescr.modifiers && fieldDescr.modifiers.invisible === true) { - fieldInfo.__no_fetch = true; - } - - if (!fieldInfo.__no_fetch && FieldComponent && FieldComponent.fieldsToFetch) { - fieldInfo.relatedFields = { ...FieldComponent.fieldsToFetch }; - fieldInfo.viewType = "default"; - const defaultView = {}; - for (const fieldName of Object.keys(FieldComponent.fieldsToFetch)) { - defaultView[fieldName] = {}; - if (fieldDescr.fieldsToFetch[fieldName]) { - defaultView[fieldName].__WOWL_FIELD_DESCR__ = - fieldDescr.fieldsToFetch[fieldName]; - } - } - fieldInfo.fieldsInfo = { default: defaultView }; - const colorField = fieldInfo.options && fieldInfo.options.color_field; - if (colorField) { - fieldInfo.relatedFields[colorField] = { type: "integer" }; - fieldInfo.fieldsInfo.default[colorField] = {}; - if (fieldDescr.fieldsToFetch[colorField]) { - fieldInfo.fieldsInfo.default[colorField].__WOWL_FIELD_DESCR__ = - fieldDescr.fieldsToFetch[colorField]; - } - } - } - if (fieldDescr.views && fieldDescr.views[fieldDescr.viewMode]) { - fieldInfo.limit = fieldDescr.views[fieldDescr.viewMode].limit || 40; - fieldInfo.orderedBy = fieldDescr.views[fieldDescr.viewMode].defaultOrder; - } - if (fieldDescr.onChange && !fields[fieldName].onChange) { - fields[fieldName].onChange = "1"; - } - // FIXME? FieldWidget in kanban undefined - fieldsInfo[viewType][fieldName] = fieldInfo; - } - return fieldsInfo; -} - let nextId = 0; class DataPoint { /** diff --git a/addons/web/static/src/views/legacy_utils.js b/addons/web/static/src/views/legacy_utils.js new file mode 100644 index 00000000000..a98189c308e --- /dev/null +++ b/addons/web/static/src/views/legacy_utils.js @@ -0,0 +1,150 @@ +/** @odoo-module **/ +import fieldRegistry from "web.field_registry"; +import { parseArch } from "web.viewUtils"; +import { parse } from "web.field_utils"; +import { traverse } from "web.utils"; + +import { serializeDate, serializeDateTime } from "@web/core/l10n/dates"; + +const { date: parseDate, datetime: parseDateTime } = parse; + +export function mapWowlValueToLegacy(value, type) { + switch (type) { + case "date": + // from luxon to moment + return value ? parseDate(serializeDate(value), null, { isUTC: true }) : false; + case "datetime": + // from luxon to moment + return value ? parseDateTime(serializeDateTime(value), null, { isUTC: true }) : false; + case "many2one": + return value ? { id: value[0], display_name: value[1] } : false; + case "reference": + return value + ? { id: value.resId, display_name: value.displayName, model: value.resModel } + : false; + case "one2many": + case "many2many": + if (value.operation === "REPLACE_WITH") { + return { operation: "REPLACE_WITH", ids: value.resIds }; + } + return value; + default: + return value; + } +} + +export function mapViews(views, env) { + const res = {}; + for (const [viewType, viewDescr] of Object.entries(views || {})) { + const arch = parseArch(viewDescr.__rawArch); + traverse(arch, function (node) { + if (typeof node === "string") { + return false; + } + node.attrs.modifiers = node.attrs.modifiers ? JSON.parse(node.attrs.modifiers) : {}; + return true; + }); + // the basic model expects the former shape of load_views result, where we don't know + // all co-model fields, only those in the subview, so we filter the fields here + const fields = {}; + for (const f in viewDescr.activeFields) { + fields[f] = viewDescr.fields[f]; + } + res[viewType] = { + arch, + fields, + type: viewType, + fieldsInfo: mapActiveFieldsToFieldsInfo(viewDescr.activeFields, fields, viewType, env), + }; + for (const fieldName in res[viewType].fieldsInfo[viewType]) { + if (!res[viewType].fields[fieldName]) { + res[viewType].fields[fieldName] = { + name: fieldName, + type: res[viewType].fieldsInfo[viewType][fieldName].type, + }; + } + } + } + return res; +} + +export function mapActiveFieldsToFieldsInfo(activeFields, fields, viewType, env) { + const fieldsInfo = {}; + fieldsInfo[viewType] = {}; + for (const [fieldName, fieldDescr] of Object.entries(activeFields)) { + const views = mapViews(fieldDescr.views, env); + const field = fields[fieldName]; + let Widget; + if (fieldDescr.widget) { + Widget = fieldRegistry.getAny([`${viewType}.${fieldDescr.widget}`, fieldDescr.widget]); + } else { + Widget = fieldRegistry.getAny([`${viewType}.${field.type}`, field.type]); + } + Widget = Widget || fieldRegistry.get("abstract"); + let domain; + if (fieldDescr.domain) { + domain = fieldDescr.domain.toString(); + } + let mode = fieldDescr.viewMode; + if (mode && mode.split(",").length !== 1) { + mode = env.isSmall ? "kanban" : "list"; + } + const FieldComponent = fieldDescr.FieldComponent; + const fieldInfo = { + Widget, // remove this when we no longer support legacy fields inside wowl views + specialData: FieldComponent && FieldComponent.legacySpecialData, + domain, + context: fieldDescr.context, + fieldDependencies: {}, // ?? + force_save: fieldDescr.forceSave, + mode, + modifiers: fieldDescr.modifiers, + name: fieldName, + options: fieldDescr.options, + views, + widget: fieldDescr.widget, + __WOWL_FIELD_DESCR__: fieldDescr, + }; + + if (FieldComponent && FieldComponent.limit) { + fieldInfo.limit = FieldComponent.limit; + } + + if (fieldDescr.modifiers && fieldDescr.modifiers.invisible === true) { + fieldInfo.__no_fetch = true; + } + + if (!fieldInfo.__no_fetch && FieldComponent && FieldComponent.fieldsToFetch) { + fieldInfo.relatedFields = { ...FieldComponent.fieldsToFetch }; + fieldInfo.viewType = "default"; + const defaultView = {}; + for (const fieldName of Object.keys(FieldComponent.fieldsToFetch)) { + defaultView[fieldName] = {}; + if (fieldDescr.fieldsToFetch[fieldName]) { + defaultView[fieldName].__WOWL_FIELD_DESCR__ = + fieldDescr.fieldsToFetch[fieldName]; + } + } + fieldInfo.fieldsInfo = { default: defaultView }; + const colorField = fieldInfo.options && fieldInfo.options.color_field; + if (colorField) { + fieldInfo.relatedFields[colorField] = { type: "integer" }; + fieldInfo.fieldsInfo.default[colorField] = {}; + if (fieldDescr.fieldsToFetch[colorField]) { + fieldInfo.fieldsInfo.default[colorField].__WOWL_FIELD_DESCR__ = + fieldDescr.fieldsToFetch[colorField]; + } + } + } + if (fieldDescr.views && fieldDescr.views[fieldDescr.viewMode]) { + fieldInfo.limit = fieldDescr.views[fieldDescr.viewMode].limit || 40; + fieldInfo.orderedBy = fieldDescr.views[fieldDescr.viewMode].defaultOrder; + } + if (fieldDescr.onChange && !fields[fieldName].onChange) { + fields[fieldName].onChange = "1"; + } + // FIXME? FieldWidget in kanban undefined + fieldsInfo[viewType][fieldName] = fieldInfo; + } + return fieldsInfo; +}