Skip to content

Commit 8910e0a

Browse files
committed
[FIX] mail: arrange the attachment in chronological order
Before to this commit: Non-image attachments that were uploaded were consistently displayed after image attachments. This arrangement occurred because, in the preparation of the attachment list template, image attachments were placed first, followed by non-image attachments, even if the non-image attachement were uploaded earlier. After this commit: The attachment list now arranges attachments based on their order in the 'props.attachments' object, regardless of whether they are non-image or image attachments. closes odoo#146776 Signed-off-by: Sébastien Theys (seb) <[email protected]>
1 parent 34a7669 commit 8910e0a

File tree

2 files changed

+75
-91
lines changed

2 files changed

+75
-91
lines changed

addons/mail/static/src/core/common/attachment_list.js

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -26,20 +26,6 @@ export class AttachmentList extends Component {
2626
this.fileViewer = useFileViewer();
2727
}
2828

29-
/**
30-
* @return {import("models").Attachment[]}
31-
*/
32-
get nonImagesAttachments() {
33-
return this.props.attachments.filter((attachment) => !attachment.isImage);
34-
}
35-
36-
/**
37-
* @return {import("models").Attachment[]}
38-
*/
39-
get imagesAttachments() {
40-
return this.props.attachments.filter((attachment) => attachment.isImage);
41-
}
42-
4329
/**
4430
* @param {import("models").Attachment} attachment
4531
*/

addons/mail/static/src/core/common/attachment_list.xml

Lines changed: 75 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -10,89 +10,87 @@
1010
'ms-2 ps-4': isInChatWindowAndIsAlignedRight and !env.inComposer,
1111
}"
1212
>
13-
<div class="d-flex flex-grow-1 flex-wrap mx-1" t-att-class="{
13+
<div class="d-flex flex-grow-1 flex-wrap mx-1 align-items-center" t-att-class="{
1414
'justify-content-end': isInChatWindowAndIsAlignedRight and !env.inComposer,
15-
}" role="menu">
16-
<div t-foreach="imagesAttachments" t-as="attachment" t-key="attachment.id" t-att-aria-label="attachment.filename"
17-
class="o-mail-AttachmentImage d-flex position-relative flex-shrink-0 mw-100 mb-1 me-1"
18-
t-att-title="attachment.name"
19-
t-att-class="{ 'o-isUploading': attachment.uploading }"
20-
tabindex="0"
21-
aria-label="View image"
22-
role="menuitem"
23-
t-att-data-mimetype="attachment.mimetype"
24-
t-on-click="() => this.fileViewer.open(attachment, props.attachments)"
25-
>
26-
<img
27-
class="img img-fluid my-0 mx-auto o-viewable"
28-
t-att-class="{ 'opacity-25': attachment.uploading }"
29-
t-att-src="getImageUrl(attachment)"
30-
t-att-alt="attachment.name"
31-
t-attf-style="max-width: min(100%, {{ imagesWidth }}px); max-height: {{ props.imagesHeight }}px;"
32-
t-on-load="onImageLoaded"
33-
/>
34-
<div t-if="attachment.uploading" class="position-absolute top-0 bottom-0 start-0 end-0 d-flex align-items-center justify-content-center" title="Uploading">
35-
<i class="fa fa-spin fa-spinner"/>
36-
</div>
37-
<div class="position-absolute top-0 bottom-0 start-0 end-0 p-2 text-white opacity-0 opacity-100-hover d-flex align-items-end flax-wrap flex-column">
38-
<div t-if="showDelete and !ui.isSmall"
39-
class="btn btn-sm btn-dark rounded opacity-75 opacity-100-hover"
40-
tabindex="0" aria-label="Remove" role="menuitem" t-on-click.stop="() => this.onClickUnlink(attachment)" title="Remove">
41-
<i class="fa fa-trash"/>
15+
}" role="menu" >
16+
<t t-foreach="this.props.attachments" t-as="attachment" t-key="attachment.id">
17+
<div t-if="attachment.isImage"
18+
t-att-aria-label="attachment.filename"
19+
class="o-mail-AttachmentImage d-flex position-relative flex-shrink-0 mw-100 mb-1 me-1"
20+
t-att-title="attachment.name"
21+
t-att-class="{ 'o-isUploading': attachment.uploading }"
22+
tabindex="0"
23+
t-att-data-mimetype="attachment.mimetype"
24+
t-on-click="() => this.fileViewer.open(attachment, props.attachments)"
25+
role="menuitem"
26+
>
27+
<img
28+
class="img img-fluid my-0 mx-auto o-viewable"
29+
t-att-class="{ 'opacity-25': attachment.uploading }"
30+
t-att-src="getImageUrl(attachment)"
31+
t-att-alt="attachment.name"
32+
t-attf-style="max-width: min(100%, {{ imagesWidth }}px); max-height: {{ props.imagesHeight }}px;"
33+
t-on-load="onImageLoaded"
34+
/>
35+
<div t-if="attachment.uploading" class="position-absolute top-0 bottom-0 start-0 end-0 d-flex align-items-center justify-content-center" title="Uploading">
36+
<i class="fa fa-spin fa-spinner"/>
4237
</div>
43-
<div t-if="canDownload(attachment) and !ui.isSmall" class="btn btn-sm btn-dark rounded opacity-75 opacity-100-hover mt-auto" t-on-click.stop="() => this.onClickDownload(attachment)" title="Download">
44-
<i class="fa fa-download"/>
38+
<div class="position-absolute top-0 bottom-0 start-0 end-0 p-2 text-white opacity-0 opacity-100-hover d-flex align-items-end flax-wrap flex-column">
39+
<div t-if="showDelete and !ui.isSmall"
40+
class="btn btn-sm btn-dark rounded opacity-75 opacity-100-hover"
41+
tabindex="0" aria-label="Remove" role="menuitem" t-on-click.stop="() => this.onClickUnlink(attachment)" title="Remove">
42+
<i class="fa fa-trash"/>
43+
</div>
44+
<div t-if="canDownload(attachment) and !ui.isSmall" class="btn btn-sm btn-dark rounded opacity-75 opacity-100-hover mt-auto" t-on-click.stop="() => this.onClickDownload(attachment)" title="Download">
45+
<i class="fa fa-download"/>
46+
</div>
4547
</div>
4648
</div>
47-
</div>
48-
</div>
49-
<div class="d-flex flex-grow-1 flex-wrap mt-1 mx-1" t-att-class="{
50-
'justify-content-end': isInChatWindowAndIsAlignedRight and !env.inComposer,
51-
}">
52-
<!-- t-attf-class overridden in extensions -->
53-
<div t-foreach="nonImagesAttachments" t-as="attachment" t-key="attachment.id"
54-
class="o-mail-AttachmentCard d-flex rounded mb-1 me-1 mw-100 overflow-auto"
55-
t-att-class="{
56-
'ms-1': isInChatWindowAndIsAlignedRight,
57-
'me-1': !isInChatWindowAndIsAlignedRight,
58-
'o-viewable': attachment.isViewable,
59-
'o-isUploading': attachment.uploading,
60-
}"
61-
t-attf-class="bg-300"
62-
t-att-title="attachment.name ? attachment.name : undefined" role="menu" t-att-aria-label="attachment.name"
63-
t-on-click="() => this.fileViewer.open(attachment, props.attachments)"
64-
>
65-
<!-- o_image from mimetype.scss -->
66-
<t t-ref="nonImageMain">
67-
<div class="o-mail-AttachmentCard-image o_image flex-shrink-0 m-1" role="menuitem" aria-label="Preview" t-att-tabindex="-1" t-att-aria-disabled="false" t-att-data-mimetype="attachment.mimetype"/>
68-
<div class="overflow-auto d-flex justify-content-center flex-column px-1">
69-
<div t-if="attachment.name" class="text-truncate" t-out="props.messageSearch?.highlight(attachment.name) ?? attachment.name"/>
70-
<small t-if="attachment.extension" class="text-uppercase" t-esc="attachment.extension"/>
71-
</div>
72-
</t>
73-
<div class="o-mail-AttachmentCard-aside position-relative rounded-end overflow-hidden" t-att-class="{ 'o-hasMultipleActions d-flex flex-column': attachment.isDeletable and !env.inComposer }">
74-
<div t-if="attachment.uploading" class="d-flex justify-content-center align-items-center w-100 h-100" title="Uploading">
75-
<i class="fa fa-spin fa-spinner"/>
76-
</div>
77-
<div t-if="!attachment.uploading and env.inComposer" class="d-flex justify-content-center align-items-center w-100 h-100 text-primary" title="Uploaded">
78-
<i class="fa fa-check"/>
49+
<!-- t-attf-class overridden in extensions -->
50+
<div t-else=""
51+
class="o-mail-AttachmentCard d-flex rounded mb-1 me-1 mw-100 overflow-auto"
52+
t-att-class="{
53+
'ms-1': isInChatWindowAndIsAlignedRight,
54+
'me-1': !isInChatWindowAndIsAlignedRight,
55+
'o-viewable': attachment.isViewable,
56+
'o-isUploading': attachment.uploading,
57+
}"
58+
t-attf-class="bg-300"
59+
t-att-title="attachment.name ? attachment.name : undefined" role="menu" t-att-aria-label="attachment.name"
60+
t-on-click="() => this.fileViewer.open(attachment, props.attachments)"
61+
>
62+
<!-- o_image from mimetype.scss -->
63+
<t t-ref="nonImageMain">
64+
<div class="o-mail-AttachmentCard-image o_image flex-shrink-0 m-1" role="menuitem" aria-label="Preview" t-att-tabindex="-1" t-att-aria-disabled="false" t-att-data-mimetype="attachment.mimetype"/>
65+
<div class="overflow-auto d-flex justify-content-center flex-column px-1">
66+
<div t-if="attachment.name" class="text-truncate" t-out="props.messageSearch?.highlight(attachment.name) ?? attachment.name"/>
67+
<small t-if="attachment.extension" class="text-uppercase" t-esc="attachment.extension"/>
68+
</div>
69+
</t>
70+
<div class="o-mail-AttachmentCard-aside position-relative rounded-end overflow-hidden" t-att-class="{ 'o-hasMultipleActions d-flex flex-column': attachment.isDeletable and !env.inComposer }">
71+
<div t-if="attachment.uploading" class="d-flex justify-content-center align-items-center w-100 h-100" title="Uploading">
72+
<i class="fa fa-spin fa-spinner"/>
73+
</div>
74+
<div t-if="!attachment.uploading and env.inComposer" class="d-flex justify-content-center align-items-center w-100 h-100 text-primary" title="Uploaded">
75+
<i class="fa fa-check"/>
76+
</div>
77+
<button t-if="showDelete"
78+
class="o-mail-AttachmentCard-unlink btn top-0 justify-content-center align-items-center d-flex w-100 h-100 rounded-0 border-0"
79+
t-attf-class="{{ env.inComposer ? 'o-inComposer position-absolute btn-primary transition-base' : 'bg-300' }}"
80+
t-on-click.stop="() => this.onClickUnlink(attachment)" title="Remove"
81+
>
82+
<i class="fa fa-trash" role="img" aria-label="Remove"/>
83+
</button>
84+
<!-- t-attf-class overridden in extensions -->
85+
<button t-if="canDownload(attachment)" class="btn d-flex justify-content-center align-items-center w-100 h-100 rounded-0"
86+
t-attf-class="bg-300"
87+
t-on-click.stop="() => this.onClickDownload(attachment)" title="Download"
88+
>
89+
<i class="fa fa-download" role="img" aria-label="Download"/>
90+
</button>
7991
</div>
80-
<button t-if="showDelete"
81-
class="o-mail-AttachmentCard-unlink btn top-0 justify-content-center align-items-center d-flex w-100 h-100 rounded-0 border-0"
82-
t-attf-class="{{ env.inComposer ? 'o-inComposer position-absolute btn-primary transition-base' : 'bg-300' }}"
83-
t-on-click.stop="() => this.onClickUnlink(attachment)" title="Remove"
84-
>
85-
<i class="fa fa-trash" role="img" aria-label="Remove"/>
86-
</button>
87-
<!-- t-attf-class overridden in extensions -->
88-
<button t-if="canDownload(attachment)" class="btn d-flex justify-content-center align-items-center w-100 h-100 rounded-0"
89-
t-attf-class="bg-300"
90-
t-on-click.stop="() => this.onClickDownload(attachment)" title="Download"
91-
>
92-
<i class="fa fa-download" role="img" aria-label="Download"/>
93-
</button>
9492
</div>
95-
</div>
93+
</t>
9694
</div>
9795
</div>
9896
</t>

0 commit comments

Comments
 (0)