summaryrefslogtreecommitdiff
path: root/addons
diff options
context:
space:
mode:
authorXavier Dubuc <xdu@odoo.com>2020-11-10 08:59:25 +0000
committerSébastien Theys <seb@odoo.com>2020-11-30 15:21:27 +0000
commitd9aa362914945e6cb095b04fa94cfb3469abd907 (patch)
treed234604da02879d539155206949e112d437957c2 /addons
parent24d52d4a8d0f475bb62b6653c08ce409e27e1d58 (diff)
[FIX] hr_holidays: bring back the out of office panel in threads
task-2277511 closes odoo/odoo#61586 Signed-off-by: Sébastien Theys (seb) <seb@odoo.com>
Diffstat (limited to 'addons')
-rw-r--r--addons/hr_holidays/i18n/hr_holidays.pot7
-rw-r--r--addons/hr_holidays/static/src/bugfix/bugfix.js78
-rw-r--r--addons/hr_holidays/static/src/bugfix/bugfix_tests.js92
-rw-r--r--addons/hr_holidays/static/src/components/thread_view/thread_view.js29
-rw-r--r--addons/hr_holidays/static/src/components/thread_view/thread_view.xml4
-rw-r--r--addons/hr_holidays/static/tests/helpers/mock_models.js28
-rw-r--r--addons/hr_holidays/static/tests/helpers/mock_server.js29
-rw-r--r--addons/hr_holidays/views/hr_leave_template.xml2
-rw-r--r--addons/mail/static/src/js/core/translation.js5
-rw-r--r--addons/mail/static/src/models/locale/locale.js14
-rw-r--r--addons/mail/static/src/models/partner/partner.js14
11 files changed, 269 insertions, 33 deletions
diff --git a/addons/hr_holidays/i18n/hr_holidays.pot b/addons/hr_holidays/i18n/hr_holidays.pot
index 62cc0887314..c952b719400 100644
--- a/addons/hr_holidays/i18n/hr_holidays.pot
+++ b/addons/hr_holidays/i18n/hr_holidays.pot
@@ -3308,3 +3308,10 @@ msgstr ""
#: model_terms:ir.ui.view,arch_db:hr_holidays.hr_leave_view_kanban
msgid "validated"
msgstr ""
+
+#. module: hr_holidays
+#. openerp-web
+#: code:addons/hr_holidays/static/src/bugfix/bugfix.js:0
+#, python-format
+msgid "Out of office until %s"
+msgstr ""
diff --git a/addons/hr_holidays/static/src/bugfix/bugfix.js b/addons/hr_holidays/static/src/bugfix/bugfix.js
index 1f0782785eb..41d3e558cc0 100644
--- a/addons/hr_holidays/static/src/bugfix/bugfix.js
+++ b/addons/hr_holidays/static/src/bugfix/bugfix.js
@@ -8,3 +8,81 @@ odoo.define('hr_holidays/static/src/bugfix/bugfix.js', function (require) {
'use strict';
});
+
+// FIXME move me in hr_holidays/static/src/models/partner/partner.js
+odoo.define('hr_holidays/static/src/models/partner/partner.js', function (require) {
+'use strict';
+
+const {
+ registerClassPatchModel,
+ registerFieldPatchModel,
+ registerInstancePatchModel,
+} = require('mail/static/src/model/model_core.js');
+const { attr, one2one } = require('mail/static/src/model/model_field.js');
+const { clear } = require('mail/static/src/model/model_field_command.js');
+
+const { str_to_datetime } = require('web.time');
+
+registerClassPatchModel('mail.partner', 'hr_holidays/static/src/models/partner/partner.js', {
+ /**
+ * @override
+ */
+ convertData(data) {
+ const data2 = this._super(data);
+ if ('out_of_office_date_end' in data) {
+ data2.outOfOfficeDateEnd = data.out_of_office_date_end ? data.out_of_office_date_end : clear();
+ }
+ return data2;
+ },
+});
+
+registerInstancePatchModel('mail.partner', 'hr_holidays/static/src/models/partner/partner.js', {
+ /**
+ * @private
+ */
+ _computeOutOfOfficeText() {
+ if (!this.outOfOfficeDateEnd) {
+ return clear();
+ }
+ if (!this.env.messaging.locale.language) {
+ return clear();
+ }
+ const currentDate = new Date();
+ const date = str_to_datetime(this.outOfOfficeDateEnd);
+ const options = { day: 'numeric', month: 'short' };
+ if (currentDate.getFullYear() !== date.getFullYear()) {
+ options.year = 'numeric';
+ }
+ const localeCode = this.env.messaging.locale.language.replace(/_/g,'-');
+ const formattedDate = date.toLocaleDateString(localeCode, options);
+ return _.str.sprintf(this.env._t("Out of office until %s"), formattedDate);
+ },
+
+});
+
+registerFieldPatchModel('mail.partner', 'hr/static/src/models/partner/partner.js', {
+ /**
+ * Serves as compute dependency.
+ */
+ locale: one2one('mail.locale', {
+ related: 'messaging.locale',
+ }),
+ /**
+ * Date of end of the out of office period of the partner as string.
+ * String is expected to use Odoo's datetime string format
+ * (examples: '2011-12-01 15:12:35.832' or '2011-12-01 15:12:35').
+ */
+ outOfOfficeDateEnd: attr(),
+ /**
+ * Text shown when partner is out of office.
+ */
+ outOfOfficeText: attr({
+ compute: '_computeOutOfOfficeText',
+ dependencies: [
+ 'locale',
+ 'outOfOfficeDateEnd',
+ ],
+ }),
+});
+
+});
diff --git a/addons/hr_holidays/static/src/bugfix/bugfix_tests.js b/addons/hr_holidays/static/src/bugfix/bugfix_tests.js
index a18e79a4020..6f655603071 100644
--- a/addons/hr_holidays/static/src/bugfix/bugfix_tests.js
+++ b/addons/hr_holidays/static/src/bugfix/bugfix_tests.js
@@ -16,3 +16,95 @@ QUnit.module('bugfix_tests.js', {
});
});
+
+// FIXME move me in hr_holidays/static/src/components/thread_view/thread_view_tests.js
+odoo.define('hr_holidays/static/src/components/thread_view/thread_view_tests.js', function (require) {
+'use strict';
+
+const components = {
+ ThreadView: require('mail/static/src/components/thread_view/thread_view.js'),
+};
+const {
+ afterEach,
+ beforeEach,
+ createRootComponent,
+ start,
+} = require('mail/static/src/utils/test_utils.js');
+
+QUnit.module('hr_holidays', {}, function () {
+QUnit.module('components', {}, function () {
+QUnit.module('thread_view', {}, function () {
+QUnit.module('thread_view_tests.js', {
+ beforeEach() {
+ beforeEach(this);
+
+ /**
+ * @param {mail.thread_view} threadView
+ * @param {Object} [otherProps={}]
+ */
+ this.createThreadViewComponent = async (threadView, otherProps = {}) => {
+ const target = this.widget.el;
+ const props = Object.assign({ threadViewLocalId: threadView.localId }, otherProps);
+ await createRootComponent(this, components.ThreadView, { props, target });
+ };
+
+ this.start = async params => {
+ const { afterEvent, env, widget } = await start(Object.assign({}, params, {
+ data: this.data,
+ }));
+ this.afterEvent = afterEvent;
+ this.env = env;
+ this.widget = widget;
+ };
+ },
+ afterEach() {
+ afterEach(this);
+ },
+});
+
+QUnit.test('out of office message on direct chat with out of office partner', async function (assert) {
+ assert.expect(2);
+
+ // Returning date of the out of office partner, simulates he'll be back in a month
+ const returningDate = moment.utc().add(1, 'month');
+ // Needed partner & user to allow simulation of message reception
+ this.data['res.partner'].records.push({
+ id: 11,
+ name: "Foreigner partner",
+ out_of_office_date_end: returningDate.format("YYYY-MM-DD HH:mm:ss"),
+ });
+ this.data['mail.channel'].records = [{
+ channel_type: 'chat',
+ id: 20,
+ members: [this.data.currentPartnerId, 11],
+ }];
+ await this.start();
+ const thread = this.env.models['mail.thread'].findFromIdentifyingData({
+ id: 20,
+ model: 'mail.channel'
+ });
+ const threadViewer = this.env.models['mail.thread_viewer'].create({
+ hasThreadView: true,
+ thread: [['link', thread]],
+ });
+ await this.createThreadViewComponent(threadViewer.threadView, { hasComposer: true });
+ assert.containsOnce(
+ document.body,
+ '.o_ThreadView_outOfOffice',
+ "should have an out of office alert on thread view"
+ );
+ const formattedDate = returningDate.toDate().toLocaleDateString(
+ this.env.messaging.locale.language.replace(/_/g,'-'),
+ { day: 'numeric', month: 'short' }
+ );
+ assert.ok(
+ document.querySelector('.o_ThreadView_outOfOffice').textContent.includes(formattedDate),
+ "out of office message should mention the returning date"
+ );
+});
+
+});
+});
+});
+
+});
diff --git a/addons/hr_holidays/static/src/components/thread_view/thread_view.js b/addons/hr_holidays/static/src/components/thread_view/thread_view.js
index 89923ff0384..c07ab2189a9 100644
--- a/addons/hr_holidays/static/src/components/thread_view/thread_view.js
+++ b/addons/hr_holidays/static/src/components/thread_view/thread_view.js
@@ -5,38 +5,9 @@ const components = {
ThreadView: require('mail/static/src/components/thread_view/thread_view.js'),
};
-const { str_to_datetime } = require('web.time');
const { patch } = require('web.utils');
patch(components.ThreadView, 'hr_holidays/static/src/components/thread_view/thread_view.js', {
-
- //--------------------------------------------------------------------------
- // Public
- //--------------------------------------------------------------------------
-
- /**
- * Returns the "out of office" text for the correspondent of the thread if
- * applicable.
- *
- * @returns {string}
- */
- getOutOfOfficeText() {
- if (!this.threadView.thread.correspondent) {
- return "";
- }
- if (!this.threadView.thread.correspondent.out_of_office_date_end) {
- return "";
- }
- const currentDate = new Date();
- const date = str_to_datetime(this.threadView.thread.correspondent.out_of_office_date_end);
- const options = { day: 'numeric', month: 'short' };
- if (currentDate.getFullYear() !== date.getFullYear()) {
- options.year = 'numeric';
- }
- const formattedDate = date.toLocaleDateString(window.navigator.language, options);
- return _.str.sprintf(this.env._t("Out of office until %s."), formattedDate);
- },
-
//--------------------------------------------------------------------------
// Private
//--------------------------------------------------------------------------
diff --git a/addons/hr_holidays/static/src/components/thread_view/thread_view.xml b/addons/hr_holidays/static/src/components/thread_view/thread_view.xml
index f5e0dce55d8..796dcfba651 100644
--- a/addons/hr_holidays/static/src/components/thread_view/thread_view.xml
+++ b/addons/hr_holidays/static/src/components/thread_view/thread_view.xml
@@ -2,8 +2,8 @@
<templates xml:space="preserve">
<t t-inherit="mail.ThreadView" t-inherit-mode="extension">
<xpath expr="//*[@name='loadingCondition']" position="before">
- <t t-if="threadView.thread.correspondent and threadView.thread.correspondent.out_of_office_date_end">
- <div class="o_ThreadView_outOfOffice alert alert-primary" t-esc="getOutOfOfficeText()" role="alert"/>
+ <t t-if="threadView.thread.correspondent and threadView.thread.correspondent.outOfOfficeText">
+ <div class="o_ThreadView_outOfOffice alert alert-primary" t-esc="threadView.thread.correspondent.outOfOfficeText" role="alert"/>
</t>
</xpath>
</t>
diff --git a/addons/hr_holidays/static/tests/helpers/mock_models.js b/addons/hr_holidays/static/tests/helpers/mock_models.js
new file mode 100644
index 00000000000..8513f29d2bf
--- /dev/null
+++ b/addons/hr_holidays/static/tests/helpers/mock_models.js
@@ -0,0 +1,28 @@
+odoo.define('hr_holidays/static/tests/helpers/mock_models.js', function (require) {
+'use strict';
+
+const MockModels = require('mail/static/tests/helpers/mock_models.js');
+
+MockModels.patch('hr_holidays/static/tests/helpers/mock_models.js', T =>
+ class extends T {
+
+ //----------------------------------------------------------------------
+ // Public
+ //----------------------------------------------------------------------
+
+ /**
+ * @override
+ */
+ static generateData() {
+ const data = super.generateData(...arguments);
+ Object.assign(data['res.partner'].fields, {
+ // Not a real field but ease the testing
+ out_of_office_date_end: { type: 'datetime' },
+ });
+ return data;
+ }
+
+ }
+);
+
+});
diff --git a/addons/hr_holidays/static/tests/helpers/mock_server.js b/addons/hr_holidays/static/tests/helpers/mock_server.js
new file mode 100644
index 00000000000..f4b8f6404c0
--- /dev/null
+++ b/addons/hr_holidays/static/tests/helpers/mock_server.js
@@ -0,0 +1,29 @@
+odoo.define('hr_holidays/static/tests/helpers/mock_server.js', function (require) {
+'use strict';
+
+require('mail.MockServer'); // ensure mail overrides are applied first
+
+const MockServer = require('web.MockServer');
+
+MockServer.include({
+ /**
+ * Overrides to add visitor information to livechat channels.
+ *
+ * @override
+ */
+ _mockMailChannelPartnerInfo(ids, extra_info) {
+ const partnerInfos = this._super(...arguments);
+ const partners = this._getRecords(
+ 'res.partner',
+ [['id', 'in', ids]],
+ { active_test: false },
+ );
+ for (const partner of partners) {
+ // Not a real field but ease the testing
+ partnerInfos[partner.id].out_of_office_date_end = partner.out_of_office_date_end;
+ }
+ return partnerInfos;
+ },
+});
+
+});
diff --git a/addons/hr_holidays/views/hr_leave_template.xml b/addons/hr_holidays/views/hr_leave_template.xml
index f70aa21064e..cfdeeac2c78 100644
--- a/addons/hr_holidays/views/hr_leave_template.xml
+++ b/addons/hr_holidays/views/hr_leave_template.xml
@@ -19,6 +19,8 @@
<template id="qunit_suite" name="hr_holidays_qunit_suite" inherit_id="web.qunit_suite_tests">
<xpath expr="." position="inside">
<script type="text/javascript" src="/hr_holidays/static/src/bugfix/bugfix_tests.js"></script>
+ <script type="text/javascript" src="/hr_holidays/static/tests/helpers/mock_models.js"/>
+ <script type="text/javascript" src="/hr_holidays/static/tests/helpers/mock_server.js"/>
<script type="text/javascript" src="/hr_holidays/static/tests/test_leave_stats_widget.js"></script>
</xpath>
</template>
diff --git a/addons/mail/static/src/js/core/translation.js b/addons/mail/static/src/js/core/translation.js
index a8db8cebc57..faecafaff03 100644
--- a/addons/mail/static/src/js/core/translation.js
+++ b/addons/mail/static/src/js/core/translation.js
@@ -14,9 +14,10 @@ TranslationDataBase.include({
if (Component.env.messaging) {
// Update messaging locale whenever the translation bundle changes.
// In particular if messaging is created before the end of the
- // `load_translations` RPC, the default text direction has to be
- // updated by the received one.
+ // `load_translations` RPC, the default values have to be
+ // updated by the received ones.
Component.env.messaging.locale.update({
+ language: this.parameters.code,
textDirection: this.parameters.direction,
});
}
diff --git a/addons/mail/static/src/models/locale/locale.js b/addons/mail/static/src/models/locale/locale.js
index 4007dbc796c..50167f07c2f 100644
--- a/addons/mail/static/src/models/locale/locale.js
+++ b/addons/mail/static/src/models/locale/locale.js
@@ -16,6 +16,14 @@ function factory(dependencies) {
* @private
* @returns {string}
*/
+ _computeLanguage() {
+ return this.env._t.database.parameters.code;
+ }
+
+ /**
+ * @private
+ * @returns {string}
+ */
_computeTextDirection() {
return this.env._t.database.parameters.direction;
}
@@ -23,6 +31,12 @@ function factory(dependencies) {
}
Locale.fields = {
+ /**
+ * Language used by interface, formatted like {language ISO 2}_{country ISO 2} (eg: fr_FR).
+ */
+ language: attr({
+ compute: '_computeLanguage',
+ }),
textDirection: attr({
compute: '_computeTextDirection',
}),
diff --git a/addons/mail/static/src/models/partner/partner.js b/addons/mail/static/src/models/partner/partner.js
index 95d2e2794ac..3de505426ec 100644
--- a/addons/mail/static/src/models/partner/partner.js
+++ b/addons/mail/static/src/models/partner/partner.js
@@ -259,6 +259,14 @@ function factory(dependencies) {
/**
* @private
+ * @returns {mail.messaging}
+ */
+ _computeMessaging() {
+ return [['link', this.env.messaging]];
+ }
+
+ /**
+ * @private
* @returns {string|undefined}
*/
_computeNameOrDisplayName() {
@@ -308,6 +316,12 @@ function factory(dependencies) {
messagesAsAuthor: one2many('mail.message', {
inverse: 'author',
}),
+ /**
+ * Serves as compute dependency.
+ */
+ messaging: many2one('mail.messaging', {
+ compute: '_computeMessaging',
+ }),
model: attr({
default: 'res.partner',
}),