Hello,
In our company, we have an internal system where employees request (and get approved) their vacation. Internal system provides data about approved vacations across teams.
Requirement
Export all vacations into a single calendar, that can be subscribed by my cell phone
Solution
Integray provides more solutions. You can use for example ICS Writer Connector to produce ICS content, but i chose easier way (although it required some Javascript coding)
- Create Task with following steps
- Load vacation data from internal system
- Transform data into ICS format
- Bind such task to Integray Endpoint using GET method
- Copy endpoint URL and subscribe to it in any calendar application
Task
First step of this task pretty much depends on our internal system’s ability to provide data and it’s detail is out of scope of this solution
As a second step I used Node.js processor to transform vacations into ICS format and produce Endpoint File Output output schema.
// loaded from previous step
const loaded = inputData[0].ContentJSON;
/*
loaded data is returned from internal system and contains array of vacations in following schema
[
{
"start": "2023-11-01T14:27:23.130Z", // vacation start date
"end": "2023-11-01T14:27:23.130Z", // vacation end date
"title": "Libor Zoubek", // employee name
}
]
*/
/**
* format date to ICS date
*/
function formatDateToICal(date) {
date = new Date(date);
const year = date.getUTCFullYear();
const month = String(date.getUTCMonth() + 1).padStart(2, '0'); // Months are zero-based
const day = String(date.getUTCDate()).padStart(2, '0');
const hours = String(date.getUTCHours()).padStart(2, '0');
const minutes = String(date.getUTCMinutes()).padStart(2, '0');
const seconds = String(date.getUTCSeconds()).padStart(2, '0');
return `${year}${month}${day}T${hours}${minutes}${seconds}Z`;
}
// transform vacations into ICS events
const events = loaded.map((e) => {
const now = formatDateToICal(new Date());
// each event must have some uniqueID, as our system does not expose it
// it should be sufficient to calculate hash from `start`,`end` and `title`
const hash = crypto.createHash('sha256');
hash.update(`${e.start}${e.end}${e.title}`);
return `BEGIN:VEVENT
DTSTART:${formatDateToICal(e.start)}
DTEND:${formatDateToICal(e.end)}
DTSTAMP:${now}
UID:${hash.digest('hex')}
CREATED:${now}
LAST-MODIFIED:${now}
SEQUENCE:0
STATUS:CONFIRMED
SUMMARY:${e.title} - Vacation
TRANSP:OPAQUE
END:VEVENT
`;
})
// create ICS text content
const ics = `
BEGIN:VCALENDAR
PRODID:-//Google Inc//Google Calendar 70.9054//EN
VERSION:2.0
CALSCALE:GREGORIAN
METHOD:PUBLISH
X-WR-CALNAME:Integray team
X-WR-TIMEZONE:Europe/Prague
X-WR-CALDESC:Integray team vacation
BEGIN:VTIMEZONE
TZID:Europe/Prague
X-LIC-LOCATION:Europe/Prague
BEGIN:DAYLIGHT
TZOFFSETFROM:+0100
TZOFFSETTO:+0200
TZNAME:CEST
DTSTART:19700329T020000
RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU
END:DAYLIGHT
BEGIN:STANDARD
TZOFFSETFROM:+0200
TZOFFSETTO:+0100
TZNAME:CET
DTSTART:19701025T030000
RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU
END:STANDARD
END:VTIMEZONE
${events.join('\n')}
END:VCALENDAR
`;
// return as `Endpoint File Output` schema
return [{ Name: 'calendar.ics', Data: Buffer.from(ics).toString('base64') }]
Endpoint
Endpoint binding is easy to do, the only important thing is to select Endpoint File Output output schema
Voila … I am subscribed to vacations of all team members