summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Monjoie <dmo@odoo.com>2017-06-27 16:14:55 +0200
committerDavid Monjoie <dmo@odoo.com>2017-07-03 08:15:24 +0200
commit405681fa8b0a68108291f1aab19a961c458babfa (patch)
tree771b8b36add8125e77e25251c38818261b2bbe82
parent0f7f3fc2f1c78cfaaaef435c1189ac79fe330b15 (diff)
[FIX] web,google_calendar: fix google calendar sync
-rw-r--r--addons/google_calendar/static/src/js/google_calendar.js182
-rw-r--r--addons/google_calendar/static/tests/google_calendar_tests.js122
-rw-r--r--addons/google_calendar/views/google_calendar_templates.xml6
-rw-r--r--addons/web/static/src/js/views/calendar/calendar_renderer.js1
-rw-r--r--addons/web/static/src/js/views/calendar/calendar_view.js1
5 files changed, 244 insertions, 68 deletions
diff --git a/addons/google_calendar/static/src/js/google_calendar.js b/addons/google_calendar/static/src/js/google_calendar.js
index 240b5568c0b..dbb7a308540 100644
--- a/addons/google_calendar/static/src/js/google_calendar.js
+++ b/addons/google_calendar/static/src/js/google_calendar.js
@@ -5,97 +5,143 @@ var core = require('web.core');
var Dialog = require('web.Dialog');
var framework = require('web.framework');
var CalendarRenderer = require('web.CalendarRenderer');
+var CalendarController = require('web.CalendarController');
var _t = core._t;
-CalendarRenderer.include({
- events: _.extend({}, CalendarRenderer.prototype.events, {
- 'click .o_google_sync_button': function () {
- this.syncCalendar(this.fields_view);
- }
+CalendarController.include({
+ custom_events: _.extend({}, CalendarController.prototype.custom_events, {
+ syncCalendar: '_onSyncCalendar',
}),
- syncCalendar: function() {
+
+ //--------------------------------------------------------------------------
+ // Handlers
+ //--------------------------------------------------------------------------
+
+ /**
+ * Try to sync the calendar with Google Calendar. According to the result
+ * from Google API, this function may require an action of the user by the
+ * mean of a dialog.
+ *
+ * @private
+ * @returns {OdooEvent} event
+ */
+ _onSyncCalendar: function (event) {
var self = this;
var context = this.getSession().user_context;
- this.$google_button.prop('disabled', true);
- this.trigger_up('perform_rpc', {
+ this._rpc({
route: '/google_calendar/sync_data',
- args: {
- model: this.state.model,
+ params: {
+ model: this.modelName,
fromurl: window.location.href,
local_context: context,
- },
- on_success: function (o) {
- if (o.status === "need_auth") {
- Dialog.alert(self, _t("You will be redirected to Google to authorize access to your calendar!"), {
+ }
+ }).then(function (o) {
+ if (o.status === "need_auth") {
+ Dialog.alert(self, _t("You will be redirected to Google to authorize access to your calendar!"), {
+ confirm_callback: function() {
+ framework.redirect(o.url);
+ },
+ title: _t('Redirection'),
+ });
+ } else if (o.status === "need_config_from_admin") {
+ if (!_.isUndefined(o.action) && parseInt(o.action)) {
+ Dialog.confirm(self, _t("The Google Synchronization needs to be configured before you can use it, do you want to do it now?"), {
confirm_callback: function() {
- framework.redirect(o.url);
+ self.do_action(o.action);
},
- title: _t('Redirection'),
+ title: _t('Configuration'),
});
- } else if (o.status === "need_config_from_admin") {
- if (!_.isUndefined(o.action) && parseInt(o.action)) {
- Dialog.confirm(self, _t("The Google 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 Google Synchronization before you can use it!"), {
- title: _t('Configuration'),
- });
- }
- } else if (o.status === "need_refresh") {
- self.$calendar.fullCalendar('refetchEvents');
- } else if (o.status === "need_reset") {
- var confirm_text1 = _t("The account you are trying to synchronize (%s) is not the same as the last one used (%s)!");
- var confirm_text2 = _t("In order to do this, you first need to disconnect all existing events from the old account.");
- var confirm_text3 = _t("Do you want to do this now?");
- var text = _.str.sprintf(confirm_text1 + "\n" + confirm_text2 + "\n\n" + confirm_text3, o.info.new_name, o.info.old_name);
- Dialog.confirm(self, text, {
- confirm_callback: function() {
- self._rpc({
- route: '/google_calendar/remove_references',
- params: {
- model: self.state.model,
- local_context: context,
- },
- })
- .done(function(o) {
- if (o.status === "OK") {
- Dialog.alert(self, _t("All events have been disconnected from your previous account. You can now restart the synchronization"), {
- title: _t('Event disconnection success'),
- });
- } else if (o.status === "KO") {
- Dialog.alert(self, _t("An error occured while disconnecting events from your previous account. Please retry or contact your administrator."), {
- title: _t('Event disconnection error'),
- });
- } // else NOP
- });
- },
- title: _t('Accounts'),
+ } else {
+ Dialog.alert(self, _t("An administrator needs to configure Google Synchronization before you can use it!"), {
+ title: _t('Configuration'),
});
}
-
- self.$google_button.prop('disabled', false);
- },
+ } else if (o.status === "need_refresh") {
+ self.reload();
+ } else if (o.status === "need_reset") {
+ var confirmText1 = _t("The account you are trying to synchronize (%s) is not the same as the last one used (%s)!");
+ var confirmText2 = _t("In order to do this, you first need to disconnect all existing events from the old account.");
+ var confirmText3 = _t("Do you want to do this now?");
+ var text = _.str.sprintf(confirmText1 + "\n" + confirmText2 + "\n\n" + confirmText3, o.info.new_name, o.info.old_name);
+ Dialog.confirm(self, text, {
+ confirm_callback: function() {
+ self._rpc({
+ route: '/google_calendar/remove_references',
+ params: {
+ model: self.state.model,
+ local_context: context,
+ },
+ })
+ .done(function(o) {
+ if (o.status === "OK") {
+ Dialog.alert(self, _t("All events have been disconnected from your previous account. You can now restart the synchronization"), {
+ title: _t('Event disconnection success'),
+ });
+ } else if (o.status === "KO") {
+ Dialog.alert(self, _t("An error occured while disconnecting events from your previous account. Please retry or contact your administrator."), {
+ title: _t('Event disconnection error'),
+ });
+ } // else NOP
+ });
+ },
+ title: _t('Accounts'),
+ });
+ }
+ }).always(function () {
+ event.data.on_always();
});
- },
- initSidebar: function() {
+ }
+});
+
+CalendarRenderer.include({
+ events: _.extend({}, CalendarRenderer.prototype.events, {
+ 'click .o_google_sync_button': '_onSyncCalendar',
+ }),
+
+ //--------------------------------------------------------------------------
+ // Private
+ //--------------------------------------------------------------------------
+
+ /**
+ * Adds the Sync with Google button in the sidebar
+ *
+ * @private
+ */
+ _initSidebar: function () {
var self = this;
- this._super();
- this.$google_button = $();
- if (this.state.model === "calendar.event") {
- this.$google_button = $('<button/>', {type: 'button', html: _t("Sync with <b>Google</b>")})
+ 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-sm btn-default')
.prepend($('<img/>', {
src: "/google_calendar/static/src/img/calendar_32.png",
}))
- .appendTo(self.$('.o_calendar_sidebar'));
+ .appendTo(self.$sidebar);
}
},
+
+ //--------------------------------------------------------------------------
+ // Handlers
+ //--------------------------------------------------------------------------
+
+ /**
+ * Requests to sync the calendar with Google Calendar
+ *
+ * @private
+ */
+ _onSyncCalendar: function () {
+ var self = this;
+ var context = this.getSession().user_context;
+ this.$googleButton.prop('disabled', true);
+ this.trigger_up('syncCalendar', {
+ on_always: function () {
+ self.$googleButton.prop('disabled', false);
+ },
+ });
+ },
});
});
diff --git a/addons/google_calendar/static/tests/google_calendar_tests.js b/addons/google_calendar/static/tests/google_calendar_tests.js
new file mode 100644
index 00000000000..08176dde839
--- /dev/null
+++ b/addons/google_calendar/static/tests/google_calendar_tests.js
@@ -0,0 +1,122 @@
+odoo.define('google_calendar.calendar_tests', function (require) {
+"use strict";
+
+var CalendarView = require('web.CalendarView');
+var testUtils = require('web.test_utils');
+
+var createView = testUtils.createView;
+
+var initialDate = new Date("2016-12-12T08:00:00Z");
+
+
+QUnit.module('Google Calendar', {
+ beforeEach: function () {
+ this.data = {
+ 'calendar.event': {
+ fields: {
+ id: {string: "ID", type: "integer"},
+ user_id: {string: "user", type: "many2one", relation: 'user'},
+ partner_id: {string: "user", type: "many2one", relation: 'partner', related: 'user_id.partner_id'},
+ name: {string: "name", type: "char"},
+ start_date: {string: "start date", type: "date"},
+ stop_date: {string: "stop date", type: "date"},
+ start: {string: "start datetime", type: "datetime"},
+ stop: {string: "stop datetime", type: "datetime"},
+ allday: {string: "allday", type: "boolean"},
+ partner_ids: {string: "attendees", type: "one2many", relation: 'partner'},
+ type: {string: "type", type: "integer"},
+ },
+ records: [
+ {id: 5, user_id: 4, partner_id: 4, name: "event 1", start: "2016-12-13 15:55:05", stop: "2016-12-15 18:55:05", allday: false, partner_ids: [], type: 2},
+ {id: 6, user_id: 4, partner_id: 4, name: "event 2", start: "2016-12-18 08:00:00", stop: "2016-12-18 09:00:00", allday: false, partner_ids: [], type: 3}
+ ],
+ check_access_rights: function () {
+ return $.when(true);
+ }
+ },
+ user: {
+ fields: {
+ id: {string: "ID", type: "integer"},
+ display_name: {string: "Displayed name", type: "char"},
+ partner_id: {string: "partner", type: "many2one", relation: 'partner'},
+ image: {string: "image", type: "integer"},
+ },
+ records: [
+ {id: 4, display_name: "user 4", partner_id: 4},
+ ]
+ },
+ partner: {
+ fields: {
+ id: {string: "ID", type: "integer"},
+ display_name: {string: "Displayed name", type: "char"},
+ image: {string: "image", type: "integer"},
+ },
+ records: [
+ {id: 4, display_name: "partner 4", image: 'DDD'}
+ ]
+ },
+ filter_partner: {
+ fields: {
+ id: {string: "ID", type: "integer"},
+ user_id: {string: "user", type: "many2one", relation: 'user'},
+ partner_id: {string: "partner", type: "many2one", relation: 'partner'},
+ },
+ records: [
+ {id: 3, user_id: 4, partner_id: 4}
+ ]
+ },
+ };
+ }
+}, function () {
+
+ QUnit.test('sync google calendar', function (assert) {
+ assert.expect(6);
+
+ var calendar = createView({
+ View: CalendarView,
+ model: 'calendar.event',
+ data: this.data,
+ arch:
+ '<calendar class="o_calendar_test" '+
+ 'date_start="start" '+
+ 'date_stop="stop" '+
+ 'mode="month">'+
+ '<field name="name"/>'+
+ '</calendar>',
+ viewOptions: {
+ initialDate: initialDate,
+ },
+ mockRPC: function (route, args) {
+ if (route === '/google_calendar/sync_data') {
+ assert.step(route);
+ this.data['calendar.event'].records.push(
+ {id: 7, user_id: 4, partner_id: 4, name: "event from google calendar", start: "2016-12-28 15:55:05", stop: "2016-12-29 18:55:05", allday: false, partner_ids: [], type: 2}
+ );
+ return $.when({status: 'need_refresh'});
+ } else if (route === '/google_calendar/static/src/img/calendar_32.png') {
+ return $.when();
+ } else if (route === '/web/dataset/call_kw/calendar.event/search_read') {
+ assert.step(route);
+ }
+ return this._super.apply(this, arguments);
+ },
+ });
+
+ assert.strictEqual(calendar.$('.fc-event').length, 2, "should display 2 events on the month");
+
+ var $sidebar = calendar.$('.o_calendar_sidebar');
+
+ calendar.$('.o_google_sync_button').click();
+
+ assert.verifySteps([
+ '/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');
+
+ assert.strictEqual(calendar.$('.fc-event').length, 3, "should now display 3 events on the month");
+
+ calendar.destroy();
+ });
+});
+});
diff --git a/addons/google_calendar/views/google_calendar_templates.xml b/addons/google_calendar/views/google_calendar_templates.xml
index 6f8924e4af8..4ff9df7f453 100644
--- a/addons/google_calendar/views/google_calendar_templates.xml
+++ b/addons/google_calendar/views/google_calendar_templates.xml
@@ -6,4 +6,10 @@
<script type="text/javascript" src="/google_calendar/static/src/js/google_calendar.js"></script>
</xpath>
</template>
+
+ <template id="qunit_suite" name="google_calendar_tests" inherit_id="web.qunit_suite">
+ <xpath expr="//t[@t-set='head']" position="inside">
+ <script type="text/javascript" src="/google_calendar/static/tests/google_calendar_tests.js"></script>
+ </xpath>
+ </template>
</odoo>
diff --git a/addons/web/static/src/js/views/calendar/calendar_renderer.js b/addons/web/static/src/js/views/calendar/calendar_renderer.js
index 23d63aa9044..a4930c87d37 100644
--- a/addons/web/static/src/js/views/calendar/calendar_renderer.js
+++ b/addons/web/static/src/js/views/calendar/calendar_renderer.js
@@ -164,6 +164,7 @@ return AbstractRenderer.extend({
init: function (parent, state, params) {
this._super.apply(this, arguments);
this.displayFields = params.displayFields;
+ this.model = params.model;
this.filters = [];
this.color_map = {};
diff --git a/addons/web/static/src/js/views/calendar/calendar_view.js b/addons/web/static/src/js/views/calendar/calendar_view.js
index 135224fb0cc..71a6c30b756 100644
--- a/addons/web/static/src/js/views/calendar/calendar_view.js
+++ b/addons/web/static/src/js/views/calendar/calendar_view.js
@@ -119,6 +119,7 @@ var CalendarView = AbstractView.extend({
this.rendererParams.displayFields = displayFields;
this.rendererParams.eventTemplate = _.findWhere(arch.children, {'tag': 'templates'});
+ this.rendererParams.model = viewInfo.model;
this.loadParams.fieldNames = _.uniq(fieldNames);
this.loadParams.mapping = mapping;