Odoo 15 - overwrite LegacyView in Owl framework

214 views Asked by At

I try to remove action :

beforeLeave: () => this.controllerRef.comp.__widget.canBeRemoved(), from useSetupAction to prevent write changes when user don't save the form with he edit.

Don't know how to do this from external module. I try to overwrite the file but not working.

full file:

/** @odoo-module **/
const { Component, hooks, tags } = owl;

import { useService } from "@web/core/utils/hooks";
import { useSetupAction } from "../webclient/actions/action_hook";
import legacyViewRegistry from "web.view_registry";
import { ViewAdapter } from "./action_adapters";
import Widget from "web.Widget";
import {
    breadcrumbsToLegacy,
    getGlobalState,
    getLocalState,
    searchModelStateToLegacy,
} from "./backend_utils";
import { setScrollPosition } from "../core/utils/scrolling";
import { registry } from "@web/core/registry";
import { loadPublicAsset } from "@web/core/assets";

const viewRegistry = registry.category("views");

function getJsClassWidget(fieldsInfo) {
    const parsedXML = new DOMParser().parseFromString(fieldsInfo.arch, "text/xml");
    const key = parsedXML.documentElement.getAttribute("js_class");
    return legacyViewRegistry.get(key);
}

const legacyViewTemplate = tags.xml`
    <ViewAdapter Component="Widget" View="View" viewInfo="viewInfo" viewParams="viewParams"
                 widget="widget" onReverseBreadcrumb="onReverseBreadcrumb" t-ref="controller"
                 t-on-scrollTo.stop="onScrollTo"/>`;

// registers a view from the legacy view registry to the wowl one, but wrapped
// into an Owl Component
function registerView(name, LegacyView) {
    class Controller extends Component {
        constructor() {
            super(...arguments);
            this.vm = useService("view");
            this.controllerRef = hooks.useRef("controller");
            this.Widget = Widget; // fool the ComponentAdapter with a simple Widget
            this.View = LegacyView;
            this.viewInfo = {};

            let resIds;
            let searchModel;
            let searchPanel;
            const { globalState } = this.props;
            if (globalState) {
                resIds = globalState.resIds;
                searchModel = searchModelStateToLegacy(globalState.searchModel);
                searchPanel = globalState.searchPanel;
            }

            // always add user context to the action context
            this.user = useService("user");
            const action = Object.assign({}, this.props.action, {
                context: Object.assign({}, this.user.context, this.props.action.context),
            });

            const { actionFlags, breadcrumbs = [] } = this.env.config;
            this.viewParams = Object.assign({}, actionFlags, {
                action,
                // legacy views automatically add the last part of the breadcrumbs
                breadcrumbs: breadcrumbsToLegacy(breadcrumbs),
                modelName: this.props.resModel,
                currentId: this.props.resId,
                controllerState: {
                    currentId:
                        "resId" in this.props
                            ? this.props.resId
                            : this.props.state && this.props.state.currentId,
                    resIds: this.props.resIds || resIds,
                    searchModel,
                    searchPanel,
                },
            });

            // To open a new empty form view
            // Legacy demands undefined ids, not False
            if (this.viewParams.currentId === false) {
                this.viewParams.currentId = undefined;
                this.viewParams.controllerState.currentId = undefined;
            }

            // Only add mode to viewParams if it is specified to avoid overwriting the default mode in some view (eg graph)
            if (this.props.mode) {
                this.viewParams.mode = this.props.mode;
            }
            this.widget = this.props.state && this.props.state.__legacy_widget__;
            this.onReverseBreadcrumb =
                this.props.state && this.props.state.__on_reverse_breadcrumb__;
            useSetupAction({
                beforeLeave: () => this.controllerRef.comp.__widget.canBeRemoved(),
                getGlobalState: () => getGlobalState(this.controllerRef.comp.exportState()),
                getLocalState: () => getLocalState(this.controllerRef.comp.exportState()),
            });
            this.onScrollTo = (ev) => {
                setScrollPosition(this, { left: ev.detail.left, top: ev.detail.top });
            };
        }

        async willStart() {
            const params = {
                resModel: this.props.resModel,
                views: this.props.views,
                context: this.props.context,
            };
            const options = {
                actionId: this.env.config.actionId,
                loadActionMenus: this.props.loadActionMenus,
                loadIrFilters: this.props.loadIrFilters,
            };
            const viewDescriptions = await this.vm.loadViews(params, options);
            const result = viewDescriptions.__legacy__;
            const fieldsInfo = result.fields_views[this.props.type];
            const jsClass = getJsClassWidget(fieldsInfo);
            this.View = jsClass || this.View;
            this.viewInfo = Object.assign({}, fieldsInfo, {
                fields: result.fields,
                viewFields: fieldsInfo.fields,
            });
            let controlPanelFieldsView;
            if (result.fields_views.search) {
                controlPanelFieldsView = Object.assign({}, result.fields_views.search, {
                    favoriteFilters: result.filters,
                    fields: result.fields,
                    viewFields: result.fields_views.search.fields,
                });
            }
            const { viewSwitcherEntries = [] } = this.env.config;
            const views = this.viewParams.action.views
                .filter(([, vtype]) => vtype !== "search")
                .map(([vid, vtype]) => {
                    const view = viewSwitcherEntries.find((v) => v.type === vtype);
                    if (view) {
                        return Object.assign({}, view, { viewID: vid });
                    } else {
                        return {
                            viewID: vid,
                            type: vtype,
                            multiRecord: !this.constructor.multiRecord,
                        };
                    }
                });
            this.viewParams.action = Object.assign({}, this.viewParams.action, {
                controlPanelFieldsView,
                _views: this.viewParams.action.views,
                views,
            });
        }
    }
    Controller.template = legacyViewTemplate;

    Controller.components = { ViewAdapter };
    Controller.display_name = LegacyView.prototype.display_name;
    Controller.icon = LegacyView.prototype.icon;
    Controller.isMobileFriendly = LegacyView.prototype.mobile_friendly;
    Controller.multiRecord = LegacyView.prototype.multi_record;
    Controller.type = LegacyView.prototype.viewType;
    Controller.isLegacy = true;
    if (!viewRegistry.contains(name)) {
        viewRegistry.add(name, Controller);
    }
}

// register views already in the legacy registry, and listens to future registrations
for (const [name, action] of Object.entries(legacyViewRegistry.entries())) {
    registerView(name, action);
}
legacyViewRegistry.onAdd(registerView);

export async function loadLegacyViews({ orm, rpc }) {
    if (!orm && rpc) {
        orm = {
            call: (...callArgs) => {
                const [model, method, args = [], kwargs = {}] = callArgs;
                return rpc({ model, method, args, kwargs });
            },
        };
    }
    await loadPublicAsset("web.assets_backend_legacy_lazy", orm);
}

path in manifest:

'web/static/src/legacy/legacy_views.js',
0

There are 0 answers