As tempusdominus relies on jQuery, we have written our own date(time) picker in owl. This commit converts the remaining uses of the tempusdominus date(time) picker and replaces them by our own. closes odoo/odoo#133349 Signed-off-by: Julien Mougenot (jum) <jum@odoo.com>
410 lines
14 KiB
JavaScript
410 lines
14 KiB
JavaScript
/** @odoo-module **/
|
|
|
|
import { dialogService } from "@web/core/dialog/dialog_service";
|
|
import { notificationService } from "@web/core/notifications/notification_service";
|
|
import { ormService } from "@web/core/orm_service";
|
|
import { popoverService } from "@web/core/popover/popover_service";
|
|
import { registry } from "@web/core/registry";
|
|
import { legacyServiceProvider } from "@web/legacy/legacy_service_provider";
|
|
import { viewService } from "@web/views/view_service";
|
|
import { actionService } from "@web/webclient/actions/action_service";
|
|
import { effectService } from "@web/core/effects/effect_service";
|
|
import { hotkeyService } from "@web/core/hotkeys/hotkey_service";
|
|
import { menuService } from "@web/webclient/menus/menu_service";
|
|
import { WebClient } from "@web/webclient/webclient";
|
|
import { registerCleanup } from "../helpers/cleanup";
|
|
import { makeTestEnv } from "../helpers/mock_env";
|
|
import {
|
|
fakeTitleService,
|
|
fakeCompanyService,
|
|
makeFakeLocalizationService,
|
|
makeFakeRouterService,
|
|
makeFakeHTTPService,
|
|
makeFakeUserService,
|
|
} from "../helpers/mock_services";
|
|
import { getFixture, mount, nextTick } from "../helpers/utils";
|
|
import { uiService } from "@web/core/ui/ui_service";
|
|
import { commandService } from "@web/core/commands/command_service";
|
|
import { CustomFavoriteItem } from "@web/search/custom_favorite_item/custom_favorite_item";
|
|
import { overlayService } from "@web/core/overlay/overlay_service";
|
|
|
|
import { Component, xml } from "@odoo/owl";
|
|
import { fieldService } from "@web/core/field_service";
|
|
import { nameService } from "@web/core/name_service";
|
|
import { datetimePickerService } from "@web/core/datetime/datetimepicker_service";
|
|
|
|
const actionRegistry = registry.category("actions");
|
|
const serviceRegistry = registry.category("services");
|
|
const favoriteMenuRegistry = registry.category("favoriteMenu");
|
|
|
|
/**
|
|
* Builds the required registries for tests using a WebClient.
|
|
* We use a default version of each required registry item.
|
|
* If the registry already contains one of those items,
|
|
* the existing one is kept (it means it has been added in the test
|
|
* directly, e.g. to have a custom version of the item).
|
|
*/
|
|
export function setupWebClientRegistries() {
|
|
const favoriveMenuItems = {
|
|
"custom-favorite-item": {
|
|
value: { Component: CustomFavoriteItem, groupNumber: 3 },
|
|
options: { sequence: 0 },
|
|
},
|
|
};
|
|
for (const [key, { value, options }] of Object.entries(favoriveMenuItems)) {
|
|
if (!favoriteMenuRegistry.contains(key)) {
|
|
favoriteMenuRegistry.add(key, value, options);
|
|
}
|
|
}
|
|
const services = {
|
|
action: () => actionService,
|
|
command: () => commandService,
|
|
dialog: () => dialogService,
|
|
effect: () => effectService,
|
|
field: () => fieldService,
|
|
hotkey: () => hotkeyService,
|
|
http: () => makeFakeHTTPService(),
|
|
legacy_service_provider: () => legacyServiceProvider,
|
|
localization: () => makeFakeLocalizationService(),
|
|
menu: () => menuService,
|
|
name: () => nameService,
|
|
notification: () => notificationService,
|
|
orm: () => ormService,
|
|
overlay: () => overlayService,
|
|
popover: () => popoverService,
|
|
router: () => makeFakeRouterService(),
|
|
title: () => fakeTitleService,
|
|
ui: () => uiService,
|
|
user: () => makeFakeUserService(),
|
|
view: () => viewService,
|
|
company: () => fakeCompanyService,
|
|
datetime_picker: () => datetimePickerService,
|
|
};
|
|
for (const serviceName in services) {
|
|
if (!serviceRegistry.contains(serviceName)) {
|
|
serviceRegistry.add(serviceName, services[serviceName]());
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* This method create a web client instance properly configured.
|
|
*
|
|
* Note that the returned web client will be automatically cleaned up after the
|
|
* end of the test.
|
|
*
|
|
* @param {*} params
|
|
*/
|
|
export async function createWebClient(params) {
|
|
setupWebClientRegistries();
|
|
|
|
params.serverData = params.serverData || {};
|
|
const mockRPC = params.mockRPC || undefined;
|
|
const env = await makeTestEnv({
|
|
serverData: params.serverData,
|
|
mockRPC,
|
|
});
|
|
|
|
const WebClientClass = params.WebClientClass || WebClient;
|
|
const target = params && params.target ? params.target : getFixture();
|
|
const wc = await mount(WebClientClass, target, { env });
|
|
odoo.__WOWL_DEBUG__ = { root: wc };
|
|
target.classList.add("o_web_client"); // necessary for the stylesheet
|
|
registerCleanup(() => {
|
|
target.classList.remove("o_web_client");
|
|
});
|
|
// Wait for visual changes caused by a potential loadState
|
|
await nextTick();
|
|
return wc;
|
|
}
|
|
|
|
export function doAction(env, ...args) {
|
|
if (env instanceof Component) {
|
|
env = env.env;
|
|
}
|
|
return env.services.action.doAction(...args);
|
|
}
|
|
|
|
export async function loadState(env, state) {
|
|
if (env instanceof Component) {
|
|
env = env.env;
|
|
}
|
|
env.bus.trigger("test:hashchange", state);
|
|
// wait the asynchronous hashchange
|
|
// (the event hashchange must be triggered in a nonBlocking stack)
|
|
await nextTick();
|
|
// wait for BlankComponent
|
|
await nextTick();
|
|
// wait for the regular rendering
|
|
await nextTick();
|
|
}
|
|
|
|
export function getActionManagerServerData() {
|
|
// additional basic client action
|
|
class TestClientAction extends Component {}
|
|
TestClientAction.template = xml`
|
|
<div class="test_client_action">
|
|
ClientAction_<t t-esc="props.action.params?.description"/>
|
|
</div>`;
|
|
actionRegistry.add("__test__client__action__", TestClientAction);
|
|
|
|
const menus = {
|
|
root: { id: "root", children: [0, 1, 2], name: "root", appID: "root" },
|
|
// id:0 is a hack to not load anything at webClient mount
|
|
0: { id: 0, children: [], name: "UglyHack", appID: 0, xmlid: "menu_0" },
|
|
1: { id: 1, children: [], name: "App1", appID: 1, actionID: 1001, xmlid: "menu_1" },
|
|
2: { id: 2, children: [], name: "App2", appID: 2, actionID: 1002, xmlid: "menu_2" },
|
|
};
|
|
const actionsArray = [
|
|
{
|
|
id: 1,
|
|
xml_id: "action_1",
|
|
name: "Partners Action 1",
|
|
res_model: "partner",
|
|
type: "ir.actions.act_window",
|
|
views: [[1, "kanban"]],
|
|
},
|
|
{
|
|
id: 2,
|
|
xml_id: "action_2",
|
|
type: "ir.actions.server",
|
|
},
|
|
{
|
|
id: 3,
|
|
xml_id: "action_3",
|
|
name: "Partners",
|
|
res_model: "partner",
|
|
type: "ir.actions.act_window",
|
|
views: [
|
|
[false, "list"],
|
|
[1, "kanban"],
|
|
[false, "form"],
|
|
],
|
|
},
|
|
{
|
|
id: 4,
|
|
xml_id: "action_4",
|
|
name: "Partners Action 4",
|
|
res_model: "partner",
|
|
type: "ir.actions.act_window",
|
|
views: [
|
|
[1, "kanban"],
|
|
[2, "list"],
|
|
[false, "form"],
|
|
],
|
|
},
|
|
{
|
|
id: 5,
|
|
xml_id: "action_5",
|
|
name: "Create a Partner",
|
|
res_model: "partner",
|
|
target: "new",
|
|
type: "ir.actions.act_window",
|
|
views: [[false, "form"]],
|
|
},
|
|
{
|
|
id: 6,
|
|
xml_id: "action_6",
|
|
name: "Partner",
|
|
res_id: 2,
|
|
res_model: "partner",
|
|
target: "inline",
|
|
type: "ir.actions.act_window",
|
|
views: [[false, "form"]],
|
|
},
|
|
{
|
|
id: 7,
|
|
xml_id: "action_7",
|
|
name: "Some Report",
|
|
report_name: "some_report",
|
|
report_type: "qweb-pdf",
|
|
type: "ir.actions.report",
|
|
},
|
|
{
|
|
id: 8,
|
|
xml_id: "action_8",
|
|
name: "Favorite Ponies",
|
|
res_model: "pony",
|
|
type: "ir.actions.act_window",
|
|
views: [
|
|
[false, "list"],
|
|
[false, "form"],
|
|
],
|
|
},
|
|
{
|
|
id: 9,
|
|
xml_id: "action_9",
|
|
name: "A Client Action",
|
|
tag: "ClientAction",
|
|
type: "ir.actions.client",
|
|
},
|
|
{
|
|
id: 10,
|
|
type: "ir.actions.act_window_close",
|
|
},
|
|
{
|
|
id: 11,
|
|
xml_id: "action_11",
|
|
name: "Another Report",
|
|
report_name: "another_report",
|
|
report_type: "qweb-pdf",
|
|
type: "ir.actions.report",
|
|
close_on_report_download: true,
|
|
},
|
|
{
|
|
id: 12,
|
|
xml_id: "action_12",
|
|
name: "Some HTML Report",
|
|
report_name: "some_report",
|
|
report_type: "qweb-html",
|
|
type: "ir.actions.report",
|
|
},
|
|
{
|
|
id: 24,
|
|
name: "Partner",
|
|
res_id: 2,
|
|
res_model: "partner",
|
|
type: "ir.actions.act_window",
|
|
views: [[666, "form"]],
|
|
},
|
|
{
|
|
id: 25,
|
|
name: "Create a Partner",
|
|
res_model: "partner",
|
|
target: "new",
|
|
type: "ir.actions.act_window",
|
|
views: [[3, "form"]],
|
|
},
|
|
{
|
|
id: 26,
|
|
xml_id: "action_26",
|
|
name: "Partner",
|
|
res_model: "partner",
|
|
target: "new",
|
|
type: "ir.actions.act_window",
|
|
views: [[false, "list"]],
|
|
},
|
|
{
|
|
id: 1001,
|
|
tag: "__test__client__action__",
|
|
target: "main",
|
|
type: "ir.actions.client",
|
|
params: { description: "Id 1" },
|
|
},
|
|
{
|
|
id: 1002,
|
|
tag: "__test__client__action__",
|
|
target: "main",
|
|
type: "ir.actions.client",
|
|
params: { description: "Id 2" },
|
|
},
|
|
{
|
|
xmlId: "wowl.client_action",
|
|
id: 1099,
|
|
tag: "__test__client__action__",
|
|
target: "main",
|
|
type: "ir.actions.client",
|
|
params: { description: "xmlId" },
|
|
},
|
|
];
|
|
const actions = {};
|
|
actionsArray.forEach((act) => {
|
|
actions[act.xmlId || act.id] = act;
|
|
});
|
|
const archs = {
|
|
// kanban views
|
|
"partner,1,kanban":
|
|
'<kanban><templates><t t-name="kanban-box">' +
|
|
'<div class="oe_kanban_global_click"><field name="foo"/></div>' +
|
|
"</t></templates></kanban>",
|
|
// list views
|
|
"partner,false,list": '<tree><field name="foo"/></tree>',
|
|
"partner,2,list": '<tree limit="3"><field name="foo"/></tree>',
|
|
"pony,false,list": '<tree><field name="name"/></tree>',
|
|
// form views
|
|
"partner,false,form":
|
|
"<form>" +
|
|
"<header>" +
|
|
'<button name="object" string="Call method" type="object"/>' +
|
|
'<button name="4" string="Execute action" type="action"/>' +
|
|
"</header>" +
|
|
"<group>" +
|
|
'<field name="display_name"/>' +
|
|
'<field name="foo"/>' +
|
|
"</group>" +
|
|
"</form>",
|
|
"partner,3,form": `
|
|
<form>
|
|
<footer>
|
|
<button class="btn-primary" string="Save" special="save"/>
|
|
</footer>
|
|
</form>`,
|
|
"partner,666,form": `<form>
|
|
<header></header>
|
|
<sheet>
|
|
<div class="oe_button_box" name="button_box">
|
|
<button class="oe_stat_button" type="action" name="1" icon="fa-star" context="{'default_partner': active_id}">
|
|
<field string="Partners" name="o2m" widget="statinfo"/>
|
|
</button>
|
|
</div>
|
|
<field name="display_name"/>
|
|
</sheet>
|
|
</form>`,
|
|
"pony,false,form": "<form>" + '<field name="name"/>' + "</form>",
|
|
// search views
|
|
"partner,false,search": '<search><field name="foo" string="Foo"/></search>',
|
|
"partner,4,search":
|
|
"<search>" +
|
|
'<filter name="bar" help="Bar" domain="[(\'bar\', \'=\', 1)]"/>' +
|
|
"</search>",
|
|
"pony,false,search": "<search></search>",
|
|
};
|
|
const models = {
|
|
partner: {
|
|
fields: {
|
|
id: { string: "Id", type: "integer" },
|
|
foo: { string: "Foo", type: "char" },
|
|
bar: { string: "Bar", type: "many2one", relation: "partner" },
|
|
o2m: {
|
|
string: "One2Many",
|
|
type: "one2many",
|
|
relation: "partner",
|
|
relation_field: "bar",
|
|
},
|
|
m2o: { string: "Many2one", type: "many2one", relation: "partner" },
|
|
},
|
|
records: [
|
|
{ id: 1, display_name: "First record", foo: "yop", bar: 2, o2m: [2, 3], m2o: 3 },
|
|
{
|
|
id: 2,
|
|
display_name: "Second record",
|
|
foo: "blip",
|
|
bar: 1,
|
|
o2m: [1, 4, 5],
|
|
m2o: 3,
|
|
},
|
|
{ id: 3, display_name: "Third record", foo: "gnap", bar: 1, o2m: [], m2o: 1 },
|
|
{ id: 4, display_name: "Fourth record", foo: "plop", bar: 2, o2m: [], m2o: 1 },
|
|
{ id: 5, display_name: "Fifth record", foo: "zoup", bar: 2, o2m: [], m2o: 1 },
|
|
],
|
|
},
|
|
pony: {
|
|
fields: {
|
|
id: { string: "Id", type: "integer" },
|
|
name: { string: "Name", type: "char" },
|
|
},
|
|
records: [
|
|
{ id: 4, name: "Twilight Sparkle" },
|
|
{ id: 6, name: "Applejack" },
|
|
{ id: 9, name: "Fluttershy" },
|
|
],
|
|
},
|
|
};
|
|
return {
|
|
models,
|
|
views: archs,
|
|
actions,
|
|
menus,
|
|
};
|
|
}
|