Files
kursy-mirror/kursy/templates/calendar.html

144 lines
5.0 KiB
HTML

{% extends "base.html" %}
{% load i18n %}
{% block title %}{% trans "Course Calendar" %}{% endblock %}
{% block extra_js %}
<script src="https://cdn.jsdelivr.net/npm/fullcalendar@6.1.20/index.global.min.js" integrity="sha256-sQEgS6I+FEeOlX4oTVi7qW/HMRAh0O6vifpeZXIMRsg=" crossorigin="anonymous"></script>
<script>
function showModal(eventId) {
// get event's url
const eventApiUrl = `/api/calendar/events/${eventId}`;
const eventApi = fetch(eventApiUrl)
.then(response => response.json())
.then(data => {
eventUrl = data.url;
const modal = document.createElement('div');
modal.classList.add('fixed', 'inset-0', 'flex', 'items-center', 'justify-center', 'z-50', 'shadow-lg', 'overflow-auto');
modal.style.backgroundColor = 'rgba(0, 0, 0, 0.5)'; // semi-transparent background
const modalContent = document.createElement('div');
modalContent.classList.add('bg-white', 'rounded-lg', 'p-6', 'max-w-3xl', 'relative', 'overflow-auto', 'max-h-[80vh]');
modalContent.innerHTML = '<p class="text-gray-500">{% trans "Loading..." %}</p>';
if (eventUrl) {
fetch(eventUrl)
.then(response => response.text())
.then(html => {
modalContent.innerHTML = html;
})
.catch(error => {
modalContent.innerHTML = '<p class="text-red-500">Failed to load event details.</p>';
});
modal.appendChild(modalContent);
document.body.appendChild(modal);
// Close modal when clicking outside modalContent
modal.addEventListener('click', function(e) {
if (e.target === modal) {
document.body.removeChild(modal);
// remove ?modal=eventId from the url
const url = new URL(window.location);
url.searchParams.delete('modal');
window.history.pushState({}, '', url);
}
});
// Close modal on ESC key
document.addEventListener('keydown', function escHandler(e) {
if (e.key === 'Escape') {
if (document.body.contains(modal)) {
document.body.removeChild(modal);
}
document.removeEventListener('keydown', escHandler);
// remove ?modal=eventId from the url
const url = new URL(window.location);
url.searchParams.delete('modal');
window.history.pushState({}, '', url);
}
});
const closeButton = document.createElement('button');
closeButton.classList.add('absolute', 'top-2', 'right-2', 'text-red-500', 'cursor-pointer', 'hover:text-gray-700', 'text-5xl', 'translate-x-[-50%]');
closeButton.innerHTML = '&times;';
closeButton.addEventListener('click', function() {
if (document.body.contains(modal)) {
document.body.removeChild(modal);
}
// remove ?modal=eventId from the url
const url = new URL(window.location);
url.searchParams.delete('modal');
window.history.pushState({}, '', url);
});
modal.appendChild(closeButton);
// add ?modal=eventId to the url
const url = new URL(window.location);
url.searchParams.set('modal', eventId);
window.history.pushState({}, '', url);
}
return data;
})
.catch(error => {
console.error('Error fetching event details:', error);
return null;
});
}
document.addEventListener('DOMContentLoaded', function() {
var calendarEl = document.getElementById('calendar');
var calendar = new FullCalendar.Calendar(calendarEl, {
height: "auto",
initialView: 'timeGridWeek',
firstDay: 1,
nowIndicator: true,
views: {
timeGridWeek: {
titleFormat: { month: 'long', year: 'numeric' },
slotLabelFormat: { hour: '2-digit', minute: '2-digit' },
slotMinTime: '08:00:00',
slotMaxTime: '22:00:00',
},
listWeek: {
titleFormat: { month: 'long', year: 'numeric' },
listDaySideFormat: false,
},
},
headerToolbar: {
left: 'prev,next today',
center: 'title',
right: 'timeGridWeek,listMonth',
},
locale: "{% get_current_language as LANGUAGE_CODE %}{{ LANGUAGE_CODE }}",
events: "/api/calendar/events/",
eventClick: function(info) {
// prevent default navigation
info.jsEvent.preventDefault();
const eventUrl = info.event.url;
if (eventUrl) {
showModal(info.event.id);
}
},
});
calendar.render();
// if ?modal=event_id is in the url, open the modal for that event
const urlParams = new URLSearchParams(window.location.search);
const modalEventId = urlParams.get('modal');
if (modalEventId) {
showModal(modalEventId);
}
});
</script>
{% endblock %}
{% block content %}
<div class="overflow-auto">
<div id="calendar" class="min-w-xl"></div>
</div>
{% endblock %}