[IMP] web: add the avatar icon on m2o/m2m_avatar_field autocomplete
The goal of this commit is to add the avatar when a user use the autocomplete m2o/m2m_autocomplete liked to a m2o/m2m_avatar_field. Task-id: 3121207 Part-of: odoo/odoo#114400
This commit is contained in:
@@ -18,3 +18,10 @@
|
||||
color: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
.o_avatar_many2x_autocomplete > img{
|
||||
width: 19px;
|
||||
height: 19px;
|
||||
object-fit: cover;
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
+3
-12
@@ -3,18 +3,18 @@
|
||||
import { isMobileOS } from "@web/core/browser/feature_detection";
|
||||
import { usePopover } from "@web/core/popover/popover_hook";
|
||||
import { registry } from "@web/core/registry";
|
||||
import { Many2XAutocomplete } from "@web/views/fields/relational_utils";
|
||||
import {
|
||||
many2ManyTagsField,
|
||||
Many2ManyTagsField,
|
||||
} from "@web/views/fields/many2many_tags/many2many_tags_field";
|
||||
import { TagsList } from "../many2many_tags/tags_list";
|
||||
import { onMounted, useRef, useState } from "@odoo/owl";
|
||||
import { onMounted, useState } from "@odoo/owl";
|
||||
import { AvatarMany2XAutocomplete } from "@web/views/fields/relational_utils";
|
||||
|
||||
export class Many2ManyTagsAvatarField extends Many2ManyTagsField {
|
||||
static template = "web.Many2ManyTagsAvatarField";
|
||||
static components = {
|
||||
Many2XAutocomplete,
|
||||
Many2XAutocomplete: AvatarMany2XAutocomplete,
|
||||
TagsList,
|
||||
};
|
||||
static props = {
|
||||
@@ -100,7 +100,6 @@ export class KanbanMany2ManyTagsAvatarFieldTagsList extends TagsList {
|
||||
setup() {
|
||||
super.setup();
|
||||
this.popover = usePopover();
|
||||
this.emptyAvatar = useRef("emptyAvatar");
|
||||
}
|
||||
get visibleTagsCount() {
|
||||
return this.props.itemsVisible;
|
||||
@@ -116,8 +115,6 @@ export class KanbanMany2ManyTagsAvatarFieldTagsList extends TagsList {
|
||||
if (this.closePopoverFn) {
|
||||
this.closePopover();
|
||||
}
|
||||
this.emptyAvatar.el?.dispatchEvent(new MouseEvent("mouseleave"));
|
||||
this.emptyAvatar.el?.removeAttribute("data-tooltip-template");
|
||||
this.closePopoverFn = this.popover.add(
|
||||
ev.currentTarget.parentElement,
|
||||
Many2ManyTagsAvatarFieldPopover,
|
||||
@@ -130,12 +127,6 @@ export class KanbanMany2ManyTagsAvatarFieldTagsList extends TagsList {
|
||||
},
|
||||
{
|
||||
position: "bottom",
|
||||
onClose: () => {
|
||||
this.emptyAvatar.el?.setAttribute(
|
||||
"data-tooltip-template",
|
||||
"web.TagsList.Tooltip"
|
||||
);
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
-1
@@ -31,7 +31,6 @@
|
||||
t-on-click.stop.prevent="openPopover" class="o_m2m_avatar rounded-circle align-self-center"/>
|
||||
</xpath>
|
||||
<xpath expr="//span[hasclass('o_m2m_avatar_empty')]" position="attributes">
|
||||
<attribute name="t-ref">emptyAvatar</attribute>
|
||||
<attribute name="t-on-click.stop.prevent">openPopover</attribute>
|
||||
</xpath>
|
||||
<xpath expr="//span[@t-att-title='tag.text']" position="attributes">
|
||||
|
||||
@@ -6,6 +6,7 @@ import { usePopover } from "@web/core/popover/popover_hook";
|
||||
import { many2OneField, Many2OneField } from "../many2one/many2one_field";
|
||||
|
||||
import { Component, onMounted } from "@odoo/owl";
|
||||
import { AvatarMany2XAutocomplete } from "@web/views/fields/relational_utils";
|
||||
|
||||
export class Many2OneAvatarField extends Component {
|
||||
static template = "web.Many2OneAvatarField";
|
||||
@@ -32,12 +33,14 @@ export const many2OneAvatarField = {
|
||||
...many2OneField,
|
||||
component: Many2OneAvatarField,
|
||||
};
|
||||
|
||||
export class Many2OneFieldPopover extends Many2OneField {
|
||||
static props = {
|
||||
...Many2OneField.props,
|
||||
close: { type: Function },
|
||||
};
|
||||
static components = {
|
||||
Many2XAutocomplete: AvatarMany2XAutocomplete,
|
||||
};
|
||||
setup() {
|
||||
super.setup();
|
||||
onMounted(() => this.focusInput());
|
||||
|
||||
@@ -226,6 +226,12 @@ export class Many2XAutocomplete extends Component {
|
||||
this.props.update([record], params);
|
||||
}
|
||||
|
||||
mapRecordToOption(result) {
|
||||
return {
|
||||
value: result[0],
|
||||
label: result[1].split("\n")[0],
|
||||
};
|
||||
}
|
||||
async loadOptionsSource(request) {
|
||||
if (this.lastProm) {
|
||||
this.lastProm.abort(false);
|
||||
@@ -239,10 +245,7 @@ export class Many2XAutocomplete extends Component {
|
||||
});
|
||||
const records = await this.lastProm;
|
||||
|
||||
const options = records.map((result) => ({
|
||||
value: result[0],
|
||||
label: result[1].split("\n")[0],
|
||||
}));
|
||||
const options = records.map((result) => this.mapRecordToOption(result));
|
||||
|
||||
if (this.props.quickCreate && request.length) {
|
||||
options.push({
|
||||
@@ -383,6 +386,21 @@ Many2XAutocomplete.defaultProps = {
|
||||
context: {},
|
||||
};
|
||||
|
||||
export class AvatarMany2XAutocomplete extends Many2XAutocomplete {
|
||||
mapRecordToOption(result) {
|
||||
return {
|
||||
...super.mapRecordToOption(result),
|
||||
resModel: this.props.resModel,
|
||||
};
|
||||
}
|
||||
get optionsSource() {
|
||||
return {
|
||||
...super.optionsSource,
|
||||
optionTemplate: "web.AvatarMany2XAutocomplete",
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export function useOpenMany2XRecord({
|
||||
resModel,
|
||||
onRecordSaved,
|
||||
|
||||
@@ -57,4 +57,12 @@
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<t t-name="web.AvatarMany2XAutocomplete" owl="1">
|
||||
<span class="o_avatar_many2x_autocomplete">
|
||||
<img t-if="option.value" class="rounded-circle"
|
||||
t-attf-src="/web/image/{{option.resModel}}/{{option.value}}/avatar_128" />
|
||||
<t t-esc="option.label" />
|
||||
</span>
|
||||
</t>
|
||||
|
||||
</templates>
|
||||
|
||||
Reference in New Issue
Block a user