diff --git a/addons/web/static/src/views/view.js b/addons/web/static/src/views/view.js index 10f338c3f1e..05c47c85c5a 100644 --- a/addons/web/static/src/views/view.js +++ b/addons/web/static/src/views/view.js @@ -100,6 +100,7 @@ export function getDefaultConfig() { */ export class ViewNotFoundError extends Error {} +export class LegacyFormViewInDialogError extends Error {} const STANDARD_PROPS = [ "resModel", @@ -270,6 +271,10 @@ export class View extends Component { } } + if (descr.type === "form" && descr.isLegacy && this.env.inDialog) { + throw new LegacyFormViewInDialogError(); + } + Object.assign(this.env.config, { viewId: viewDescription.id, viewType: type, diff --git a/addons/web/static/src/views/view_dialogs/form_view_dialog.js b/addons/web/static/src/views/view_dialogs/form_view_dialog.js index 93b8aaf66bf..30d9061a97f 100644 --- a/addons/web/static/src/views/view_dialogs/form_view_dialog.js +++ b/addons/web/static/src/views/view_dialogs/form_view_dialog.js @@ -2,9 +2,11 @@ import { Dialog } from "@web/core/dialog/dialog"; import { useChildRef } from "@web/core/utils/hooks"; -import { View } from "@web/views/view"; +import { LegacyFormViewInDialogError, View } from "@web/views/view"; +import { FormViewDialog as LegacyFormViewDialog } from "web.view_dialogs"; +import { standaloneAdapter } from "web.OwlCompatibility"; -const { Component, onMounted } = owl; +const { Component, onError, onMounted, onWillDestroy, useState } = owl; export class FormViewDialog extends Component { setup() { @@ -51,7 +53,10 @@ export class FormViewDialog extends Component { }; onMounted(() => { - if (this.modalRef.el.querySelector(".modal-footer").childElementCount > 1) { + if ( + !this.state.error && + this.modalRef.el.querySelector(".modal-footer").childElementCount > 1 + ) { const defaultButton = this.modalRef.el.querySelector( ".modal-footer button.o-default-button" ); @@ -60,6 +65,36 @@ export class FormViewDialog extends Component { } } }); + + // FIXME: If the form view to instantiate is a js_class that hasn't been converted yet, + // we can't use the new FormViewDialog, as it would instantiate the legacy form view. As + // a consequence, the control panel buttons would not be moved to the footer. In this case, + // View triggers an error that we catch here, and we spawn a legacy FormViewDialog instead. + this.state = useState({ error: null }); + this.dialogClose = []; + onError((e) => { + if (e.cause instanceof LegacyFormViewInDialogError) { + this.state.error = e.cause; + const adapterParent = standaloneAdapter({ Component }); + const dialog = new LegacyFormViewDialog(adapterParent, { + res_model: this.props.resModel, + context: this.props.context || {}, + title: this.props.title, + disable_multiple_selection: true, + on_saved: async (record) => { + await this.props.onRecordSaved(record); + this.props.close(); + }, + }); + dialog.open(); + this.dialogClose.push(() => dialog.close()); + return; + } + throw e; + }); + onWillDestroy(() => { + this.dialogClose.forEach((close) => close()); + }); } } diff --git a/addons/web/static/src/views/view_dialogs/form_view_dialog.xml b/addons/web/static/src/views/view_dialogs/form_view_dialog.xml index 3a1891de2d0..13584b0b7f1 100644 --- a/addons/web/static/src/views/view_dialogs/form_view_dialog.xml +++ b/addons/web/static/src/views/view_dialogs/form_view_dialog.xml @@ -2,7 +2,7 @@ - +