[FIX] web: FormViewDialog: fallback on LegacyFormViewDialog

It might happen that one wants to spawn a FormViewDialog with a
view that has a js_class, and the corresponding js code hasn't
been converted to owl yet (it is still an extension of the legacy
FormView). Before this commit, when that happened, the control
panel buttons of the form view weren't moved to the footer of the
dialog, because this isn't supported with legacy views. This
commit is a workaround, as it fallbacks on the legacy FormViewDialog
in this situation.

Without this commit, the main flow tour fails.

Part-of: odoo/odoo#78221
This commit is contained in:
Aaron Bohy
2022-07-22 16:21:39 +02:00
committed by Géry Debongnie
parent 1c344b8955
commit 8dda736df4
3 changed files with 44 additions and 4 deletions
+5
View File
@@ -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,
@@ -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());
});
}
}
@@ -2,7 +2,7 @@
<templates xml:space="preserve">
<t t-name="web.FormViewDialog" owl="1">
<Dialog title="props.title" contentClass="'o_form_view_dialog'" modalRef="modalRef">
<Dialog title="props.title" contentClass="'o_form_view_dialog'" modalRef="modalRef" t-if="!state.error">
<View t-props="viewProps"/>
<t t-set-slot="footer">
<t t-if="props.preventEdit and props.preventCreate">