cryptpad/www/calendar/export.js

222 lines
7.7 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// This file is used when a user tries to export the entire CryptDrive.
// Calendars will be exported using this format instead of plain text.
define([
'/customize/pages.js',
], function (Pages) {
var module = {};
var getICSDate = function (str) {
var date = new Date(str);
var m = date.getUTCMonth() + 1;
var d = date.getUTCDate();
var h = date.getUTCHours();
var min = date.getUTCMinutes();
var year = date.getUTCFullYear().toString();
var month = m < 10 ? "0" + m : m.toString();
var day = d < 10 ? "0" + d : d.toString();
var hours = h < 10 ? "0" + h : h.toString();
var minutes = min < 10 ? "0" + min : min.toString();
return year + month + day + "T" + hours + minutes + "00Z";
};
var getDate = function (str, end) {
var date = new Date(str);
if (end) {
date.setDate(date.getDate() + 1);
}
var m = date.getUTCMonth() + 1;
var d = date.getUTCDate();
var year = date.getUTCFullYear().toString();
var month = m < 10 ? "0" + m : m.toString();
var day = d < 10 ? "0" + d : d.toString();
return year+month+day;
};
var MINUTE = 60;
var HOUR = MINUTE * 60;
var DAY = HOUR * 24;
module.main = function (userDoc) {
var content = userDoc.content;
var ICS = [
'BEGIN:VCALENDAR',
'VERSION:2.0',
'PRODID:-//CryptPad//CryptPad Calendar '+Pages.versionString+'//EN',
'METHOD:PUBLISH',
];
Object.keys(content).forEach(function (uid) {
var data = content[uid];
// DTSTAMP: now...
// UID: uid
var start, end;
if (data.isAllDay && data.startDay && data.endDay) {
start = "DTSTART;VALUE=DATE:" + getDate(data.startDay);
end = "DTEND;VALUE=DATE:" + getDate(data.endDay, true);
} else {
start = "DTSTART:"+getICSDate(data.start);
end = "DTEND:"+getICSDate(data.end);
}
Array.prototype.push.apply(ICS, [
'BEGIN:VEVENT',
'DTSTAMP:'+getICSDate(+new Date()),
'UID:'+uid,
start,
end,
'SUMMARY:'+ data.title,
'LOCATION:'+ data.location,
]);
if (Array.isArray(data.reminders)) {
data.reminders.forEach(function (valueMin) {
var time = valueMin * 60;
var days = Math.floor(time / DAY);
time -= days * DAY;
var hours = Math.floor(time / HOUR);
time -= hours * HOUR;
var minutes = Math.floor(time / MINUTE);
time -= minutes * MINUTE;
var seconds = time;
var str = "-P" + days + "D";
if (hours || minutes || seconds) {
str += "T" + hours + "H" + minutes + "M" + seconds + "S";
}
Array.prototype.push.apply(ICS, [
'BEGIN:VALARM',
'ACTION:DISPLAY',
'DESCRIPTION:This is an event reminder',
'TRIGGER:'+str,
'END:VALARM'
]);
});
}
if (Array.isArray(data.cp_hidden)) {
Array.prototype.push.apply(ICS, data.cp_hidden);
}
ICS.push('END:VEVENT');
});
ICS.push('END:VCALENDAR');
return new Blob([ ICS.join('\n') ], { type: 'text/calendar;charset=utf-8' });
};
module.import = function (content, id, cb) {
require(['/lib/ical.min.js'], function () {
var ICAL = window.ICAL;
var res = {};
var vcalendar;
try {
var jcalData = ICAL.parse(content);
vcalendar = new ICAL.Component(jcalData);
} catch (e) {
console.error(e);
return void cb(e);
}
//var method = vcalendar.getFirstPropertyValue('method');
//if (method !== "PUBLISH") { return void cb('NOT_SUPPORTED'); }
// Add all timezones in iCalendar object to TimezoneService
// if they are not already registered.
var timezones = vcalendar.getAllSubcomponents("vtimezone");
timezones.forEach(function (timezone) {
if (!(ICAL.TimezoneService.has(timezone.getFirstPropertyValue("tzid")))) {
ICAL.TimezoneService.register(timezone);
}
});
var events = vcalendar.getAllSubcomponents('vevent');
events.forEach(function (ev) {
var uid = ev.getFirstPropertyValue('uid');
if (!uid) { return; }
// Get start and end time
var isAllDay = false;
var start = ev.getFirstPropertyValue('dtstart');
var end = ev.getFirstPropertyValue('dtend');
var duration = ev.getFirstPropertyValue('duration');
if (!end && !duration) {
if (start.isDate) {
end = start.clone();
end.adjust(1); // Add one day
} else {
end = start.clone();
}
} else if (!end) {
end = start.clone();
end.addDuration(duration);
}
if (start.isDate && end.isDate) {
isAllDay = true;
start = String(start);
end.adjust(-1); // Substract one day
end = String(end);
} else {
start = +start.toJSDate();
end = +end.toJSDate();
}
// Store other properties
var used = ['dtstart', 'dtend', 'uid', 'summary', 'location', 'dtstamp'];
var hidden = [];
ev.getAllProperties().forEach(function (p) {
if (used.indexOf(p.name) !== -1) { return; }
// This is an unused property
hidden.push(p.toICALString());
});
// Get reminders
var reminders = [];
ev.getAllSubcomponents('valarm').forEach(function (al) {
var action = al.getFirstPropertyValue('action');
if (action !== 'DISPLAY') {
// Email notification: keep it in "hidden" and create a cryptpad notification
hidden.push(al.toString());
}
var trigger = al.getFirstPropertyValue('trigger');
var minutes = trigger && trigger.toSeconds ? (-trigger.toSeconds() / 60) : 0;
if (reminders.indexOf(minutes) === -1) { reminders.push(minutes); }
});
// Create event
res[uid] = {
calendarId: id,
id: uid,
category: 'time',
title: ev.getFirstPropertyValue('summary'),
location: ev.getFirstPropertyValue('location'),
isAllDay: isAllDay,
start: start,
end: end,
reminders: reminders,
cp_hidden: hidden
};
if (!hidden.length) { delete res[uid].cp_hidden; }
if (!reminders.length) { delete res[uid].reminders; }
});
cb(null, res);
});
};
return module;
});