summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--addons/mail/static/src/js/activity.js101
-rw-r--r--addons/mail/static/src/scss/mail_activity.scss77
-rw-r--r--addons/mail/static/src/xml/web_kanban_activity.xml77
-rw-r--r--addons/mail/static/tests/activity_tests.js8
-rw-r--r--addons/mail/static/tests/chatter_tests.js7
5 files changed, 155 insertions, 115 deletions
diff --git a/addons/mail/static/src/js/activity.js b/addons/mail/static/src/js/activity.js
index cabcd469b5c..65a4f0a6f2e 100644
--- a/addons/mail/static/src/js/activity.js
+++ b/addons/mail/static/src/js/activity.js
@@ -271,39 +271,55 @@ var BasicActivity = AbstractField.extend({
ev.stopPropagation();
ev.preventDefault();
var self = this;
- var $popoverElement = $(ev.currentTarget);
- var activityID = $popoverElement.data('activity-id');
- var previousActivityTypeID = $popoverElement.data('previous-activity-type-id');
- var forceNextActivity = $popoverElement.data('force-next-activity');
- if (!$popoverElement.data('bs.popover')) {
- $popoverElement.popover({
+ var $markDoneBtn = $(ev.currentTarget);
+ var activityID = $markDoneBtn.data('activity-id');
+ var previousActivityTypeID = $markDoneBtn.data('previous-activity-type-id');
+ var forceNextActivity = $markDoneBtn.data('force-next-activity');
+
+ if ($markDoneBtn.data('toggle') == 'collapse') {
+ var $actLi = $markDoneBtn.parents('.o_log_activity');
+ var $panel = self.$('#o_activity_form_' + activityID);
+
+ if (!$panel.data('bs.collapse')) {
+ var $form = $(QWeb.render('mail.activity_feedback_form', { previous_activity_type_id: previousActivityTypeID, force_next: forceNextActivity}));
+ $panel.append($form);
+ self._onMarkActivityDoneActions($markDoneBtn, $form, activityID);
+
+ // Close and reset any other open panels
+ _.each($panel.siblings('.o_activity_form'), function (el) {
+ if ($(el).data('bs.collapse')) {
+ $(el).empty().collapse('dispose').removeClass('show');
+ }
+ });
+
+ // Scroll to selected activity
+ $markDoneBtn.parents('.o_activity_log_container').scrollTo($actLi.position().top, 100);
+ }
+
+ // Empty and reset panel on close
+ $panel.on('hidden.bs.collapse', function () {
+ if ($panel.data('bs.collapse')) {
+ $actLi.removeClass('o_activity_selected');
+ $panel.collapse('dispose');
+ $panel.empty();
+ }
+ });
+
+ this.$('.o_activity_selected').removeClass('o_activity_selected');
+ $actLi.toggleClass('o_activity_selected');
+ $panel.collapse('toggle');
+
+ } else if (!$markDoneBtn.data('bs.popover')) {
+ $markDoneBtn.popover({
template: $(Popover.Default.template).addClass('o_mail_activity_feedback')[0].outerHTML, // Ugly but cannot find another way
- container: $popoverElement,
+ container: $markDoneBtn,
title : _t("Feedback"),
html: true,
trigger:'click',
placement: 'right', // FIXME: this should work, maybe a bug in the popper lib
content : function () {
var $popover = $(QWeb.render('mail.activity_feedback_form', { previous_activity_type_id: previousActivityTypeID, force_next: forceNextActivity}));
- $popover.find('#activity_feedback').val(self._draftFeedback[activityID]);
- $popover.on('click', '.o_activity_popover_done', function (ev) {
- ev.stopPropagation();
- self._markActivityDone({
- activityID: activityID,
- feedback: _.escape($popover.find('#activity_feedback').val()),
- });
- });
- $popover.on('click', '.o_activity_popover_done_next', function (ev) {
- ev.stopPropagation();
- self._markActivityDoneAndScheduleNext({
- activityID: activityID,
- feedback: _.escape($popover.find('#activity_feedback').val()),
- });
- });
- $popover.on('click', '.o_activity_popover_discard', function (ev) {
- ev.stopPropagation();
- $popoverElement.popover('hide');
- });
+ self._onMarkActivityDoneActions($markDoneBtn, $popover, activityID);
return $popover;
},
}).on('shown.bs.popover', function () {
@@ -316,6 +332,39 @@ var BasicActivity = AbstractField.extend({
}
},
/**
+ * Bind all necessary actions to the 'mark as done' form
+ *
+ * @private
+ * @param {Object} $form
+ * @param {integer} activityID
+ */
+ _onMarkActivityDoneActions: function ($btn, $form, activityID) {
+ var self = this;
+ $form.find('#activity_feedback').val(self._draftFeedback[activityID]);
+ $form.on('click', '.o_activity_popover_done', function (ev) {
+ ev.stopPropagation();
+ self._markActivityDone({
+ activityID: activityID,
+ feedback: _.escape($form.find('#activity_feedback').val()),
+ });
+ });
+ $form.on('click', '.o_activity_popover_done_next', function (ev) {
+ ev.stopPropagation();
+ self._markActivityDoneAndScheduleNext({
+ activityID: activityID,
+ feedback: _.escape($form.find('#activity_feedback').val()),
+ });
+ });
+ $form.on('click', '.o_activity_popover_discard', function (ev) {
+ ev.stopPropagation();
+ if ($btn.data('bs.popover')) {
+ $btn.popover('hide');
+ } else if ($btn.data('toggle') == 'collapse') {
+ self.$('#o_activity_form_' + activityID).collapse('hide');
+ }
+ });
+ },
+ /**
* @private
* @param {MouseEvent} ev
* @returns {$.Deferred}
diff --git a/addons/mail/static/src/scss/mail_activity.scss b/addons/mail/static/src/scss/mail_activity.scss
index cdd8bbe1cb5..16ad01a83b0 100644
--- a/addons/mail/static/src/scss/mail_activity.scss
+++ b/addons/mail/static/src/scss/mail_activity.scss
@@ -123,13 +123,13 @@
}
.o_activity_color_planned {
- color: theme-color('success');
+ color: darken(theme-color('success'), 10%);
}
.o_activity_color_overdue {
- color: theme-color('danger');
+ color: darken(theme-color('danger'), 10%);
}
.o_activity_color_today {
- color: theme-color('warning');
+ color: darken(theme-color('warning'), 10%);
}
}
@@ -160,62 +160,45 @@
}
}
- .o_activity_link_kanban {
- visibility: hidden;
- @include media-breakpoint-down(sm) {
- visibility: visible;
- }
- }
-
- .o_activity_template_preview,.o_activity_template_send {
- font-weight: bold;
- color: $o-brand-primary;
- cursor: pointer;
- &:hover:not(.active) {
- color: darken($o-brand-primary, 15%);
- border-color: darken($o-brand-primary, 15%);
- }
- }
-
div.o_activity {
min-width: 290px;
padding: 0px 0px;
- > :last-child {
- background-color: $o-brand-lightsecondary;
- line-height: 3em;
- }
- ul.o_activity_log {
+ .o_activity_log_container {
max-height: 300px;
overflow-y: auto;
+ }
+
+ ul.o_activity_log {
color: $body-color;
li {
- width: 100%;
- display: inline-block;
+ .o_activity_title_entry {
+ display: flex;
+ align-items: baseline;
+ }
+
+ .o_edit_button {
+ opacity: 0.5;
+ }
+
+ &:hover .o_edit_button{
+ opacity: 1;
+ }
+
+ .o_activity_link_kanban {
+ font-size: 1.5em;
+ @include o-hover-text-color($text-muted, theme-color('success'));
+ @include o-hover-opacity(0.5, 1);
+ }
- &.o_activity_label {
- line-height: 2.5em;
- padding: 0px 5px;
- background-color: $o-brand-lightsecondary;
+ &.o_activity_selected {
+ border-bottom: 0;
}
- &.o_log_activity {
- padding: 8px 10px 8px 0px;
- vertical-align: middle;
- &:hover {
- background-color: theme-color('light');
- .o_activity_link_kanban {
- visibility: visible;
- }
- }
-
- .o_activity_title {
- width: 85%;
- padding: 0px 5px 0px 10px;
- white-space: nowrap;
- text-overflow: ellipsis;
- }
+ &.o_activity_form > div {
+ padding-top: 0.5em;
+ padding-bottom: 0.7em;
}
}
}
diff --git a/addons/mail/static/src/xml/web_kanban_activity.xml b/addons/mail/static/src/xml/web_kanban_activity.xml
index 25d25c1d09b..eb71ba044c2 100644
--- a/addons/mail/static/src/xml/web_kanban_activity.xml
+++ b/addons/mail/static/src/xml/web_kanban_activity.xml
@@ -20,58 +20,65 @@
<span role="menuitem" t-if="_.isEmpty(records)" class="dropdown-item-text text-center o_no_activity">
No activities planned.
</span>
- <div t-else="" aria-haspopup="true" role="menu">
- <ul class="nav o_activity_log" role="menu">
+ <div t-else="" aria-haspopup="true" role="menu" class="o_activity_log_container dropdown-item bg-100 p-0">
+ <ul class="o_activity_log list-group list-group-flush mb-2" role="menu">
<t t-foreach="_.keys(records)" t-as="key">
<t t-set="logs" t-value="records[key]" />
- <li role="menuitem" class="nav-item o_activity_label">
- <strong t-attf-class="o_activity_color_#{key}">
- <t t-esc="selection[key]" /> (<t t-esc="logs.length"/>)
- </strong>
+ <t t-set="contextual_class" t-value="key == 'planned' ? 'success' : (key == 'today' ? 'warning' : 'danger') "/>
+
+ <li role="menuitem" t-attf-class="o_activity_label list-group-item list-group-item list-group-item-light d-flex justify-content-between align-items-center o_activity_color_{{key}} {{!key_first ? 'mt-2' : ''}}">
+ <strong><t t-esc="selection[key]"/></strong>
+ <span t-attf-class="badge badge-pill badge-{{contextual_class}} border-0 mr-0"><t t-esc="logs.length"/></span>
</li>
<t t-foreach="logs" t-as="log">
<t t-set="edit_class" t-value="'o_edit_activity'"/>
<t t-if="log.force_next">
<t t-set="edit_class" t-value=""/>
</t>
- <li t-att-data-activity-id="log.id" t-attf-class="nav-item o_log_activity #{edit_class}" role="menuitem">
- <div class="o_activity_title float-left">
- <span t-attf-class="fa #{log.icon} fa-fw" role="img" aria-label="Log" title="Log"/>
- <strong>
- <t t-esc="log.title_action or log.activity_type_id[1]" />
- </strong>
- <div>
- <span class="fa fa-clock-o fa-fw" role="img" aria-label="Deadline" title="Deadline"/>
- <span t-att-title="log.date_deadline"><t t-esc="log.label_delay" /></span>
- <div class="mt16" t-att-data-activity-id="log.id" t-att-data-force-next-activity="log.force_next" t-att-data-previous-activity-type-id="log.activity_type_id[0]">
- <t t-if="log.mail_template_ids">
- <t t-foreach="log.mail_template_ids" t-as="mail_template">
- <div>
- <i class="fa fa-envelope-o" aria-label="Mail" title="Mail" role="img"></i>
- <span t-esc="mail_template.name"/>:
- <span class="o_activity_template_preview" t-att-data-template-id="mail_template.id">Preview</span>
- <span class="text-muted">or</span>
- <span class="o_activity_template_send" t-att-data-template-id="mail_template.id">Send Now</span>
- </div>
- </t>
- </t>
+ <li t-att-data-activity-id="log.id" t-attf-class="list-group-item o_log_activity d-flex #{edit_class} #{log_last ? 'border-bottom' : ''}" role="menuitem">
+ <div class="o_activity_title">
+ <div t-attf-class="o_activity_title_entry {{! log.force_next ? 'align-items-center' : 'mb-1'}}">
+ <span t-attf-class="fa #{log.icon ? log.icon : 'fa-bell' } fa-fw mr-2 text-center text-muted" role="img" aria-label="Log" title="Log"/>
+ <strong class="text-dark"><t t-esc="log.title_action or log.activity_type_id[1]"/></strong>
+ <button t-if="! log.force_next" class="btn btn-sm btn-link py-0 o_edit_button"><i class="fa fa-pencil"/></button>
+ </div>
+ <div class="o_activity_title_entry mt-1" t-if="log.state != 'today'">
+ <span class="fa fa-clock-o fa-fw mr-2 text-center text-muted" role="img" aria-label="Deadline" title="Deadline"/>
+ <small t-att-title="log.date_deadline"><t t-esc="log.label_delay" /></small>
+ </div>
+ <t t-if="log.mail_template_ids">
+ <div t-foreach="log.mail_template_ids" t-as="mail_template" class="o_activity_title_entry mt-2" t-att-data-activity-id="log.id" t-att-data-force-next-activity="log.force_next" t-att-data-previous-activity-type-id="log.activity_type_id[0]">
+ <i class="fa fa-envelope-o fa-fw mr-2 text-center text-muted" aria-label="Mail" title="Mail" role="img"></i>
+ <small>
+ <div class="mb-1" t-esc="mail_template.name + ':'"/>
+ <a class="o_activity_template_preview" t-att-data-template-id="mail_template.id" href="#"><b>Preview</b></a>
+ <small>or</small>
+ <a class="o_activity_template_send" t-att-data-template-id="mail_template.id" href="#"><b>Send Now</b></a>
+ </small>
</div>
- <t t-if="log.user_id[0] != uid">
- <span class="ml4 fa fa-user" role="img" aria-label="User" title="User"/>
- <span><t t-esc="log.user_id[1]" /></span>
- </t>
+ </t>
+ <div t-if="log.user_id[0] != uid and log.mail_template_ids" class="o_activity_title_entry">
+ <span class="fa fa-user fa-fw mr-2 text-center text-muted" role="img" aria-label="User" title="User"/>
+ <span><t t-esc="log.user_id[1]" /></span>
</div>
</div>
- <div class="float-right">
- <span class="o_mark_as_done o_activity_link o_activity_link_kanban fa fa-check-circle fa-2x mt4" t-att-data-force-next-activity="log.force_next" t-att-data-previous-activity-type-id="log.activity_type_id[0]" t-att-data-activity-id="log.id" title="Mark as done" role="img" aria-label="Mark as done"/>
+ <div class="flex-grow-1 text-right">
+ <a t-att-data-force-next-activity="log.force_next"
+ t-att-data-previous-activity-type-id="log.activity_type_id[0]"
+ t-att-data-activity-id="log.id"
+ t-attf-href="#o_mark_done_form{{log.id}}"
+ class="o_mark_as_done o_activity_link o_activity_link_kanban fa fa-check-circle"
+ data-toggle="collapse" title="Mark as done" role="img" aria-label="Mark as done"/>
</div>
</li>
+ <li t-attf-id="o_activity_form_{{log.id}}" class="o_activity_form list-group-item border-top-0 py-0 mb-2 collapse"></li>
</t>
</t>
</ul>
</div>
- <div role="menuitem" class="o_schedule_activity text-center">
- <a role="button" class="btn btn-link btn-block">
+ <div class="dropdown-divider mt-0"/>
+ <div role="menuitem" class="o_schedule_activity dropdown-header py-1 text-center">
+ <a role="button" class="btn btn-secondary mb-1">
<i class="fa fa-plus fa-fw"></i><strong>Schedule an activity</strong>
</a>
</div>
diff --git a/addons/mail/static/tests/activity_tests.js b/addons/mail/static/tests/activity_tests.js
index 8dfa518da5f..9f7f7fd8808 100644
--- a/addons/mail/static/tests/activity_tests.js
+++ b/addons/mail/static/tests/activity_tests.js
@@ -308,13 +308,13 @@ QUnit.test('activity view: activity widget', function (assert) {
today.find('.o_closest_deadline').click();
assert.ok(dropdown.hasClass('show'), "dropdown should be displayed");
assert.ok(dropdown.find('.o_activity_color_today:contains(Today)').length, "Title should be today");
- assert.ok(dropdown.find('.o_activity_title div div div:first span:contains(template8)').length,
+ assert.ok(dropdown.find('.o_activity_title_entry[data-activity-id="2"]:first div:contains(template8)').length,
"template8 should be available");
- assert.ok(dropdown.find('.o_activity_title div div div:nth-child(2) span:contains(template9)').length,
+ assert.ok(dropdown.find('.o_activity_title_entry[data-activity-id="2"]:eq(1) div:contains(template9)').length,
"template9 should be available");
- dropdown.find('.o_activity_title div div div:first .o_activity_template_preview').click();
- dropdown.find('.o_activity_title div div div:first .o_activity_template_send').click();
+ dropdown.find('.o_activity_title_entry[data-activity-id="2"]:first .o_activity_template_preview').click();
+ dropdown.find('.o_activity_title_entry[data-activity-id="2"]:first .o_activity_template_send').click();
var overdue = activity.$('table tbody tr:first td:nth-child(3).overdue');
overdue.find('.o_closest_deadline').click();
dropdown = overdue.find('.dropdown-menu.o_activity');
diff --git a/addons/mail/static/tests/chatter_tests.js b/addons/mail/static/tests/chatter_tests.js
index 00705b0c26e..b69bc6825e5 100644
--- a/addons/mail/static/tests/chatter_tests.js
+++ b/addons/mail/static/tests/chatter_tests.js
@@ -492,7 +492,7 @@ QUnit.test('kanban activity widget with no activity', function (assert) {
});
QUnit.test('kanban activity widget with an activity', function (assert) {
- assert.expect(11);
+ assert.expect(12);
this.data.partner.records[0].activity_ids = [1];
this.data.partner.records[0].activity_state = 'today';
@@ -539,8 +539,9 @@ QUnit.test('kanban activity widget with an activity', function (assert) {
$record.find('.o_activity_btn').click();
assert.strictEqual(rpcCount, 2, 'a read should have been done to fetch the activity details');
assert.strictEqual($record.find('.o_activity_title').length, 1, "should have an activity scheduled");
- var label_text = $record.find('.o_activity_label .o_activity_color_today').text();
- assert.ok(label_text.indexOf('Today (1)') >= 0, "should display the correct label and count");
+ var label = $record.find('.o_activity_log .o_activity_color_today');
+ assert.strictEqual(label.find('strong').text(), "Today", "should display the correct label");
+ assert.strictEqual(label.find('.badge-warning').text(), "1", "should display the correct count");
// click on the activity button to close the dropdown
$record.find('.o_activity_btn').click();