[FIX] microsoft_calendar: Badge when sync is active

Add a cron to sync events in Microsoft calendar
In Google and Microsoft calendar: remove 'sync with ...' button
when the synchronization is already activated, and replace it by a
badge.

closes odoo/odoo#58197

Taskid: 2329313
X-original-commit: 255eb91dd5e9fb39a7625064d1ba8e0b492bfb85
Signed-off-by: Yannick Tivisse (yti) <yti@odoo.com>
Signed-off-by: jbm-odoo <jbm-odoo@users.noreply.github.com>
This commit is contained in:
jbm-odoo
2020-09-22 10:08:27 +00:00
parent 9ac156b777
commit edee29613d
12 changed files with 110 additions and 26 deletions
@@ -20,7 +20,7 @@ class ResConfigSettings(models.TransientModel):
module_google_calendar = fields.Boolean(
string='Allow the users to synchronize their calendar with Google Calendar')
module_microsoft_calendar = fields.Boolean(
string='Allow the users to synchronize their calendar with Office 365 Calendar')
string='Allow the users to synchronize their calendar with Outlook Calendar')
module_google_drive = fields.Boolean("Attach Google documents to any record")
module_google_spreadsheet = fields.Boolean("Google Spreadsheet")
module_auth_oauth = fields.Boolean("Use external authentication providers (OAuth)")
@@ -253,7 +253,7 @@
<field name="module_microsoft_calendar" />
</div>
<div class="o_setting_right_pane">
<label string="Office 365 Calendar" for="module_microsoft_calendar"/>
<label string="Outlook Calendar" for="module_microsoft_calendar"/>
<div class="text-muted">
Synchronize your calendar with Outlook
</div>
@@ -14,6 +14,24 @@ var _t = core._t;
const GoogleCalendarModel = CalendarModel.include({
/**
* @override
*/
init: function () {
this._super.apply(this, arguments);
this.google_is_sync = true;
},
/**
* @override
*/
__get: function () {
var result = this._super.apply(this, arguments);
result.google_is_sync = this.google_is_sync;
return result;
},
/**
* @override
* @returns {Promise}
@@ -35,6 +53,7 @@ const GoogleCalendarModel = CalendarModel.include({
},
_syncGoogleCalendar(shadow = false) {
var self = this;
var context = this.getSession().user_context;
return this._rpc({
route: '/google_calendar/sync_data',
@@ -43,7 +62,14 @@ const GoogleCalendarModel = CalendarModel.include({
fromurl: window.location.href,
local_context: context, // LUL TODO remove this local_context
}
}, {shadow});
}, {shadow}).then(function (result) {
if (result.status === "need_config_from_admin" || result.status === "need_auth") {
self.google_is_sync = false;
} else if (result.status === "no_new_event_from_google" || result.status === "need_refresh") {
self.google_is_sync = true;
}
return result
});
},
})
@@ -115,12 +141,16 @@ const GoogleCalendarRenderer = CalendarRenderer.include({
this._super.apply(this, arguments);
this.$googleButton = $();
if (this.model === "calendar.event") {
this.$googleButton = $('<button/>', {type: 'button', html: _t("Sync with <b>Google</b>")})
.addClass('o_google_sync_button oe_button btn btn-secondary')
.prepend($('<img/>', {
src: "/google_calendar/static/src/img/calendar_32.png",
}))
if (this.state.google_is_sync) {
this.$googleButton = $('<span/>', {html: _t("Synched with Google")})
.addClass('o_google_sync badge badge-pill badge-success')
.prepend($('<i/>', {class: "fa mr-2 fa-check"}))
.appendTo(self.$sidebar);
} else {
this.$googleButton = $('<button/>', {type: 'button', html: _t("Sync with <b>Google</b>")})
.addClass('o_google_sync_button oe_button btn btn-secondary')
.appendTo(self.$sidebar);
}
}
},
@@ -1,10 +1,12 @@
.o_google_sync_button {
display: block;
margin: auto;
> img {
margin-right: 10px;
}
}
.o_google_sync.badge {
border: none;
}
img.calendar_img_tuto {
margin: 0 0 10px 50px;
@@ -70,7 +70,7 @@ QUnit.module('Google Calendar', {
}, function () {
QUnit.test('sync google calendar', async function (assert) {
assert.expect(8);
assert.expect(9);
var calendar = await createCalendarView({
View: GoogleCalendarView,
@@ -105,12 +105,14 @@ QUnit.module('Google Calendar', {
assert.containsN(calendar, '.fc-event', 3, "should display 3 events on the month");
await testUtils.dom.click(calendar.$('.o_google_sync_button'));
await testUtils.dom.click(calendar.$('.o_calendar_button_next'));
await testUtils.dom.click(calendar.$('.o_calendar_button_prev'));
assert.verifySteps([
'/google_calendar/sync_data',
'/web/dataset/call_kw/calendar.event/search_read',
'/google_calendar/sync_data',
'/web/dataset/call_kw/calendar.event/search_read',
'/google_calendar/sync_data',
'/web/dataset/call_kw/calendar.event/search_read',
], 'should do a search_read before and after the call to sync_data');
@@ -9,6 +9,7 @@
'depends': ['microsoft_account', 'calendar'],
'qweb': ['static/src/xml/*.xml'],
'data': [
'data/microsoft_calendar_data.xml',
'security/ir.model.access.csv',
'wizard/reset_account_views.xml',
'views/res_config_settings_views.xml',
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<data>
<record forcecreate="True" id="ir_cron_sync_all_cals" model="ir.cron">
<field name="name">Outlook: synchronization</field>
<field name="model_id" ref="model_res_users"/>
<field name="state">code</field>
<field name="code">
model._sync_all_microsoft_calendar()
</field>
<field name="user_id" ref="base.user_root" />
<field name="interval_number">12</field>
<field name="interval_type">hours</field>
<field name="numbercall">-1</field>
<field eval="False" name="doall" />
</record>
</data>
</odoo>
@@ -112,7 +112,7 @@ class MicrosoftSync(models.AbstractModel):
synced.write({self._active_name: False})
self = self - synced
elif synced:
raise UserError(_("You cannot delete a record synchronized with Microsoft Calendar, archive it instead."))
raise UserError(_("You cannot delete a record synchronized with Outlook Calendar, archive it instead."))
return super().unlink()
@api.model
@@ -39,7 +39,7 @@ class User(models.Model):
client_secret = get_param('microsoft_calendar_client_secret')
if not client_id or not client_secret:
raise UserError(_("The account for the Microsoft Calendar service is not configured."))
raise UserError(_("The account for the Outlook Calendar service is not configured."))
headers = {"content-type": "application/x-www-form-urlencoded"}
data = {
@@ -14,6 +14,23 @@ var _t = core._t;
const MicrosoftCalendarModel = CalendarModel.include({
/**
* @override
*/
init: function () {
this._super.apply(this, arguments);
this.microsoft_is_sync = true;
},
/**
* @override
*/
__get: function () {
var result = this._super.apply(this, arguments);
result.microsoft_is_sync = this.microsoft_is_sync;
return result;
},
/**
* @override
* @returns {Promise}
@@ -29,19 +46,27 @@ const MicrosoftCalendarModel = CalendarModel.include({
if (error.event) {
error.event.preventDefault();
}
console.error("Could not synchronize Microsoft events now.", error);
console.error("Could not synchronize Outlook events now.", error);
}
return _super(...arguments);
},
_syncMicrosoftCalendar(shadow = false) {
var self = this;
return this._rpc({
route: '/microsoft_calendar/sync_data',
params: {
model: this.modelName,
fromurl: window.location.href,
}
}, {shadow});
}, {shadow}).then(function (result) {
if (result.status === "need_config_from_admin" || result.status === "need_auth") {
self.microsoft_is_sync = false;
} else if (result.status === "no_new_event_from_microsoft" || result.status === "need_refresh") {
self.microsoft_is_sync = true;
}
return result
});
},
});
@@ -68,7 +93,7 @@ const MicrosoftCalendarController = CalendarController.include({
return this.model._syncMicrosoftCalendar().then(function (o) {
if (o.status === "need_auth") {
Dialog.alert(self, _t("You will be redirected to Microsoft to authorize the access to your calendar."), {
Dialog.alert(self, _t("You will be redirected to Outlook to authorize the access to your calendar."), {
confirm_callback: function() {
framework.redirect(o.url);
},
@@ -76,14 +101,14 @@ const MicrosoftCalendarController = CalendarController.include({
});
} else if (o.status === "need_config_from_admin") {
if (!_.isUndefined(o.action) && parseInt(o.action)) {
Dialog.confirm(self, _t("The Microsoft Synchronization needs to be configured before you can use it, do you want to do it now?"), {
Dialog.confirm(self, _t("The Outlook Synchronization needs to be configured before you can use it, do you want to do it now?"), {
confirm_callback: function() {
self.do_action(o.action);
},
title: _t('Configuration'),
});
} else {
Dialog.alert(self, _t("An administrator needs to configure Microsoft Synchronization before you can use it!"), {
Dialog.alert(self, _t("An administrator needs to configure Outlook Synchronization before you can use it!"), {
title: _t('Configuration'),
});
}
@@ -104,7 +129,7 @@ const MicrosoftCalendarRenderer = CalendarRenderer.include({
//--------------------------------------------------------------------------
/**
* Adds the Sync with Microsoft button in the sidebar
* Adds the Sync with Outlook button in the sidebar
*
* @private
*/
@@ -113,12 +138,16 @@ const MicrosoftCalendarRenderer = CalendarRenderer.include({
this._super.apply(this, arguments);
this.$microsoftButton = $();
if (this.model === "calendar.event") {
this.$microsoftButton = $('<button/>', {type: 'button', html: _t("Sync with <b>Microsoft</b>")})
.addClass('o_microsoft_sync_button oe_button btn btn-secondary')
.prepend($('<img/>', {
src: "/microsoft_calendar/static/src/img/calendar_outlook_32.png",
}))
if (this.state.microsoft_is_sync) {
this.$microsoftButton = $('<span/>', {html: _t("Synched with Outlook")})
.addClass('o_microsoft_sync badge badge-pill badge-success')
.prepend($('<i/>', {class: "fa mr-2 fa-check"}))
.appendTo(self.$sidebar);
} else {
this.$microsoftButton = $('<button/>', {type: 'button', html: _t("Sync with <b>Outlook</b>")})
.addClass('o_microsoft_sync_button oe_button btn btn-secondary')
.appendTo(self.$sidebar);
}
}
},
@@ -1,10 +1,12 @@
.o_microsoft_sync_button {
display: block;
margin: auto;
> img {
margin-right: 10px;
}
}
.o_microsoft_sync.badge {
border: none;
}
img.calendar_img_tuto {
margin: 0 0 10px 50px;
@@ -5,7 +5,7 @@
<field name="model">microsoft.calendar.account.reset</field>
<field name="arch" type="xml">
<form>
<h1>Reset Microsoft Calendar Account</h1>
<h1>Reset Outlook Calendar Account</h1>
<group>
<field name="delete_policy" widget="radio"/>
<field name="sync_policy" widget="radio"/>