/**
* Proxy to access Google **[event resources](https://developers.google.com/google-apps/calendar/v3/reference/events)**.
*/
Ext.define('Ext.google.data.EventsProxy', {
extend: 'Ext.google.data.AbstractProxy',
alias: 'proxy.google-events',
googleApis: { 'calendar': { version: 'v3' } },
/**
* @method buildApiRequests
* @protected
* @inheritdoc
*/
buildApiRequests: function(request) {
var me = this,
action = request.getAction();
switch (action) {
case 'read':
return me.buildReadApiRequests(request);
case 'create':
return me.buildCreateApiRequests(request);
case 'update':
return me.buildUpdateApiRequests(request);
case 'destroy':
return me.buildDestroyApiRequests(request);
default:
Ext.raise('unsupported request: events.' + action);
return null;
}
},
/**
* @method extractResponseData
* @protected
* @inheritdoc
*/
extractResponseData: function(response) {
var me = this,
data = me.callParent(arguments),
items = [];
Ext.each(data.results, function(result) {
switch (result.kind) {
case 'calendar#events':
items = items.concat(result.items.map(me.fromApiEvent.bind(me)));
break;
case 'calendar#event':
items.push(me.fromApiEvent(result));
break;
default:
break;
}
});
return {
items: me.sanitizeItems(items),
success: data.success,
error: data.error
};
},
privates: {
// https://developers.google.com/google-apps/calendar/v3/reference/events
toApiEvent: function(data, allDay) {
var res = {};
Ext.Object.each(data, function(key, value) {
var dateTime = null,
date = null;
switch (key) {
case 'calendarId':
case 'description':
res[key] = value;
break;
case 'id':
res.eventId = value;
break;
case 'title':
res.summary = value;
break;
case 'startDate':
case 'endDate':
if (allDay) {
date = new Date(value);
date.setHours(0, -date.getTimezoneOffset());
date = Ext.Date.format(date, 'Y-m-d');
}
else {
dateTime = Ext.Date.format(new Date(value), 'c');
}
// Need to explicitly set unused date field to null
// http://stackoverflow.com/a/35658479
res[key.slice(0, -4)] = { date: date, dateTime: dateTime };
break;
default:
break;
}
});
return res;
},
// https://developers.google.com/google-apps/calendar/v3/reference/events
fromApiEvent: function(data) {
var res = { allDay: true };
Ext.Object.each(data, function(key, value) {
var date, offset, allDay;
switch (key) {
case 'id':
case 'description':
res[key] = value;
break;
case 'summary':
res.title = value;
break;
case 'start':
case 'end':
date = Ext.Date.parse(value.dateTime || value.date, 'C');
offset = date.getTimezoneOffset();
allDay = !!value.date;
// IMPORTANT: all day events must have their time equal to 00:00 GMT
if (allDay && offset !== 0) {
date.setHours(0, -offset);
}
res[key + 'Date'] = date;
res.allDay = res.allDay && allDay;
break;
default:
break;
}
});
return res;
},
// See https://developers.google.com/google-apps/calendar/v3/reference/events/list
buildReadApiRequests: function(request) {
// by default, the API returns max 250 events per request, up to 2500. Since we
// don't have control on the min & max requested times, and don't know how many
// events will be returned, let's split requests per 3 months and set maxResults
// to 2500 (~26 events per day - should be enough!?).
var rparams = request.getParams(),
start = new Date(rparams.startDate),
end = new Date(rparams.endDate),
requests = [],
next;
while (start < end) {
next = Ext.Date.add(start, Ext.Date.MONTH, 3);
if (next > end) {
next = end;
}
requests.push(gapi.client.calendar.events.list({
calendarId: rparams.calendar,
timeMin: Ext.Date.format(start, 'C'),
timeMax: Ext.Date.format(next, 'C'),
singleEvents: true,
maxResults: 2500
}));
start = next;
}
return requests;
},
// https://developers.google.com/google-apps/calendar/v3/reference/events/insert
buildCreateApiRequests: function(request) {
var record = request.getRecords()[0]; // batch not currently supported!
return gapi.client.calendar.events.insert(
this.toApiEvent(
request.getJsonData(),
record.get('allDay')));
},
// https://developers.google.com/google-apps/calendar/v3/reference/events/patch
// https://developers.google.com/google-apps/calendar/v3/reference/events/move
buildUpdateApiRequests: function(request) {
var record = request.getRecords()[0], // batch not currently supported!
params = this.toApiEvent(request.getJsonData(), record.get('allDay')),
prevCalendarId = record.getModified('calendarId'),
currCalendarId = record.get('calendarId'),
eventId = record.getId(),
requests = [];
// REQUIRED fields for the patch API
params.calendarId = currCalendarId;
params.eventId = eventId;
if (prevCalendarId && prevCalendarId !== currCalendarId) {
// The event has been moved to another calendar
requests.push(gapi.client.calendar.events.move({
destination: currCalendarId,
calendarId: prevCalendarId,
eventId: eventId
}));
}
if (Object.keys(params).length > 2) {
// There is fields to update other than the calendarId + eventId
requests.push(gapi.client.calendar.events.patch(params));
}
return requests;
},
// https://developers.google.com/google-apps/calendar/v3/reference/events/delete
buildDestroyApiRequests: function(request) {
var record = request.getRecords()[0]; // batch not currently supported!
data = request.getJsonData();
// The current calendar implementation nullifies the calendar ID before deleting
// it, so let's get it from the previous values if not anymore in data.
data.calendarId = data.calendarId ||
record.get('calendarId') ||
record.getPrevious('calendarId');
// ['delete'] to make YUI happy
return gapi.client.calendar.events.delete({
'calendarId': data.calendarId,
'eventId': data.id
});
}
}
});