mirror of
https://github.com/hanzoai/jube-fork.git
synced 2026-11-02 14:29:36 +00:00
265 lines
9.8 KiB
HTML
Executable File
265 lines
9.8 KiB
HTML
Executable File
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<title>Import and Export to iCal</title>
|
|
<meta charset="utf-8">
|
|
<link href="../content/shared/styles/examples-offline.css" rel="stylesheet">
|
|
<link href="../../styles/kendo.common.min.css" rel="stylesheet">
|
|
<link href="../../styles/kendo.rtl.min.css" rel="stylesheet">
|
|
<link href="../../styles/kendo.default.min.css" rel="stylesheet">
|
|
<link href="../../styles/kendo.default.mobile.min.css" rel="stylesheet">
|
|
<script src="../../js/jquery.min.js"></script>
|
|
<script src="../../js/jszip.min.js"></script>
|
|
<script src="../../js/kendo.all.min.js"></script>
|
|
<script src="../content/shared/js/console.js"></script>
|
|
<script>
|
|
|
|
</script>
|
|
|
|
|
|
</head>
|
|
<body>
|
|
|
|
<a class="offline-button" href="../index.html">Back</a>
|
|
|
|
<div id="example">
|
|
<div class="k-widget k-upload k-import-upload">
|
|
<div class="k-button k-button-icontext k-upload-button">
|
|
<span class="k-icon k-i-calendar"></span>Import from iCal<input id="importUpload" type="file" name="file" />
|
|
</div>
|
|
<button class="k-button k-button-icontext" id="exportButton">
|
|
<span class='k-icon k-i-save'></span>Export to iCal
|
|
</button>
|
|
</div>
|
|
|
|
<div id="scheduler"></div>
|
|
|
|
<!-- Load the ical.js -->
|
|
<script src="https://cdn.jsdelivr.net/npm/[email protected]/build/ical.min.js"></script>
|
|
|
|
<script>
|
|
// Example iCal data
|
|
var iCalendarData = [
|
|
'BEGIN:VCALENDAR',
|
|
'PRODID:-//Google Inc//Google Calendar 70.9054//EN',
|
|
'VERSION:2.0',
|
|
'BEGIN:VEVENT',
|
|
'DTSTART:20200414T120000Z',
|
|
'DTEND:20200414T130000Z',
|
|
'RRULE:FREQ=DAILY;COUNT=5',
|
|
'EXDATE:20200416T120000Z',
|
|
'UID:5u021pgsbn8tldfmmvgv7g053i',
|
|
'DESCRIPTION: Recurring Event',
|
|
'SUMMARY: Recurring Event',
|
|
'DTSTAMP:20200411T120000Z',
|
|
'END:VEVENT',
|
|
'BEGIN:VEVENT',
|
|
'DTSTART:20200416T120000Z',
|
|
'DTEND:20200416T130000Z',
|
|
'UID:5u021pgsbn8tldfmmvgv7g053i',
|
|
'RECURRENCE-ID:20200416T120000Z',
|
|
'DESCRIPTION:Recurring Exception',
|
|
'SUMMARY:Exception of the Recurring Event',
|
|
'DTSTAMP:20200411T120000Z',
|
|
'END:VEVENT',
|
|
'BEGIN:VEVENT',
|
|
'DTSTART:20200413T120000Z',
|
|
'DTEND:20200413T130000Z',
|
|
'UID:2au0j5159mn8k71p0m3i17r4ej',
|
|
'DESCRIPTION:Plain Event',
|
|
'SUMMARY:Plain Event',
|
|
'DTSTAMP:20200411T120000Z',
|
|
'END:VEVENT',
|
|
'END:VCALENDAR',
|
|
].join("\r\n");
|
|
|
|
// DataSource schema for iCal support (id is string instead of number)
|
|
kendo.data.schemas["scheduler-ical"] = {
|
|
model: {
|
|
id: "id",
|
|
fields: {
|
|
id: { type: "string" },
|
|
title: { defaultValue: "", type: "string" },
|
|
start: { type: "date" },
|
|
startTimezone: { type: "string" },
|
|
end: { type: "date" },
|
|
endTimezone: { type: "string" },
|
|
recurrenceRule: { defaultValue: "", type: "string" },
|
|
recurrenceException: { defaultValue: "", type: "string" },
|
|
isAllDay: { type: "boolean", defaultValue: false },
|
|
description: { type: "string" }
|
|
}
|
|
}
|
|
};
|
|
|
|
$(function () {
|
|
// Create a blank Scheduler
|
|
$("#scheduler").kendoScheduler({
|
|
startTime: new Date("2020/4/12 08:00"),
|
|
endTime: new Date("2020/4/12 21:00"),
|
|
date: new Date("2020/4/12"),
|
|
height: 600,
|
|
views: [
|
|
{ type: "day" },
|
|
{ type: "workWeek" },
|
|
{ type: "week" },
|
|
{ type: "month", selected: true },
|
|
],
|
|
timezone: "Etc/UTC"
|
|
});
|
|
|
|
//Handle export button click.
|
|
$("#exportButton").on("click", function (ev) {
|
|
ev.preventDefault();
|
|
exportICal();
|
|
});
|
|
|
|
// Create Import Upload widget
|
|
$("#importUpload").kendoUpload({
|
|
async: {
|
|
autoUpload: false
|
|
},
|
|
select: function (ev) {
|
|
// Prevent file selection (file is read only client-side)
|
|
ev.preventDefault();
|
|
|
|
// Get the raw file uploaded/selected
|
|
var myFile = ev.files[0].rawFile;
|
|
var reader = new FileReader();
|
|
|
|
reader.addEventListener('load', function (e) {
|
|
var result = e.target.result;
|
|
// Call the import logic with the file contents
|
|
importICal(result);
|
|
});
|
|
|
|
// Read the file
|
|
reader.readAsBinaryString(myFile);
|
|
},
|
|
multiple: false
|
|
});
|
|
|
|
// Import default iCal data.
|
|
var intervalRunner = window.setInterval(function () {
|
|
if (window.ICAL) {
|
|
window.clearInterval(intervalRunner);
|
|
// Import default iCal data.
|
|
importICal(iCalendarData);
|
|
}
|
|
}, 10);
|
|
});
|
|
|
|
function importICal(iCalData) {
|
|
var scheduler = $("#scheduler").data("kendoScheduler");
|
|
var data = [];
|
|
var jcalData = ICAL.parse(iCalData);
|
|
var vcalendar = new ICAL.Component(jcalData);
|
|
var components = vcalendar.getAllSubcomponents("vevent");
|
|
|
|
for (var i = 0; i < components.length; i++) {
|
|
var event = new ICAL.Event(components[i]);
|
|
var recurrenceRule = null;
|
|
var recurrenceException = null;
|
|
|
|
if (event.isRecurring()) {
|
|
var recur = new ICAL.Recur(event.component.getFirstProperty("rrule"));
|
|
recurrenceRule = recur.getFirstValue().toString()
|
|
}
|
|
|
|
if (event.component.getFirstProperty("exdate")) {
|
|
recurrenceException = event.component.getFirstProperty("exdate").getFirstValue().toICALString();
|
|
}
|
|
|
|
data.push({
|
|
id: event.isRecurrenceException() ? kendo.guid() : event.uid,
|
|
title: event.summary,
|
|
description: event.description,
|
|
start: event.startDate.toString(),
|
|
startTimezone: getTimeZone(event.startDate.timezone),
|
|
end: event.endDate.toString(),
|
|
endTimezone: getTimeZone(event.endDate.timezone),
|
|
recurrenceRule: recurrenceRule,
|
|
recurrenceId: event.isRecurrenceException() ? event.uid : null,
|
|
recurrenceException: recurrenceException
|
|
});
|
|
}
|
|
|
|
scheduler.setDataSource(new kendo.data.SchedulerDataSource({
|
|
data: data,
|
|
schema: kendo.data.schemas["scheduler-ical"]
|
|
}));
|
|
}
|
|
|
|
function exportICal() {
|
|
var scheduler = $("#scheduler").data("kendoScheduler");
|
|
var component = new ICAL.Component(['vcalendar', [], []]);
|
|
component.updatePropertyWithValue('prodid', '-//iCal.js Example');
|
|
component.updatePropertyWithValue('version', '2.0');
|
|
|
|
var schedulerEvents = scheduler.dataSource.view().toJSON();
|
|
|
|
for (var i = 0; i < schedulerEvents.length; i++) {
|
|
var schedulerEvent = schedulerEvents[i];
|
|
var vevent = new ICAL.Component('vevent');
|
|
var event = new ICAL.Event(vevent);
|
|
|
|
event.uid = schedulerEvent.recurrenceId ? schedulerEvent.recurrenceId : schedulerEvent.id;
|
|
event.summary = schedulerEvent.title;
|
|
event.description = schedulerEvent.description;
|
|
event.startDate = ICAL.Time.fromDateTimeString(getISOString(schedulerEvent.start, true));
|
|
event.endDate = ICAL.Time.fromDateTimeString(getISOString(schedulerEvent.end, true));
|
|
|
|
if (schedulerEvent.recurrenceRule) {
|
|
event.component.addProperty(
|
|
new ICAL.Property(ICAL.parse.property("RRULE:" + schedulerEvent.recurrenceRule)));
|
|
}
|
|
|
|
if (schedulerEvent.recurrenceException) {
|
|
event.component.addProperty(
|
|
new ICAL.Property(ICAL.parse.property("EXDATE:" + schedulerEvent.recurrenceException)));
|
|
}
|
|
|
|
if (schedulerEvent.recurrenceId) {
|
|
event.recurrenceId = ICAL.Time.fromDateTimeString(getISOString(schedulerEvent.start, true));
|
|
}
|
|
|
|
event.component.addPropertyWithValue("dtstamp",
|
|
ICAL.Time.fromDateTimeString(getISOString(new Date(), true)));
|
|
|
|
component.addSubcomponent(vevent);
|
|
}
|
|
|
|
kendo.saveAs({
|
|
dataURI: "data:text/calendar," + component.toString(),
|
|
fileName: "KendoSchedulerCal.ics"
|
|
});
|
|
}
|
|
|
|
function getTimeZone(timezone) {
|
|
return timezone.toLowerCase() === "z" ? null : timezone;
|
|
}
|
|
|
|
function getISOString(date, toUTC) {
|
|
date = toUTC ? kendo.timezone.convert(date, date.getTimezoneOffset(), "Etc/UTC") : date;
|
|
return kendo.toString(date, "yyyy-MM-ddTHH:mm:ssZ");
|
|
}
|
|
</script>
|
|
</div>
|
|
|
|
<style>
|
|
.k-import-upload.k-upload {
|
|
padding: 0;
|
|
border-width: 0;
|
|
background: 0 0;
|
|
}
|
|
|
|
.k-import-upload.k-upload .k-upload-button {
|
|
margin-right: 0;
|
|
}
|
|
</style>
|
|
|
|
|
|
|
|
</body>
|
|
</html>
|