[FIX] web: ask to save new record before translating
Fixup for 4caa9596bc, where a rebase went bad.
Have a translatable field in a form view.
Create a new record with that form view.
Click on the button to open translations for that field.
Before this commit, the record was not before opening the translation dialog, hence
changing the translations could not work properly.
After this commit, this feature is back, and we ask to save a new record before
opening the translation dialog.
closes odoo/odoo#97824
Signed-off-by: Lucas Perais (lpe) <lpe@odoo.com>
This commit is contained in:
@@ -8,6 +8,7 @@ import { ComponentAdapter } from "web.OwlCompatibility";
|
||||
import viewUtils from "web.viewUtils";
|
||||
import { useWowlService } from "@web/legacy/utils";
|
||||
import { RPCError } from "@web/core/network/rpc_service";
|
||||
import { useTranslationDialog } from "@web/views/fields/translation_button";
|
||||
|
||||
const { Component, useEffect, xml } = owl;
|
||||
const fieldRegistry = registry.category("fields");
|
||||
@@ -22,6 +23,7 @@ const legacyFieldTemplate = xml`
|
||||
class FieldAdapter extends ComponentAdapter {
|
||||
setup() {
|
||||
super.setup();
|
||||
this.translationDialog = useTranslationDialog();
|
||||
this.wowlEnv = this.env;
|
||||
this.env = Component.env;
|
||||
this.orm = useWowlService("orm");
|
||||
|
||||
@@ -19,11 +19,8 @@
|
||||
<t t-if="props.isTranslatable">
|
||||
<TranslationButton
|
||||
fieldName="props.name"
|
||||
resId="props.record.resId"
|
||||
resModel="props.record.resModel"
|
||||
value="props.value"
|
||||
record="props.record"
|
||||
updateField="props.update"
|
||||
context="props.record.context"
|
||||
/>
|
||||
</t>
|
||||
</t>
|
||||
|
||||
@@ -18,11 +18,8 @@
|
||||
<t t-if="props.isTranslatable">
|
||||
<TranslationButton
|
||||
fieldName="props.name"
|
||||
resId="props.record.resId"
|
||||
resModel="props.record.resModel"
|
||||
value="props.value"
|
||||
record="props.record"
|
||||
updateField="props.update"
|
||||
context="props.record.context"
|
||||
/>
|
||||
</t>
|
||||
</t>
|
||||
|
||||
@@ -3,14 +3,75 @@
|
||||
import { localization } from "@web/core/l10n/localization";
|
||||
import { useService } from "@web/core/utils/hooks";
|
||||
import { TranslationDialog } from "./translation_dialog";
|
||||
import { ConfirmationDialog } from "@web/core/confirmation_dialog/confirmation_dialog";
|
||||
|
||||
const { Component } = owl;
|
||||
const { Component, useEnv } = owl;
|
||||
|
||||
/**
|
||||
* Prepares a function that will open the dialog that allows to edit translation
|
||||
* values for a given field.
|
||||
*
|
||||
* It is mainly a factorization of the feature that is also used
|
||||
* in legacy_fields. We expect it to be fully implemented in TranslationButton
|
||||
* when legacy code is removed.
|
||||
*/
|
||||
export function useTranslationDialog() {
|
||||
const dialog = useService("dialog");
|
||||
const rpc = useService("rpc");
|
||||
const env = useEnv();
|
||||
|
||||
async function openTranslationDialog({ record, fieldName, updateField }) {
|
||||
if (!record.resId) {
|
||||
let _continue = true;
|
||||
await new Promise((resolve) => {
|
||||
dialog.add(ConfirmationDialog, {
|
||||
async confirm() {
|
||||
_continue = await record.save({ stayInEdition: true });
|
||||
resolve();
|
||||
},
|
||||
cancel() {
|
||||
_continue = false;
|
||||
resolve();
|
||||
},
|
||||
body: env._t(
|
||||
"You need to save this new record before editing the translation. Do you want to proceed?"
|
||||
),
|
||||
title: env._t("Warning"),
|
||||
});
|
||||
});
|
||||
if (!_continue) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
const { resModel, resId, context } = record;
|
||||
const result = await rpc("/web/dataset/call_button", {
|
||||
model: "ir.translation",
|
||||
method: "translate_fields",
|
||||
args: [resModel, resId, fieldName],
|
||||
kwargs: { context },
|
||||
});
|
||||
|
||||
dialog.add(TranslationDialog, {
|
||||
domain: result.domain,
|
||||
searchName: result.context.search_default_name,
|
||||
fieldName: fieldName,
|
||||
userLanguageValue: record.data[fieldName] || "",
|
||||
isComingFromTranslationAlert: false,
|
||||
isText: result.context.translation_type === "text",
|
||||
showSource: result.context.translation_show_src,
|
||||
updateField,
|
||||
});
|
||||
}
|
||||
|
||||
return openTranslationDialog;
|
||||
}
|
||||
|
||||
export class TranslationButton extends Component {
|
||||
setup() {
|
||||
this.user = useService("user");
|
||||
this.rpc = useService("rpc");
|
||||
this.dialog = useService("dialog");
|
||||
this.translationDialog = useTranslationDialog();
|
||||
}
|
||||
|
||||
get isMultiLang() {
|
||||
@@ -20,24 +81,9 @@ export class TranslationButton extends Component {
|
||||
return this.user.lang.split("_")[0].toUpperCase();
|
||||
}
|
||||
|
||||
async onClick() {
|
||||
const result = await this.rpc("/web/dataset/call_button", {
|
||||
model: "ir.translation",
|
||||
method: "translate_fields",
|
||||
args: [this.props.resModel, this.props.resId, this.props.fieldName],
|
||||
kwargs: { context: this.props.context },
|
||||
});
|
||||
|
||||
this.dialog.add(TranslationDialog, {
|
||||
domain: result.domain,
|
||||
searchName: result.context.search_default_name,
|
||||
fieldName: this.props.fieldName,
|
||||
userLanguageValue: this.props.value || "",
|
||||
isComingFromTranslationAlert: false,
|
||||
isText: result.context.translation_type === "text",
|
||||
showSource: result.context.translation_show_src,
|
||||
updateField: this.props.updateField,
|
||||
});
|
||||
onClick() {
|
||||
const { fieldName, record, updateField } = this.props;
|
||||
this.translationDialog({ fieldName, record, updateField });
|
||||
}
|
||||
}
|
||||
TranslationButton.template = "web.TranslationButton";
|
||||
|
||||
@@ -20,6 +20,7 @@ import {
|
||||
triggerEvent,
|
||||
} from "@web/../tests/helpers/utils";
|
||||
import { FieldOne2Many } from "web.relational_fields";
|
||||
import { FieldChar as LegacyFieldChar } from "web.basic_fields";
|
||||
import * as legacyFieldRegistry from "web.field_registry";
|
||||
import { toggleActionMenu, toggleGroupByMenu, toggleMenuItem } from "@web/../tests/search/helpers";
|
||||
import { makeView, setupViewRegistries } from "@web/../tests/views/helpers";
|
||||
@@ -36,6 +37,8 @@ import BasicModel from "web.BasicModel";
|
||||
import { localization } from "@web/core/l10n/localization";
|
||||
import { SIZES } from "@web/core/ui/ui_service";
|
||||
|
||||
import * as legacyCore from "web.core";
|
||||
|
||||
const fieldRegistry = registry.category("fields");
|
||||
const serviceRegistry = registry.category("services");
|
||||
const widgetRegistry = registry.category("view_widgets");
|
||||
@@ -8030,6 +8033,103 @@ QUnit.module("Views", (hooks) => {
|
||||
assert.strictEqual(target.querySelector(".modal-title").textContent, "Translate: foo");
|
||||
});
|
||||
|
||||
QUnit.test("ask to save new record before opening translate dialog", async function (assert) {
|
||||
serverData.models.partner.fields.foo.translate = true;
|
||||
|
||||
patchWithCleanup(localization, {
|
||||
multiLang: true,
|
||||
});
|
||||
|
||||
await makeView({
|
||||
type: "form",
|
||||
resModel: "partner",
|
||||
serverData,
|
||||
arch: `
|
||||
<form>
|
||||
<field name="foo"/>
|
||||
</form>`,
|
||||
mockRPC(route, args) {
|
||||
assert.step(args.method);
|
||||
if (route === "/web/dataset/call_button") {
|
||||
return { context: {}, domain: [] };
|
||||
}
|
||||
if (args.method === "get_installed") {
|
||||
return [
|
||||
["CUST", "custom lang"],
|
||||
["CUST2", "second custom"],
|
||||
];
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
assert.verifySteps(["get_views", "onchange"]);
|
||||
assert.containsOnce(target, ".o_form_editable");
|
||||
await click(target, ".o_field_translate.btn-link");
|
||||
assert.containsOnce(target, ".modal");
|
||||
assert.strictEqual(target.querySelector(".modal-title").textContent, "Warning");
|
||||
|
||||
await click(target.querySelectorAll(".modal-footer button")[1]); // cancel
|
||||
assert.verifySteps([]);
|
||||
|
||||
await click(target, ".o_field_translate.btn-link");
|
||||
await click(target.querySelectorAll(".modal-footer button")[0]); // save
|
||||
assert.verifySteps(["create", "read", "translate_fields", "get_installed", "search_read"]);
|
||||
assert.containsOnce(target, ".modal");
|
||||
assert.strictEqual(target.querySelector(".modal-title").textContent, "Translate: foo");
|
||||
});
|
||||
|
||||
QUnit.test("legacy field support translation dialog", async (assert) => {
|
||||
serverData.models.partner.fields.foo.translate = true;
|
||||
|
||||
patchWithCleanup(legacyCore._t.database, {
|
||||
multi_lang: true,
|
||||
parameters: {
|
||||
code: "CUST",
|
||||
},
|
||||
});
|
||||
|
||||
const myChar = LegacyFieldChar.extend({
|
||||
async _render() {
|
||||
// DIY because the compatibility layer doesn't support
|
||||
// legacy widget having multiple nodes in their this.$el.
|
||||
await this._super(...arguments);
|
||||
const div = document.createElement("div");
|
||||
const $div = $(div).append(this.$el);
|
||||
this.setElement($div);
|
||||
},
|
||||
});
|
||||
|
||||
legacyFieldRegistry.add("legacy_char", myChar);
|
||||
await makeView({
|
||||
type: "form",
|
||||
resModel: "partner",
|
||||
serverData,
|
||||
resId: 1,
|
||||
arch: `
|
||||
<form>
|
||||
<field name="foo" widget="legacy_char"/>
|
||||
</form>`,
|
||||
mockRPC(route, args) {
|
||||
assert.step(args.method);
|
||||
if (route === "/web/dataset/call_button") {
|
||||
return { context: {}, domain: [] };
|
||||
}
|
||||
if (args.method === "get_installed") {
|
||||
return [
|
||||
["CUST", "custom lang"],
|
||||
["CUST2", "second custom"],
|
||||
];
|
||||
}
|
||||
},
|
||||
});
|
||||
assert.verifySteps(["get_views", "read"]);
|
||||
await clickEdit(target);
|
||||
await click(target, ".o_field_legacy_char .o_field_translate.btn-link");
|
||||
assert.verifySteps(["translate_fields", "get_installed", "search_read"]);
|
||||
assert.containsOnce(target, ".modal");
|
||||
assert.strictEqual(target.querySelector(".modal-title").textContent, "Translate: foo");
|
||||
});
|
||||
|
||||
QUnit.test("translation alerts are preserved on pager change", async function (assert) {
|
||||
serverData.models.partner.fields.foo.translate = true;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user