[REF] web: convert many2manyattendee to owl

closes odoo/odoo#99676

Signed-off-by: Aaron Bohy (aab) <aab@odoo.com>
This commit is contained in:
FrancoisGe
2022-09-08 11:45:15 +02:00
committed by Aaron Bohy
parent 26444fcaef
commit 1b3630fcf2
5 changed files with 282 additions and 80 deletions
+1 -1
View File
@@ -50,7 +50,7 @@ If you need to manage your meetings, you should install the CRM module.
'calendar/static/src/js/calendar_model.js',
'calendar/static/src/js/calendar_view.js',
'calendar/static/src/js/services/calendar_notification_service.js',
'calendar/static/src/views/*',
'calendar/static/src/views/**/*',
],
'web.qunit_suite_tests': [
'calendar/static/tests/**/*',
@@ -0,0 +1,30 @@
/** @odoo-module **/
import { registry } from "@web/core/registry";
import { Many2ManyTagsAvatarField } from "@web/views/fields/many2many_tags_avatar/many2many_tags_avatar_field";
export class Many2ManyAttendee extends Many2ManyTagsAvatarField {
get tags() {
const { partner_ids: partnerIds } = this.props.record.preloadedData;
const tags = super.tags.map((tag) => {
const partner = partnerIds.find((partner) => tag.resId === partner.id);
if (partner) {
tag.className = `o_attendee_border o_attendee_border_${partner.status}`;
}
return tag;
});
const organizer = partnerIds.find((partner) => partner.is_organizer);
if (organizer) {
const orgId = organizer.id;
// sort elements according to the partner id
tags.sort((a, b) => {
const a_org = a.id === orgId;
return a_org ? -1 : 1;
});
}
return tags;
}
}
registry.category("fields").add("many2manyattendee", Many2ManyAttendee);
+121 -78
View File
@@ -1,86 +1,129 @@
/** @odoo-module **/
import FormView from 'web.FormView';
import testUtils from "web.test_utils";
import { getFixture } from "@web/../tests/helpers/utils";
import { makeView, setupViewRegistries } from "@web/../tests/views/helpers";
var createView = testUtils.createView;
let serverData;
let target;
QUnit.module('calendar', {
beforeEach: function () {
this.data = {
event: {
fields: {
partner_ids: {string: "Partners", type: "many2many", relation: "partner"},
QUnit.module(
"calendar",
{
beforeEach: function () {
target = getFixture();
serverData = {
models: {
event: {
fields: {
partner_ids: {
string: "Partners",
type: "many2many",
relation: "partner",
},
},
records: [
{
id: 14,
partner_ids: [1, 2],
},
],
},
partner: {
fields: {
name: { string: "Name", type: "char" },
},
records: [
{
id: 1,
name: "Jesus",
},
{
id: 2,
name: "Mahomet",
},
],
},
},
records: [{
id: 14,
partner_ids: [1, 2],
}],
},
partner: {
fields: {
name: {string: "Name", type: "char"},
},
records: [{
id: 1,
name: "Jesus",
}, {
id: 2,
name: "Mahomet",
}],
},
};
};
setupViewRegistries();
},
},
}, function () {
QUnit.test("many2manyattendee widget: basic rendering", async function (assert) {
assert.expect(12);
function () {
QUnit.test("Many2ManyAttendee: basic rendering", async function (assert) {
await makeView({
type: "form",
resModel: "event",
serverData,
resId: 14,
arch: `
<form>
<field name="partner_ids" widget="many2manyattendee"/>
</form>`,
mockRPC(route, args) {
if (args.method === "get_attendee_detail") {
assert.step(args.method);
assert.strictEqual(
args.model,
"res.partner",
"the method should only be called on res.partner"
);
assert.deepEqual(
args.args[0],
[1, 2],
"the partner ids should be passed as argument"
);
assert.deepEqual(
args.args[1],
[14],
"the event id should be passed as argument"
);
return Promise.resolve([
{ id: 1, name: "Jesus", status: "accepted", color: 0 },
{ id: 2, name: "Mahomet", status: "tentative", color: 0 },
]);
}
},
});
var form = await createView({
View: FormView,
model: 'event',
data: this.data,
res_id: 14,
arch:
'<form>' +
'<field name="partner_ids" widget="many2manyattendee"/>' +
'</form>',
mockRPC: function (route, args) {
if (args.method === 'get_attendee_detail') {
assert.strictEqual(args.model, 'res.partner',
"the method should only be called on res.partner");
assert.deepEqual(args.args[0], [1, 2],
"the partner ids should be passed as argument");
assert.deepEqual(args.args[1], [14],
"the event id should be passed as argument");
return Promise.resolve([
{id: 1, name: "Jesus", status: "accepted", color: 0},
{id: 2, name: "Mahomet", status: "tentative", color: 0},
]);
}
return this._super.apply(this, arguments);
},
assert.hasClass(
target.querySelector('.o_field_widget[name="partner_ids"] div'),
"o_field_tags"
);
assert.containsN(
target,
'.o_field_widget[name="partner_ids"] .badge',
2,
"there should be 2 tags"
);
const badges = target.querySelectorAll('.o_field_widget[name="partner_ids"] .badge');
assert.strictEqual(
badges[0].textContent.trim(),
"Jesus",
"the tag should be correctly named"
);
assert.hasClass(
badges[0].querySelector("img"),
"o_attendee_border_accepted",
"Jesus should attend the meeting"
);
assert.strictEqual(
badges[1].textContent.trim(),
"Mahomet",
"the tag should be correctly named"
);
assert.hasClass(
badges[1].querySelector("img"),
"o_attendee_border_tentative",
"Mohamet should still confirm his attendance to the meeting"
);
assert.containsOnce(badges[0], "img", "should have img tag");
assert.hasAttrValue(
badges[0].querySelector("img"),
"data-src",
"/web/image/partner/1/avatar_128",
"should have correct avatar image"
);
assert.verifySteps(["get_attendee_detail"]);
});
assert.hasClass(form.$('.o_field_widget[name="partner_ids"]'), 'o_field_many2manytags');
assert.containsN(form, '.o_field_widget[name="partner_ids"] .badge', 2,
"there should be 2 tags");
assert.strictEqual(form.$('.o_field_widget[name="partner_ids"] .badge:first').text().trim(), "Jesus",
"the tag should be correctly named");
assert.hasClass(form.$('.o_field_widget[name="partner_ids"] .badge:first img'),'o_attendee_border_accepted',
"Jesus should attend the meeting");
assert.strictEqual(form.$('.o_field_widget[name="partner_ids"] .badge[data-id="2"]').text().trim(), "Mahomet",
"the tag should be correctly named");
assert.hasClass(form.el.querySelector('.o_field_widget[name="partner_ids"] .badge[data-id="2"] img'), 'o_attendee_border_tentative',
"Mohamet should still confirm his attendance to the meeting");
assert.hasClass(form.el.querySelector('.o_field_many2manytags'), 'avatar',
"should have avatar class");
assert.containsOnce(form, '.o_field_many2manytags.avatar.o_field_widget .badge:first img',
"should have img tag");
assert.hasAttrValue(form.$('.o_field_many2manytags.avatar.o_field_widget .badge:first img'),
'data-src',
'/web/image/partner/1/avatar_128',
"should have correct avatar image");
form.destroy();
});
});
}
);
@@ -0,0 +1,129 @@
/** @odoo-module **/
import FormView from "web.FormView";
import testUtils from "web.test_utils";
var createView = testUtils.createView;
QUnit.module(
"Legacy calendar",
{
beforeEach: function () {
this.data = {
event: {
fields: {
partner_ids: { string: "Partners", type: "many2many", relation: "partner" },
},
records: [
{
id: 14,
partner_ids: [1, 2],
},
],
},
partner: {
fields: {
name: { string: "Name", type: "char" },
},
records: [
{
id: 1,
name: "Jesus",
},
{
id: 2,
name: "Mahomet",
},
],
},
};
},
},
function () {
QUnit.test("many2manyattendee widget: basic rendering", async function (assert) {
assert.expect(12);
var form = await createView({
View: FormView,
model: "event",
data: this.data,
res_id: 14,
debug: 1,
arch:
"<form>" + '<field name="partner_ids" widget="many2manyattendee"/>' + "</form>",
mockRPC: function (route, args) {
if (args.method === "get_attendee_detail") {
assert.strictEqual(
args.model,
"res.partner",
"the method should only be called on res.partner"
);
assert.deepEqual(
args.args[0],
[1, 2],
"the partner ids should be passed as argument"
);
assert.deepEqual(
args.args[1],
[14],
"the event id should be passed as argument"
);
return Promise.resolve([
{ id: 1, name: "Jesus", status: "accepted", color: 0 },
{ id: 2, name: "Mahomet", status: "tentative", color: 0 },
]);
}
return this._super.apply(this, arguments);
},
});
assert.hasClass(form.$('.o_field_widget[name="partner_ids"]'), "o_field_many2manytags");
assert.containsN(
form,
'.o_field_widget[name="partner_ids"] .badge',
2,
"there should be 2 tags"
);
assert.strictEqual(
form.$('.o_field_widget[name="partner_ids"] .badge:first').text().trim(),
"Jesus",
"the tag should be correctly named"
);
assert.hasClass(
form.$('.o_field_widget[name="partner_ids"] .badge:first img'),
"o_attendee_border_accepted",
"Jesus should attend the meeting"
);
assert.strictEqual(
form.$('.o_field_widget[name="partner_ids"] .badge[data-id="2"]').text().trim(),
"Mahomet",
"the tag should be correctly named"
);
assert.hasClass(
form.el.querySelector(
'.o_field_widget[name="partner_ids"] .badge[data-id="2"] img'
),
"o_attendee_border_tentative",
"Mohamet should still confirm his attendance to the meeting"
);
assert.hasClass(
form.el.querySelector(".o_field_many2manytags"),
"avatar",
"should have avatar class"
);
assert.containsOnce(
form,
".o_field_many2manytags.avatar.o_field_widget .badge:first img",
"should have img tag"
);
assert.hasAttrValue(
form.$(".o_field_many2manytags.avatar.o_field_widget .badge:first img"),
"data-src",
"/web/image/partner/1/avatar_128",
"should have correct avatar image"
);
form.destroy();
});
}
);
@@ -4,7 +4,7 @@
<t t-name="web.TagsList" owl="1">
<t t-foreach="visibleTags" t-as="tag" t-key="tag.id or tag_index">
<span t-attf-class="{{`o_tag_color_${ tag.colorIndex or 0 } ${props.displayBadge ? 'badge rounded-pill' : ''}`}} o_tag d-inline-flex align-items-center h-100" tabindex="-1" t-att-data-color="tag.colorIndex" t-att-title="tag.text" t-on-click="(ev) => tag.onClick and tag.onClick(ev)" t-on-keydown="tag.onKeydown">
<img t-if="tag.img" t-att-src="tag.img" class="o_m2m_avatar rounded-circle"/>
<img t-if="tag.img" t-att-src="tag.img" class="o_m2m_avatar rounded-circle" t-att-class="tag.className"/>
<div t-if="props.displayBadge" class="o_tag_badge_text" t-esc="tag.text" />
<t t-else="">
<span />