Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <head>
- <meta charset="utf-8">
- <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
- <meta name="description" content="KULoket to iCal script">
- <meta name="keywords" content="KUL,KULoket,Toledo,uurrooster,roster,schedule,ical,google,calendar">
- <meta name="author" content="Dries007">
- <title>KUL2iCal</title>
- <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M" crossorigin="anonymous">
- <style>
- body {
- margin-bottom: 80px;
- }
- html {
- position: relative;
- min-height: 100%;
- }
- footer {
- position: absolute;
- bottom: 0;
- width: 100%;
- /* Set the fixed height of the footer here */
- height: 60px;
- background-color: #f5f5f5;
- }
- footer p {
- margin: 20px 0;
- }
- label {
- margin-bottom: 0;
- }
- .string { color: green; }
- .number { color: darkorange; }
- .boolean { color: blue; }
- .null { color: magenta; }
- .key { color: darkmagenta; }
- </style>
- <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
- <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.11.0/umd/popper.min.js" integrity="sha384-b/U6ypiBEHpOf/4+1nzFpr53nxSS+GLCkfwBdFNTxtclqqenISfwAzpKaMNFNmj4" crossorigin="anonymous"></script>
- <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/js/bootstrap.min.js" integrity="sha384-h0AbiXch4ZDo7tp9hKZ4TsHbi047NrKGLO3SEJAg45jXxnGIfYzk4Si90RDIqNm1" crossorigin="anonymous"></script>
- <script src="download.js"></script>
- <!--suppress EqualityComparisonWithCoercionJS -->
- <script>
- 'use strict';
- var dateRegex = /^\/Date\((\d+)\)\/$/;
- var timeRegex = /^PT(\d{2})H(\d{2})M\d{2}S$/;
- var baseurl = "https://webwsp.aps.kuleuven.be/sap/opu/odata/sap/zc_ep_schedule_srv/Events?$format=json&$filter=";
- var output;
- var steps;
- var data;
- $(function ()
- {
- steps = [$('#step1'), $('#step2'), $('#step3'), $('#step4')];
- step(1);
- });
- /**
- * Json syntax highlighting
- * Give this guy all the credit: http://stackoverflow.com/questions/4810841/how-can-i-pretty-print-json-using-javascript/7220510#7220510
- */
- function syntaxHighlight(json)
- {
- if (typeof json != 'string') json = JSON.stringify(json, undefined, 2);
- json = json.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
- return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function (match)
- {
- var cls = 'number';
- if (/^"/.test(match))
- {
- if (/:$/.test(match)) cls = 'key';
- else cls = 'string';
- }
- else if (/true|false/.test(match)) cls = 'boolean';
- else if (/null/.test(match)) cls = 'null';
- return '<span class="' + cls + '">' + match + '</span>';
- });
- }
- function makeUrl()
- {
- try
- {
- var start = $("#start").val();
- var end = $("#end").val();
- var teachers = $("#teachers").prop("checked");
- var locations = $("#locations").prop("checked");
- if (start == "" || end == "") return false;
- var filter = "date ge datetime'" + start + "T00:00:00' and date le datetime'" + end + "T00:00:00'";
- var url = baseurl + encodeURIComponent(filter);
- if (teachers || locations)
- {
- url += "&$expand=";
- var expand = [];
- if (teachers) expand.push("EventTeacherSet");
- if (locations) expand.push("EventLocationSet");
- url += encodeURIComponent(expand.join(','));
- }
- $("#link").html('<a href="' + url + '" target="_blank">' + url + '</a>');
- step(2)
- }
- catch (e)
- {
- console.log(e);
- }
- return false;
- }
- function getLocation(result)
- {
- return result.roomNumber + ' ' + result.roomName + " in " + result.buildingName;
- }
- function getLocations(results)
- {
- var n = results.length;
- if (n == 0) return '???';
- if (n == 1) return getLocation(results[0]);
- var a = [];
- for (var i = 0; i < n; i++) a.push(getLocation(results[i]));
- return a.join(', ');
- }
- function getTeachers(results)
- {
- var n = results.length;
- if (n == 0) return '???';
- if (n == 1) return results[0].name;
- var a = [];
- for (var i = 0; i < n; i++) a.push(results[i].name);
- return a.join(', ');
- }
- /**
- * @param date {Date}
- * @returns {string}
- */
- function getIcalFormat(date)
- {
- return date.getFullYear() + ("0" + (date.getMonth() + 1)).slice(-2) + ("0" + date.getDate()).slice(-2) + "T" + ("0" + date.getHours()).slice(-2) + ("0" + date.getMinutes()).slice(-2) + "00";
- }
- function downloadIcal()
- {
- download(output, "kul2ical.ics", "text/calendar; charset=UTF-8");
- }
- function showIcal()
- {
- var generator = window.open('', '_blank', '');
- generator.document.write('<html><head><title>kul2ical.ics</title></head><body><pre>');
- generator.document.write(output);
- generator.document.write('</pre></body></html>');
- generator.document.close();
- }
- function parseJson()
- {
- try
- {
- var json = $("#json").val();
- json = JSON.parse(json, function (k, v) {
- if (k === "__metadata") return;
- return v;
- }).d.results;
- // console.debug(json);
- // $("#jsonOut").html(syntaxHighlight(JSON.stringify(json, null, 2)));
- var teachers = json[0].hasOwnProperty('EventTeacherSet');
- var locations = json[0].hasOwnProperty('EventLocationSet');
- data = {};
- json.forEach(function (event_json)
- {
- var date = parseInt(dateRegex.exec(event_json['date'])[1]);
- var start = new Date(date);
- var end = new Date(date);
- var temp = timeRegex.exec(event_json['start_time']);
- start.setHours(temp[1], temp[2], 0, 0);
- temp = timeRegex.exec(event_json['end_time']);
- end.setHours(temp[1], temp[2], 0, 0);
- var event = {
- location: locations ? getLocations(event_json['EventLocationSet']['results']) : '',
- teachers: teachers ? getTeachers(event_json['EventTeacherSet']['results']) : '',
- start: getIcalFormat(start),
- end: getIcalFormat(end)
- };
- var group = {
- group: event_json['groupinfo_general'],
- group_extra: event_json['groupinfo_detail'],
- events: [event],
- checkbox: null
- };
- var common = {
- ects: event_json['ects_code'],
- name: event_json['ola_description'],
- groups: [group]
- };
- // console.debug(event_json);
- // console.debug(event);
- if (!data.hasOwnProperty(event_json['eventID']))
- {
- data[event_json['eventID']] = [common];
- }
- else // eventID already present
- {
- var found_common = data[event_json['eventID']].filter(function (t)
- {
- return t.ects == common.ects && t.name == common.name
- });
- if (found_common.length == 0) // New 'common', push it to the eventID array
- {
- data[event_json['eventID']].push(common);
- }
- else // Common already present
- {
- found_common = found_common[0];
- var found_group = found_common.groups.filter(function (t)
- {
- return t.group == group.group && t.group_extra == group.group_extra
- });
- if (found_group.length == 0) // New 'group', push it to the common's groups array
- {
- found_common.groups.push(group);
- }
- else // Group already present, push event to groups's events
- {
- found_group = found_group[0];
- found_group.events.push(event);
- }
- }
- }
- });
- // console.debug(data);
- var courses = $('#courses').empty();
- Object.keys(data).forEach(function (id)
- {
- data[id].forEach(function (common)
- {
- var common_e = $('<li><b><small>' + common.ects + '</small> ' + common.name + '</b></li>');
- var list = $('<ul>').appendTo(common_e);
- common.groups.forEach(function (group)
- {
- group.checkbox = $('<label class="custom-control custom-checkbox"><input type="checkbox" class="custom-control-input"/><span class="custom-control-indicator"></span><span class="custom-control-description">' + group.group + group.group_extra + '</span></label>');
- group.checkbox.find('input').prop('checked', true);
- list.append($('<li>').append(group.checkbox));
- });
- courses.append(common_e);
- });
- });
- step(3);
- }
- catch (e)
- {
- console.log(e);
- }
- return false;
- }
- function selectGroups()
- {
- try
- {
- // console.info(data);
- var icalLines = ["BEGIN:VCALENDAR", "VERSION:2.0"];
- Object.keys(data).forEach(function (id)
- {
- data[id].forEach(function (common)
- {
- // console.debug('common');
- // console.debug(common);
- common.groups.forEach(function (group)
- {
- // console.debug('group');
- // console.debug(group);
- if (group.checkbox.find('input').prop('checked'))
- {
- var events = group.events;
- events.forEach(function (event) {
- // console.debug('event');
- // console.debug(event);
- icalLines.push(
- "BEGIN:VEVENT",
- "CLASS:PUBLIC",
- "DESCRIPTION:By " + event.teachers,
- "DTSTART;VALUE=DATE-TIME:" + event.start,
- "DTEND;VALUE=DATE-TIME:" + event.end,
- "LOCATION:" + event.location,
- "SUMMARY:" + common.name + ' (' + group.group + group.group_extra + ')',
- "TRANSP:TRANSPARENT",
- "END:VEVENT");
- });
- }
- });
- });
- });
- icalLines.push("END:VCALENDAR");
- output = icalLines.join("\r\n");
- $("#download").html('<div class="btn-group">' +
- '<button class="btn btn-primary" onclick="downloadIcal();">Download!</butt>' +
- '<button class="btn btn-secondary" onclick="showIcal();">Show iCal as text</butt>' +
- '</div>');
- step(4);
- }
- catch (e)
- {
- console.log(e);
- }
- return false;
- }
- function step(id)
- {
- id = id - 1;
- steps.forEach(function (t, i)
- {
- if (id == i) t.show();
- else t.hide();
- });
- }
- </script>
- </head>
- <body>
- <div class="container">
- <h1>KUL2iCal</h1>
- <p class="lead">Be careful with this tool, the iCal file doesn't magically update when changes are made in KULoket!<br>
- I recommend you use <a href="https://quivr.be/en/">quivr</a> or setup <a href="https://admin.kuleuven.be/icts/config/android/tablet/mail-config-android-t">account synchronisation</a> on your phone.</p>
- <p>Follow the instructions step by step. You can go back by clicking on the grey button with the step number.</p>
- <h2><button type="button" class="btn btn-outline-secondary btn-sm" onclick="step(1)">Step 1</button> Options</h2>
- <div id="step1">
- <p>This page can get slow if the range of data is too big. You can import multiple iCal files into 1 calender in Google Calender.</p>
- <form onsubmit="return makeUrl();">
- <div class="form-group">
- <label for="start" class="control-label">Start date</label>
- <input class="form-control" type="date" name="start" id="start" placeholder="YYYY-MM-DD">
- </div>
- <div class="form-group">
- <label for="end" class="control-label">End date</label>
- <input class="form-control" type="date" name="end" id="end" placeholder="YYYY-MM-DD">
- </div>
- <div class="checkbox">
- <label>
- <input type="checkbox" id="locations" value="" checked="">
- Include Locations
- </label>
- </div>
- <div class="checkbox">
- <label>
- <input type="checkbox" id="teachers" value="" checked="">
- Include Teachers
- </label>
- </div>
- <div class="form-group">
- <button type="submit" class="btn btn-primary">Next</button>
- </div>
- </form>
- </div>
- <h2><button type="button" class="btn btn-outline-secondary btn-sm" onclick="step(2)">Step 2</button> Get the data</h2>
- <div id="step2" style="display: none;">
- <p>Click the link below. It will open in a new tab.<br>
- You will be prompted to log in if you are not already.</p>
- <p id="link"><em>The link will appear here when you click 'Go' in step 1.</em></p>
- <p>If the data looks way too short (something like <code>{"d":{"results":[]}}</code>) pick a later start date or sooner end date.<br>
- This happens when one of the dates are in a different semester (according to KU Loket).</p>
- <form onsubmit="return parseJson();">
- <label for="json">Click link above & copy ALL of the data into the textbox below.</label>
- <div class="form-group">
- <textarea id="json" class="form-control" rows="10"></textarea>
- </div>
- <div class="form-group">
- <button type="submit" class="btn btn-primary">Next</button>
- </div>
- </form>
- </div>
- <h2><button type="button" class="btn btn-outline-secondary btn-sm" onclick="step(3)">Step 3</button> Select wanted groups</h2>
- <div id="step3" style="display: none;">
- <form onsubmit="return selectGroups();">
- <label for="courses">Select the events you'd like to export:</label>
- <div class="form-group">
- <ul id="courses">
- <li style="list-style: none"><em>Data will appear after adding data in step 3.</em></li>
- </ul>
- </div>
- <div class="form-group">
- <button type="submit" class="btn btn-primary">Next</button>
- </div>
- </form>
- </div>
- <h2><button type="button" class="btn btn-outline-secondary btn-sm" onclick="step(4)">Step 4</button> Download the iCal file</h2>
- <div id="step4" style="display: none;">
- <p><b>Thank you for using Dries007's KUL2iCal. Have a good semester!</b></p>
- <p id="download"><em>The download button will appear here when you click 'Go' in step 2.</em></p>
- <p>If the download button doesn't work, copy and save all of the iCal text as 'KUL.ics'.</p>
- </div>
- </div>
- <footer>
- <div class="container">
- <p class="text-muted">
- © 2015-2017 <a href="http://dries007.net">Dries007.net</a> See source for more info —
- This script works entirely in your browser. No data is send back to my server.
- </p>
- </div>
- </footer>
- </body>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement