Skip to content
Snippets Groups Projects
Commit 6e12372f authored by stefanorigano's avatar stefanorigano Committed by Géry Debongnie
Browse files

[IMP] mail: attachments list design

With this commit, the attachments displayed in a thread (typically a
chatter) are properly styled.
parent 3820b56c
Branches
Tags
No related merge requests found
......@@ -132,6 +132,13 @@ var Thread = Widget.extend({
} else {
msg.display_author = !options.squash_close_messages;
}
if (msg.attachment_ids) {
var sortedAttachments = _.partition(msg.attachment_ids, function (att) {
return att.mimetype && att.mimetype.split('/')[0] === 'image';
});
msg.images = sortedAttachments[0];
msg.others = sortedAttachments[1];
}
prev_msg = msg;
});
......
......@@ -230,106 +230,164 @@
// Attachment Icons (common for chat thread and chat composer)
// ------------------------------------------------------------------
@-webkit-keyframes oe_mail_attach_loading_anim {
0% { background: @odoo-brand-optional }
50% { background: darken(@odoo-brand-optional, 10%) }
100% { background: @odoo-brand-optional }
}
@-moz-keyframes oe_mail_attach_loading_anim {
0% { background: @odoo-brand-optional }
50% { background: darken(@odoo-brand-optional, 10%) }
100% { background: @odoo-brand-optional }
}
@-o-keyframes oe_mail_attach_loading_anim {
0% { background: @odoo-brand-optional }
50% { background: darken(@odoo-brand-optional, 10%) }
100% { background: @odoo-brand-optional }
}
@keyframes oe_mail_attach_loading_anim {
0% { background: @odoo-brand-optional }
50% { background: darken(@odoo-brand-optional, 10%) }
100% { background: @odoo-brand-optional }
@o-mail-attachment-image-size: 38px;
@o-mail-attachment-margin: 5px;
.o_attachments_list, .o_attachments_previews {
margin: 0 -@o-mail-attachment-margin 0;
.o-flex-display();
.o-flex-flow(row, wrap);
}
@o-mail-attachment-image-size: 100px;
.o_attachment {
position: relative;
vertical-align: top;
display: inline-block;
text-align: center;
width: @o-mail-attachment-image-size;
margin: 5px;
.o_image_box {
width: 100%;
padding: @o-mail-attachment-margin;
@media (min-width: @screen-sm-min) {
width: 50%;
}
@media (min-width: @screen-md-min) {
width: percentage(1/4);
}
.o_attachment_wrap {
overflow: hidden;
position: relative;
img {
width: @o-mail-attachment-image-size;
height: @o-mail-attachment-image-size;
image-orientation: from-image; // Only supported in Firefox
}
.o_image_overlay{
display: none;
}
&:hover .o_image_overlay {
display: block;
.o-position-absolute(@top: 0, @left: 0, @right:0, @bottom:0);
z-index: 20;
background: rgba(0, 0, 0, 0.5);
overflow: hidden;
cursor: pointer;
.o_attachment_download {
.o-position-absolute(@left: 10px, @bottom:5px);
}
.o_attachment_play {
.o-position-absolute(@top: 50%, @left: 50%);
transform: translate(-50%, -50%);
}
.o_overlay_download {
width: 100%;
height: 100%;
}
i {
color: #FFFFFF;
}
border-bottom: 1px solid fade(black, 10%);
border-radius: 2px;
padding: 4px 6px 0 4px;
background-color: fade(black, 5%);
}
&.o_attachment_editable .o_attachment_wrap {
padding-right: 40px;
}
.o_image {
.square(@o-mail-attachment-image-size);
image-orientation: from-image; // Only supported in Firefox
&.o_hover {
.o-hover-opacity(@default-opacity: 1, @hover-opacity: 0.7);
}
}
.o_attachment_view {
cursor: zoom-in;
}
.caption {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
padding: 5px;
.o-text-overflow(block);
a {
color: @odoo-main-text-color;
.o-hover-text-color(@default-color: @odoo-main-text-color, @hover-color: @headings-color);
}
}
.o_attachment_progress_bar {
display: none;
}
.o_attachment_uploaded, .o_attachment_delete {
.o-position-absolute(0,0,0, @left: auto);
.o-flex-display();
.o-align-items(center);
.o-justify-content(center);
width: 45px;
}
.o_attachment_delete {
.o-position-absolute(@top: -10px, @right: -8px);
color: @odoo-main-text-color;
background: desaturate(@brand-primary, 50%);
color: white;
cursor: pointer;
opacity: 0;
.o-transition(opacity, 0.2s, linear);
font-size: 20px;
.o-transform(translateX(100%));
.o-transition(all, 0.3s);
&:hover {
background: @brand-primary;
}
}
&.o_attachment_uploading {
.o_attachment_progress_bar {
display: block;
.o-position-absolute(@top: 18px, @left: 16px, @right: 16px);
height: 17px;
line-height: 13px;
color: white;
border-radius: @border-radius-base;
border: solid 1px grey;
box-shadow: 0px 1px 10px @odoo-shadow-color;
.o-animation(@name: oe_mail_attach_loading_anim, @duration: 1s, @timing-function: linear, @iteration-count: infinite);
display: inline-block;
margin: 0 0 0 8px;
border-radius: 2px;
vertical-align: bottom;
> div {
font-size: 11px;
padding: 0 7px;
}
}
.o_attachment_delete {
.o_attachment_delete, .o_attachment_uploaded {
display: none;
}
}
&:hover .o_attachment_delete {
opacity: 1;
.o-transition(opacity, 0.2s, linear);
.o-transition(all, 0.1s);
.o-transform(translateX(0));
}
}
.o_attachments_previews {
> .o_attachment {
width: 50%;
@media (min-width: @screen-sm-min) {
width: percentage(1/3);
}
@media (min-width: @screen-md-min) {
width: percentage(1/4);
}
@media (min-width: @screen-lg-min) {
width: percentage(1/6);
}
.o_attachment_wrap {
padding: 0;
border-radius: 2px;
border: 1px solid @gray-lighter-darker;
}
.o_image_box {
overflow: hidden;
padding-top: 75%;
.o_attachment_image {
.o-position-absolute(0,0,0,0);
background-size: cover;
background-position: center;
.o-transform(scale(1.05));
.o-transition(all, 0.3s);
}
&:hover .o_attachment_image {
.o-transform(scale(1));
}
}
.o_image_overlay {
.o-position-absolute(@top: 0, @left: 0, @right:0, @bottom:0);
.o-hover-opacity(@default-opacity: 0, @hover-opacity: 1);
.o-linear-gradient(180deg, fade(black, 20%), fade(black, 90%));
.o-transition(all, 0.3s);
padding: 10px;
.o_attachment_title {
.o-position-absolute(@bottom: 7px);
width: 80%;
.o-text-overflow(inline-block);
font-size: @font-size-small;
}
.o_attachment_download {
.o-position-absolute(@right: 7px, @bottom:7px);
}
}
}
}
......
......@@ -177,6 +177,12 @@
}
}
.o_attachments_list, .o_attachments_previews {
&:last-child {
margin-bottom: @grid-gutter-width;
}
}
.o_thread_tooltip_container {
display: inline;
position: relative;
......
......@@ -207,9 +207,18 @@
<t t-if="!(message.tracking_value_ids and message.tracking_value_ids.length &gt; 0)">
<t t-raw="message.body"/>
</t>
<t t-foreach="message.attachment_ids" t-as="attachment">
<t t-call="mail.Attachment"/>
</t>
<t t-if="message.attachment_ids.length > 0">
<div t-if="message.images.length > 0" class="o_attachments_previews">
<t t-foreach="message.images" t-as="attachment">
<t t-call="mail.AttachmentPreview"/>
</t>
</div>
<div t-if="message.others.length > 0" class="o_attachments_list">
<t t-foreach="message.others" t-as="attachment">
<t t-call="mail.Attachment"/>
</t>
</div>
</t>
</div>
</div>
</div>
......@@ -242,7 +251,7 @@
</t>
<t t-name="mail.ChatComposer.Attachments">
<div t-if="attachments.length > 0" class="o_attachments">
<div t-if="attachments.length > 0" class="o_attachments o_attachments_list">
<t t-foreach="attachments" t-as='attachment'>
<t t-call="mail.Attachment">
<t t-set="editable" t-value="true"/>
......@@ -251,68 +260,58 @@
</div>
</t>
<t t-name="mail.Attachment">
<t t-set="type" t-value="attachment.mimetype and attachment.mimetype.split('/').shift()"/>
<div t-attf-class="o_attachment #{attachment.upload ? 'o_attachment_uploading' : ''}" t-att-title="attachment.name">
<t t-if="type == 'image'">
<t t-name="mail.AttachmentPreview">
<div class="o_attachment" t-att-title="attachment.name">
<div class="o_attachment_wrap">
<div class="o_image_box">
<img t-attf-src="/web/image/#{attachment.id}/200x200/?crop=True"/>
<div class="o_attachment_image" t-attf-style="background-image:url('/web/image/#{attachment.id}/160x160/?crop=true')"/>
<div t-attf-class="o_image_overlay o_attachment_view" t-att-data-id="attachment.id">
<a class="o_attachment_download" t-att-href='attachment.url' target="_blank">
<i t-attf-class="fa fa-2x fa-arrow-circle-o-down" title="Download this attachment" aria-hidden="true"></i>
<span class="o_attachment_title text-white"><t t-esc="attachment.name"/></span>
<a class="o_attachment_download" t-att-href='attachment.url'>
<i t-attf-class="fa fa-download text-white" t-att-title="'Download ' + attachment.name" aria-hidden="true"></i>
</a>
</div>
</div>
</t>
<t t-elif="type == 'video'">
<div class="o_image_box o_image_preview">
<img class="o_image" t-att-data-mimetype="attachment.mimetype"/>
<div t-attf-class="o_image_overlay o_attachment_view" t-att-data-id="attachment.id">
<a class="o_attachment_play">
<i t-attf-class="fa fa-2x fa-play-circle" title="Play this video" aria-hidden="true"></i>
</a>
<a class="o_attachment_download" t-att-href='attachment.url' target="_blank">
<i t-attf-class="fa fa-2x fa-arrow-circle-o-down" title="Download this attachment" aria-hidden="true"></i>
</a>
</div>
</div>
</t>
<t t-name="mail.Attachment">
<t t-set="type" t-value="attachment.mimetype and attachment.mimetype.split('/').shift()"/>
<div t-attf-class="o_attachment #{ editable ? 'o_attachment_editable' : '' } #{attachment.upload ? 'o_attachment_uploading' : ''}" t-att-title="attachment.name">
<div class="o_attachment_wrap">
<t t-set="has_preview" t-value="type == 'image' or type == 'video' or attachment.mimetype == 'application/pdf'"/>
<div t-attf-class="o_image_box pull-left #{has_preview ? 'o_attachment_view' : ''}" t-att-data-id="attachment.id">
<div t-if="has_preview"
class="o_image o_hover"
t-att-style="type == 'image' ? 'background-image:url(/web/image/' + attachment.id + '/38x38/?crop=true' : '' "
t-att-data-mimetype="attachment.mimetype">
</div>
<a t-elif="!editable" t-att-href='attachment.url' t-att-title="'Download ' + attachment.name">
<span class="o_image o_hover" t-att-data-mimetype="attachment.mimetype"/>
</a>
<span t-else="" class="o_image" t-att-data-mimetype="attachment.mimetype"/>
</div>
</t>
<t t-elif="attachment.mimetype == 'application/pdf'">
<div class="o_image_box">
<div class="o_image_box">
<img src="/web/static/src/img/mimetypes/pdf.png"/>
<div class="o_image_overlay o_attachment_view" t-att-data-id="attachment.id">
<a class="o_attachment_download" t-att-href='attachment.url' target="_blank">
<i t-attf-class="fa fa-2x fa-arrow-circle-o-down" title="Download this PDF" aria-hidden="true"></i>
</a>
</div>
</div>
<div class="caption">
<span t-if="has_preview or editable" t-attf-class="ml4 #{has_preview? 'o_attachment_view' : ''}" t-att-data-id="attachment.id"><t t-esc='attachment.name'/></span>
<a t-else="" class="ml4" t-att-href="attachment.url" t-att-title="'Download ' + attachment.name"><t t-esc='attachment.name'/></a>
</div>
</t>
<t t-else="">
<div class="o_image_box">
<img class="o_image" t-att-data-mimetype="attachment.mimetype"/>
<div t-attf-class="o_image_overlay">
<a class="o_overlay_download" t-att-href='attachment.url' target="_blank"/>
<a class="o_attachment_download" t-att-href='attachment.url' target="_blank">
<i t-attf-class="fa fa-2x fa-arrow-circle-o-down" title="Download this attachment" aria-hidden="true"></i>
</a>
<div t-if="editable" class="caption small">
<b t-attf-class="ml4 small text-uppercase #{has_preview? 'o_attachment_view' : ''}" t-att-data-id="attachment.id"><t t-esc="ext"/></b>
<div class="progress o_attachment_progress_bar">
<div class="progress-bar progress-bar-striped active" style="width: 100%">Uploading</div>
</div>
</div>
</t>
<div class="caption">
<a t-att-href='attachment.url' target="_blank">
<t t-esc='attachment.name'/>
</a>
</div>
<t t-if="editable">
<div class="o_attachment_delete">
<i class='fa fa-times-circle' title="Delete this attachment" t-att-data-id="attachment.id"/>
</div>
<div class="o_attachment_progress_bar">
Uploading
<div t-if="!editable" class="caption small">
<b t-if="has_preview" class="ml4 small text-uppercase o_attachment_view" t-att-data-id="attachment.id"><t t-esc="ext"/></b>
<a t-else="" class="ml4 small text-uppercase" t-att-href="attachment.url" t-att-title="'Download ' + attachment.name"><b><t t-esc='ext'/></b></a>
<a class="ml4 o_attachment_download pull-right" t-att-title="'Download ' + attachment.name" t-att-href='attachment.url'><i t-attf-class="fa fa-download"/></a>
</div>
</t>
<div t-if="editable" class="o_attachment_uploaded"><i class="text-success fa fa-check"/></div>
<div t-if="editable" class="o_attachment_delete" t-att-data-id="attachment.id"><span class="text-white">×</span></div>
</div>
</div>
</t>
......
......@@ -684,7 +684,7 @@ QUnit.test('chatter: Attachment viewer', function (assert) {
});
assert.strictEqual(form.$('.o_thread_message .o_attachment').length, 4,
"there should be three attachment on message");
assert.strictEqual(form.$('.o_thread_message .o_attachment .caption a').first().attr('href'), '/web/content/1?download=true',
assert.strictEqual(form.$('.o_thread_message .o_attachment a').first().attr('href'), '/web/content/1?download=true',
"image caption should have correct download link");
// click on first image attachement
form.$('.o_thread_message .o_attachment .o_image_box .o_image_overlay').first().click();
......@@ -699,7 +699,7 @@ QUnit.test('chatter: Attachment viewer', function (assert) {
// close attachment popup
$('.o_modal_fullscreen .o_viewer-header .o_close_btn').click();
// click on pdf attachement
form.$('.o_thread_message .o_attachment .o_image_box .o_image_overlay').eq(3).click();
form.$('span:contains(Test PDF 1)').click();
assert.strictEqual($('.o_modal_fullscreen iframe[data-src*="/web/content/4"]').length, 1,
"Modal popup should open with the pdf preview");
// close attachment popup
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment