function populateTable(resourceUPN, events, container) { events.sort((a, b) => new Date(a.start.dateTime) - new Date(b.start.dateTime)); // Create a wrapper for the resource and its events const resourceWrapper = document.createElement('div'); resourceWrapper.className = 'resource-wrapper'; // Create a row for the resource title const titleRow = document.createElement('div'); titleRow.className = 'title-row'; switch (resourceUPN.split("@")[0]) { case "s-er-1431-00": titleRow.innerHTML = 'ER 1431-00 Open Space'; break; case "s-er-1431-03": titleRow.innerHTML = 'ER 1431-03 Visualization Lab'; break; case "s-er-1431-33": titleRow.innerHTML = 'ER 1431-33 Ideation Room'; break; case "s-er-1431-37": titleRow.innerHTML = 'ER 1431-37 Multipurpose Room'; break; case "s-er-1431-39": titleRow.innerHTML = 'ER 1431-39 Conference Room'; break; } resourceWrapper.appendChild(titleRow); // Create a grid for events const eventGrid = document.createElement('div'); eventGrid.className = 'event-row'; events.forEach((event, index) => { if (index < 3) { const eventCell = document.createElement('div'); eventCell.className = 'flex-cell'; const title = event.subject.length > 18 ? event.subject.substring(0, 18) + "..." : event.subject; const organizer = !event.location.displayName || event.organizer.emailAddress.address === resourceUPN ? "Walk-Up" : event.organizer.emailAddress.name; const startTime = formatTime(event.start.dateTime + "Z"); const endTime = formatTime(event.end.dateTime + "Z"); const endTimeCheck = new Date(event.end.dateTime); const currentTime = new Date(); if (endTimeCheck > currentTime) { const titleDiv = document.createElement('div'); titleDiv.textContent = title; const organizerDiv = document.createElement('div'); organizerDiv.textContent = organizer; organizerDiv.className = 'organizer'; const timeDiv = document.createElement('div'); timeDiv.className = 'time-range'; timeDiv.innerHTML = `${startTime} - ${endTime}`; eventCell.appendChild(titleDiv); eventCell.appendChild(organizerDiv); eventCell.appendChild(timeDiv); eventGrid.appendChild(eventCell); } } }); if (eventGrid.children.length === 0) { const noEventsMessage = document.createElement('div'); noEventsMessage.className = 'flex-cell'; noEventsMessage.textContent = 'No upcoming meetings at this time'; eventGrid.appendChild(noEventsMessage); } resourceWrapper.appendChild(eventGrid); container.appendChild(resourceWrapper); } function formatTime(date) { const etDate = new Date(date); const hours = etDate.getHours(); const minutes = etDate.getMinutes().toString().padStart(2, '0'); return `${hours}:${minutes}`; } async function fetchAllEvents() { console.log("fetching events"); const response = await fetch('/api/events'); const allEvents = await response.json(); const resourcesContainer = document.getElementById('resources-container'); resourcesContainer.innerHTML = ''; const keys = Object.keys(allEvents); keys.forEach((key) => { populateTable(key, allEvents[key], resourcesContainer); }); } function updateTime(showSeparator) { let timeString = formatTime(new Date()); if (!showSeparator) { timeString = timeString.replace(':', ' '); } document.getElementById('time').innerHTML = timeString; } function updateFontSize(elementId) { const element = document.getElementById(elementId); const textLength = element.textContent.length; if (textLength <= 83) { element.style.fontSize = '5em'; } else if (textLength <= 166) { element.style.fontSize = '4em'; } else { element.style.fontSize = '3em'; } } // Function to fetch and display a quote async function fetchAndDisplayQuote() { try { // Update the endpoint if you created a new one const response = await fetch('/api/quotes'); // or '/api/quotes/random' if (response.ok) { const randomQuote = await response.json(); // Validate the received quote if (randomQuote && randomQuote.quote && randomQuote.author) { document.getElementById('quote').innerHTML = `${randomQuote.quote}`; updateFontSize('quote'); document.getElementById('author').innerHTML = `${randomQuote.author}`; } else { throw new Error('Invalid quote data received'); } } else { console.error('Server responded with status:', response.status); displayDefaultQuote(); } } catch (error) { console.error('An error occurred:', error); displayDefaultQuote(); } } // Helper function to display a default quote function displayDefaultQuote() { document.getElementById('quote').innerHTML = `Wishing you an utmost wonderful day!`; updateFontSize('quote'); document.getElementById('author').innerHTML = `Next-Generation Cities Institute`; } // Fetch Current Weather async function fetchWeather() { const response = await fetch('/api/weather'); const data = await response.json(); if (data.cod === 200) { const temperature = data.main.temp; const description = data.weather[0].description; const iconCode = data.weather[0].icon; const iconUrl = `https://openweathermap.org/img/wn/${iconCode}.png` document.getElementById("weather-icon-container").innerHTML = `Weather Icon`; document.getElementById("temperature").innerHTML = `${temperature}°`; document.getElementById("description").innerHTML = `${description}`; } else { document.getElementById("weather").innerText = 'Weather data unavailable'; } } // Display Current Time function displayTime() { const now = new Date(); const timeHtml = formatTime(now); document.getElementById("time").innerHTML = timeHtml; setTimeout(displayTime, 60000); } // Slideshow async function fetchSlideshowImages() { try { const response = await fetch('/api/slideshow'); if (!response.ok) { throw new Error('Failed to fetch slideshow images'); } const images = await response.json(); updateSlideshow(images); } catch (error) { console.error('Error fetching slideshow images:', error); } } function createSlideshowElement(src) { const img = document.createElement('img'); // img.src = src; img.src = `${src}`; img.className = 'slideshow-img'; img.style.width = '100%'; img.style.maxHeight = '100vh'; img.style.objectFit = 'cover'; const filename = src.split('/').pop().split('.')[0]; // Extracts filename without extension // Set the filename as the alt text img.alt = filename; // If you also want to set the title attribute img.title = filename; return img; } let currentIndex = 0; function updateSlideshow(images) { if (images.length === 0) { console.log('No images found for the slideshow.'); return; } const slideshowContainer = document.getElementById('slideshow'); slideshowContainer.innerHTML = ''; const imageElement = createSlideshowElement(images[currentIndex]); slideshowContainer.appendChild(imageElement); // Wait a little bit before starting the fade-in to ensure it's loaded setTimeout(() => { imageElement.style.opacity = '1'; }, 100); // Clean up the previous image after the new one has faded in setTimeout(() => { while (slideshowContainer.children.length > 1) { slideshowContainer.removeChild(slideshowContainer.firstChild); } }, 100); currentIndex = (currentIndex + 1) % images.length; setTimeout(() => updateSlideshow(images), 30000); // Change image every 30 seconds } const welcomeDiv = document.getElementById('welcome-message'); const logo = document.querySelector('#welcome-message img'); const backgroundColors = ['#00ADEF', '#912338', '#e5a712', '#db0272', '#8cc63e', '#573996']; const logoColors = ['black', 'white', 'black', 'white', 'black', 'white']; let colorIndex = 0; function showWelcomeMessage() { welcomeDiv.classList.add('visible'); welcomeDiv.style.backgroundColor = backgroundColors[colorIndex]; logo.src = logoColors[colorIndex] === 'white' ? 'ngci-logo-white-wide.svg' : 'ngci-logo-black.png'; colorIndex = (colorIndex + 1) % backgroundColors.length; } function hideWelcomeMessage() { welcomeDiv.classList.remove('visible'); } setInterval(function() { showWelcomeMessage(); setTimeout(hideWelcomeMessage, 30000); }, 600000); fetchAndDisplayQuote(); setInterval(fetchAndDisplayQuote, 60 * 60 * 1000 * 24); fetchWeather(); setInterval(fetchWeather, 5 * 60 * 1000); let showSeparator = true; updateTime(showSeparator); setInterval(() => { updateTime(showSeparator); showSeparator = !showSeparator; }, 1000); fetchSlideshowImages(); fetchAllEvents(); setInterval(fetchAllEvents, 3 * 60 * 1000);