Compare commits
7 Commits
e5216b24e1
...
f75001d03b
Author | SHA1 | Date |
---|---|---|
Ryan Mwangi | f75001d03b | |
Ryan Mwangi | 3d75b40018 | |
Ryan Mwangi | 0e2d6cac8a | |
Ryan Mwangi | 6441714568 | |
Ryan Mwangi | fa2dd50beb | |
Ryan Mwangi | c5b6fbaaaf | |
Ryan Mwangi | 89bd4582d1 |
38
index.html
38
index.html
|
@ -4,19 +4,38 @@
|
|||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Calendar Merger</title>
|
||||
<link rel="stylesheet" href="/styles.css">
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
}
|
||||
#calendars {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
#calendars .calendar {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
#calendars .calendar input[type="text"] {
|
||||
width: 50%;
|
||||
margin-right: 10px;
|
||||
}
|
||||
#calendars .calendar input[type="url"] {
|
||||
width: 50%;
|
||||
}
|
||||
#add-calendar {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Calendar Merger</h1>
|
||||
<form id="merge-form">
|
||||
<label for="cal1-url">Calendar 1 URL:</label>
|
||||
<input type="url" id="cal1-url" name="cal1-url"><br><br>
|
||||
<label for="cal1-prefix">Calendar 1 Prefix:</label>
|
||||
<input type="text" id="cal1-prefix" name="cal1-prefix"><br><br>
|
||||
<label for="cal2-url">Calendar 2 URL:</label>
|
||||
<input type="url" id="cal2-url" name="cal2-url"><br><br>
|
||||
<label for="cal2-prefix">Calendar 2 Prefix:</label>
|
||||
<input type="text" id="cal2-prefix" name="cal2-prefix"><br><br>
|
||||
<div id="calendars">
|
||||
<div class="calendar">
|
||||
<input type="text" id="prefix-0" placeholder="Prefix">
|
||||
<input type="url" id="url-0" placeholder="Calendar URL">
|
||||
</div>
|
||||
</div>
|
||||
<button id="add-calendar" type="button">Add Calendar</button>
|
||||
<button type="submit">Merge Calendars</button>
|
||||
</form>
|
||||
<div id="result"></div>
|
||||
|
@ -24,3 +43,4 @@
|
|||
<script src="script.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
|
67
script.js
67
script.js
|
@ -1,31 +1,42 @@
|
|||
const form = document.getElementById('merge-form');
|
||||
const resultDiv = document.getElementById('result');
|
||||
const calendars = document.getElementById('calendars');
|
||||
const addCalendarButton = document.getElementById('add-calendar');
|
||||
const result = document.getElementById('result');
|
||||
|
||||
form.addEventListener('submit', (e) => {
|
||||
e.preventDefault();
|
||||
const cal1Url = document.getElementById('cal1-url').value;
|
||||
const cal1Prefix = document.getElementById('cal1-prefix').value;
|
||||
const cal2Url = document.getElementById('cal2-url').value;
|
||||
const cal2Prefix = document.getElementById('cal2-prefix').value;
|
||||
let calendarIndex = 1;
|
||||
|
||||
fetch('/merge', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
cal1Url,
|
||||
cal1Prefix,
|
||||
cal2Url,
|
||||
cal2Prefix
|
||||
})
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then((data) => {
|
||||
resultDiv.innerHTML = `Merged calendar URL: <a href="${data.url}" target="_blank">${data.url}</a>`;
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
resultDiv.innerHTML = 'Error merging calendars';
|
||||
});
|
||||
});
|
||||
addCalendarButton.addEventListener('click', () => {
|
||||
const newCalendar = document.createElement('div');
|
||||
newCalendar.className = 'calendar';
|
||||
newCalendar.innerHTML = `
|
||||
<input type="text" id="prefix-${calendarIndex}" placeholder="Prefix">
|
||||
<input type="url" id="url-${calendarIndex}" placeholder="Calendar URL">
|
||||
`;
|
||||
calendars.appendChild(newCalendar);
|
||||
calendarIndex++;
|
||||
});
|
||||
|
||||
form.addEventListener('submit', (event) => {
|
||||
event.preventDefault();
|
||||
const calendarsData = [];
|
||||
for (let i = 0; i < calendarIndex; i++) {
|
||||
const prefix = document.getElementById(`prefix-${i}`).value;
|
||||
const url = document.getElementById(`url-${i}`).value;
|
||||
calendarsData.push({ prefix, url });
|
||||
}
|
||||
fetch('/merge', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({ calendars: calendarsData })
|
||||
})
|
||||
.then((response) => response.json())
|
||||
.then((data) => {
|
||||
result.innerHTML = `Merged calendar URL: <a href="${data.url}">${data.url}</a>`;
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
result.innerHTML = 'Error merging calendars';
|
||||
});
|
||||
});
|
53
server.js
53
server.js
|
@ -14,36 +14,46 @@ app.get('/', (req, res) => {
|
|||
});
|
||||
|
||||
app.post('/merge', async (req, res) => {
|
||||
const { cal1Url, cal1Prefix, cal2Url, cal2Prefix } = req.body;
|
||||
const { calendars } = req.body;
|
||||
|
||||
try {
|
||||
//validate the input
|
||||
if (!calendars || !Array.isArray(calendars)) {
|
||||
return res.status(400).json({ error: 'Invalid input' });
|
||||
}
|
||||
// Fetch calendar data from URLs
|
||||
const cal1Data = await axios.get(cal1Url);
|
||||
const cal2Data = await axios.get(cal2Url);
|
||||
const promises = calendars.map((calendar) => {
|
||||
return axios.get(calendar.url)
|
||||
.then((response) => {
|
||||
return {
|
||||
data: response.data,
|
||||
prefix: calendar.prefix,
|
||||
};
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
return null;
|
||||
});
|
||||
});
|
||||
|
||||
const results = await Promise.all(promises);
|
||||
// Filter out any failed requests
|
||||
const validResults = results.filter((result) => result !== null);
|
||||
|
||||
// Parse calendar data
|
||||
const cal1 = ical.parseICS(cal1Data.data);
|
||||
const cal2 = ical.parseICS(cal2Data.data);
|
||||
const mergedCal = [];
|
||||
|
||||
// Merge calendars
|
||||
Object.keys(cal1).forEach((key) => {
|
||||
let event = cal1[key];
|
||||
mergedCal.push({
|
||||
start: event.start,
|
||||
end: event.end,
|
||||
summary: `${cal1Prefix} ${event.summary}`,
|
||||
validResults.forEach((result) => {
|
||||
const calendar = ical.parseICS(result.data);
|
||||
Object.keys(calendar).forEach((key) => {
|
||||
const event = calendar[key];
|
||||
mergedCal.push({
|
||||
start: event.start,
|
||||
end: event.end,
|
||||
summary: `${result.prefix} ${event.summary}`,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Object.keys(cal2).forEach((key) => {
|
||||
let event = cal2[key];
|
||||
mergedCal.push({
|
||||
start: event.start,
|
||||
end: event.end,
|
||||
summary: `${cal2Prefix} ${event.summary}`,
|
||||
});
|
||||
});
|
||||
|
||||
// Save merged calendar to file
|
||||
const filename = `merged-${Date.now()}.ics`;
|
||||
|
@ -63,6 +73,7 @@ END:VEVENT
|
|||
icalString += `END:VCALENDAR`;
|
||||
fs.writeFileSync(filename, icalString);
|
||||
|
||||
|
||||
// Generate a unique URL for the merged calendar
|
||||
const mergedCalendarUrl = `${req.protocol}://${req.get('host')}/${filename}`;
|
||||
|
||||
|
|
Loading…
Reference in New Issue