Eliminate Python dependency: embed frontend assets in odoo-go
- Copy all OWL frontend assets (JS/CSS/XML/fonts/images) into frontend/ directory (2925 files, 43MB) — no more runtime reads from Python Odoo - Replace OdooAddonsPath config with FrontendDir pointing to local frontend/ - Rewire bundle.go, static.go, templates.go, webclient.go to read from frontend/ instead of external Python Odoo addons directory - Auto-detect frontend/ and build/ dirs relative to binary in main.go - Delete obsolete Python helper scripts (tools/*.py) The Go server is now fully self-contained: single binary + frontend/ folder. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
import { fields, models } from "@web/../tests/web_test_helpers";
|
||||
|
||||
export class FakeUser extends models.Model {
|
||||
_name = "fake.user";
|
||||
|
||||
name = fields.Char({ string: "Name" });
|
||||
lang = fields.Char({ string: "Lang" });
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
import { models, fields } from "@web/../tests/web_test_helpers";
|
||||
|
||||
export class HrDepartment extends models.ServerModel {
|
||||
_name = "hr.department";
|
||||
_rec_name = "complete_name";
|
||||
|
||||
name = fields.Char();
|
||||
complete_name = fields.Char({
|
||||
compute: "_compute_complete_name",
|
||||
});
|
||||
display_name = fields.Char({
|
||||
compute: "_compute_display_name",
|
||||
});
|
||||
|
||||
_compute_complete_name() {
|
||||
for (const department of this) {
|
||||
department.complete_name = department.name;
|
||||
}
|
||||
}
|
||||
|
||||
_compute_display_name() {
|
||||
this._compute_complete_name();
|
||||
for (const department of this) {
|
||||
department.display_name = department.complete_name;
|
||||
}
|
||||
}
|
||||
|
||||
get _to_store_defaults() {
|
||||
return ["name"];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import { fields, models } from "@web/../tests/web_test_helpers";
|
||||
import { mailDataHelpers } from "@mail/../tests/mock_server/mail_mock_server";
|
||||
|
||||
export class HrEmployee extends models.ServerModel {
|
||||
_name = "hr.employee";
|
||||
|
||||
department_id = fields.Many2one({ relation: "hr.department" });
|
||||
work_email = fields.Char();
|
||||
work_phone = fields.Char();
|
||||
work_location_type = fields.Char();
|
||||
work_location_id = fields.Many2one({ relation: "hr.work.location" });
|
||||
job_title = fields.Char();
|
||||
|
||||
_get_store_avatar_card_fields() {
|
||||
return [
|
||||
"company_id",
|
||||
mailDataHelpers.Store.one("department_id", ["name"]),
|
||||
"work_email",
|
||||
mailDataHelpers.Store.one("work_location_id", ["location_type", "name"]),
|
||||
"work_phone",
|
||||
"job_title",
|
||||
];
|
||||
}
|
||||
|
||||
_views = {
|
||||
search: `<search><field name="display_name" string="Name" /></search>`,
|
||||
list: `<list><field name="display_name"/></list>`,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import { models } from "@web/../tests/web_test_helpers";
|
||||
|
||||
export class HrEmployeePublic extends models.ServerModel {
|
||||
_name = "hr.employee.public";
|
||||
|
||||
_views = {
|
||||
search: `<search><field name="display_name" string="Name" /></search>`,
|
||||
list: `<list><field name="display_name"/></list>`,
|
||||
};
|
||||
}
|
||||
10
frontend/hr/static/tests/mock_server/mock_models/hr_job.js
Normal file
10
frontend/hr/static/tests/mock_server/mock_models/hr_job.js
Normal file
@@ -0,0 +1,10 @@
|
||||
import { models } from "@web/../tests/web_test_helpers";
|
||||
|
||||
export class HrJob extends models.ServerModel {
|
||||
_name = "hr.job";
|
||||
|
||||
_views = {
|
||||
search: `<search><field name="display_name" string="Name" /></search>`,
|
||||
list: `<list><field name="display_name"/></list>`,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import { models } from "@web/../tests/web_test_helpers";
|
||||
|
||||
export class HrVersion extends models.ServerModel {
|
||||
_name = "hr.version";
|
||||
|
||||
_views = {
|
||||
search: `<search><field name="display_name" string="Name" /></search>`,
|
||||
list: `<list><field name="display_name"/></list>`,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import { models, fields } from "@web/../tests/web_test_helpers";
|
||||
|
||||
export class HrWorkLocation extends models.ServerModel {
|
||||
_name = "hr.work.location";
|
||||
|
||||
name = fields.Char();
|
||||
location_type = fields.Selection({
|
||||
selection: [
|
||||
["office", "Office"],
|
||||
["home", "Home"],
|
||||
["other", "Other"],
|
||||
],
|
||||
});
|
||||
|
||||
_views = {
|
||||
search: `<search><field name="display_name" string="Name" /></search>`,
|
||||
list: `<list><field name="display_name"/></list>`,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
import { fields, models } from "@web/../tests/web_test_helpers";
|
||||
|
||||
export class M2xAvatarEmployee extends models.Model {
|
||||
_name = "m2x.avatar.employee";
|
||||
|
||||
employee_id = fields.Many2one({ string: "Employee", relation: "hr.employee.public" });
|
||||
employee_ids = fields.Many2many({ string: "Employees", relation: "hr.employee.public" });
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import { mailModels } from "@mail/../tests/mail_test_helpers";
|
||||
import { fields, makeKwArgs } from "@web/../tests/web_test_helpers";
|
||||
import { mailDataHelpers } from "@mail/../tests/mock_server/mail_mock_server";
|
||||
|
||||
export class ResPartner extends mailModels.ResPartner {
|
||||
employee_ids = fields.One2many({
|
||||
relation: "hr.employee",
|
||||
inverse: "work_contact_id",
|
||||
});
|
||||
|
||||
_get_store_avatar_card_fields() {
|
||||
return [
|
||||
...super._get_store_avatar_card_fields(),
|
||||
mailDataHelpers.Store.many(
|
||||
"employee_ids",
|
||||
makeKwArgs({
|
||||
fields: this.env["hr.employee"]._get_store_avatar_card_fields(),
|
||||
mode: "ADD",
|
||||
})
|
||||
),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
import { mailModels } from "@mail/../tests/mail_test_helpers";
|
||||
import { fields } from "@web/../tests/web_test_helpers";
|
||||
|
||||
export class ResUsers extends mailModels.ResUsers {
|
||||
employee_id = fields.Many2one({ relation: "hr.employee" });
|
||||
employee_ids = fields.One2many({
|
||||
relation: "hr.employee",
|
||||
inverse: "user_id",
|
||||
});
|
||||
department_id = fields.Many2one({
|
||||
related: "employee_id.department_id",
|
||||
relation: "hr.department",
|
||||
});
|
||||
work_email = fields.Char({ related: "employee_id.work_email" });
|
||||
work_phone = fields.Char({ related: "employee_id.work_phone" });
|
||||
work_location_type = fields.Char({ related: "employee_id.work_location_type" });
|
||||
work_location_id = fields.Many2one({
|
||||
related: "employee_id.work_location_id",
|
||||
relation: "hr.work.location",
|
||||
});
|
||||
job_title = fields.Char({ related: "employee_id.job_title" });
|
||||
}
|
||||
12
frontend/hr/static/tests/mock_server/mock_server.js
Normal file
12
frontend/hr/static/tests/mock_server/mock_server.js
Normal file
@@ -0,0 +1,12 @@
|
||||
import { onRpc } from "@web/../tests/web_test_helpers";
|
||||
|
||||
onRpc("get_avatar_card_data", function getAvatarCardData({ args }) {
|
||||
const resourceId = args[0][0];
|
||||
const resources = this.env["hr.employee.public"].search_read([["id", "=", resourceId]]);
|
||||
return resources.map((resource) => ({
|
||||
name: resource.name,
|
||||
work_email: resource.work_email,
|
||||
phone: resource.phone,
|
||||
user_id: resource.user_id,
|
||||
}));
|
||||
});
|
||||
Reference in New Issue
Block a user