From 319f83afaf342a45bb714e3c293110115df4ec82 Mon Sep 17 00:00:00 2001 From: Sura Hanna Date: Wed, 16 Oct 2024 17:45:47 -0400 Subject: [PATCH] implemented our own quotes DB via a json object --- frontend-dev/vwss-frontend/frontend.js | 36 +++-- public/assets/index-CWJf9nUx.js | 1 - public/assets/index-HtVCQZEd.js | 1 + public/index.html | 2 +- quotes.json | 210 +++++++++++++++++++++++++ server.js | 123 +++++++++------ 6 files changed, 306 insertions(+), 67 deletions(-) delete mode 100644 public/assets/index-CWJf9nUx.js create mode 100644 public/assets/index-HtVCQZEd.js create mode 100644 quotes.json diff --git a/frontend-dev/vwss-frontend/frontend.js b/frontend-dev/vwss-frontend/frontend.js index 9f83184..7cadc83 100644 --- a/frontend-dev/vwss-frontend/frontend.js +++ b/frontend-dev/vwss-frontend/frontend.js @@ -127,28 +127,38 @@ function updateFontSize(elementId) { // Function to fetch and display a quote async function fetchAndDisplayQuote() { try { - const response = await fetch('http://localhost:8080/api/quotes'); + // Update the endpoint if you created a new one + const response = await fetch('http://localhost:8080/api/quotes'); // or '/api/quotes/random' if (response.ok) { - const data = await response.json(); - const quotes = data.results; - const randomIndex = Math.floor(Math.random() * quotes.length); - const randomQuote = quotes[randomIndex]; - - document.getElementById('quote').innerHTML = `${randomQuote.content}`; - updateFontSize('quote'); - document.getElementById('author').innerHTML = `${randomQuote.author}`; + 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 { - document.getElementById('quote').innerHTML = `Wishing you an utmost wonderful day!`; - updateFontSize('quote'); - document.getElementById('author').innerHTML = `Next-Generation Cities Institute`; + 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('http://localhost:8080/api/weather'); @@ -258,7 +268,7 @@ setInterval(function() { }, 600000); fetchAndDisplayQuote(); -setInterval(fetchAndDisplayQuote, 60 * 60 * 1000); +setInterval(fetchAndDisplayQuote, 60 * 60 * 1000 * 24); fetchWeather(); setInterval(fetchWeather, 5 * 60 * 1000); diff --git a/public/assets/index-CWJf9nUx.js b/public/assets/index-CWJf9nUx.js deleted file mode 100644 index cec8562..0000000 --- a/public/assets/index-CWJf9nUx.js +++ /dev/null @@ -1 +0,0 @@ -(function(){const e=document.createElement("link").relList;if(e&&e.supports&&e.supports("modulepreload"))return;for(const t of document.querySelectorAll('link[rel="modulepreload"]'))r(t);new MutationObserver(t=>{for(const s of t)if(s.type==="childList")for(const i of s.addedNodes)i.tagName==="LINK"&&i.rel==="modulepreload"&&r(i)}).observe(document,{childList:!0,subtree:!0});function o(t){const s={};return t.integrity&&(s.integrity=t.integrity),t.referrerPolicy&&(s.referrerPolicy=t.referrerPolicy),t.crossOrigin==="use-credentials"?s.credentials="include":t.crossOrigin==="anonymous"?s.credentials="omit":s.credentials="same-origin",s}function r(t){if(t.ep)return;t.ep=!0;const s=o(t);fetch(t.href,s)}})();function N(n,e,o){e.sort((i,d)=>new Date(i.start.dateTime)-new Date(d.start.dateTime));const r=document.createElement("div");r.className="resource-wrapper";const t=document.createElement("div");switch(t.className="title-row",n.split("@")[0]){case"s-er-1431-00":t.innerHTML="ER 1431-00 Open Space";break;case"s-er-1431-03":t.innerHTML="ER 1431-03 Visualization Lab";break;case"s-er-1431-33":t.innerHTML="ER 1431-33 Ideation Room";break;case"s-er-1431-37":t.innerHTML="ER 1431-37 Multipurpose Room";break;case"s-er-1431-39":t.innerHTML="ER 1431-39 Conference Room";break}r.appendChild(t);const s=document.createElement("div");if(s.className="event-row",e.forEach((i,d)=>{if(d<3){const c=document.createElement("div");c.className="flex-cell";const I=i.subject.length>18?i.subject.substring(0,18)+"...":i.subject,L=!i.location.displayName||i.organizer.emailAddress.address===n?"Walk-Up":i.organizer.emailAddress.name,M=p(i.start.dateTime+"Z"),H=p(i.end.dateTime+"Z");if(new Date(i.end.dateTime)>new Date){const f=document.createElement("div");f.textContent=I;const m=document.createElement("div");m.textContent=L,m.className="organizer";const u=document.createElement("div");u.className="time-range",u.innerHTML=`${M} - ${H}`,c.appendChild(f),c.appendChild(m),c.appendChild(u),s.appendChild(c)}}}),s.children.length===0){const i=document.createElement("div");i.className="flex-cell",i.textContent="No upcoming meetings at this time",s.appendChild(i)}r.appendChild(s),o.appendChild(r)}function p(n){const e=new Date(n),o=e.getHours(),r=e.getMinutes().toString().padStart(2,"0");return`${o}:${r}`}async function E(){console.log("fetching events");const e=await(await fetch("http://localhost:8080/api/events")).json(),o=document.getElementById("resources-container");o.innerHTML="",Object.keys(e).forEach(t=>{N(t,e[t],o)})}function T(n){let e=p(new Date);n||(e=e.replace(":"," ")),document.getElementById("time").innerHTML=e}function w(n){const e=document.getElementById(n),o=e.textContent.length;o<=83?e.style.fontSize="5em":o<=166?e.style.fontSize="4em":e.style.fontSize="3em"}async function C(){try{const n=await fetch("http://localhost:8080/api/quotes");if(n.ok){const o=(await n.json()).results,r=Math.floor(Math.random()*o.length),t=o[r];document.getElementById("quote").innerHTML=`${t.content}`,w("quote"),document.getElementById("author").innerHTML=`${t.author}`}else document.getElementById("quote").innerHTML="Wishing you an utmost wonderful day!",w("quote"),document.getElementById("author").innerHTML="Next-Generation Cities Institute"}catch(n){console.error("An error occurred:",n)}}async function b(){const e=await(await fetch("http://localhost:8080/api/weather")).json();if(e.cod===200){const o=e.main.temp,r=e.weather[0].description,s=`https://openweathermap.org/img/wn/${e.weather[0].icon}.png`;document.getElementById("weather-icon-container").innerHTML=`Weather Icon`,document.getElementById("temperature").innerHTML=`${o}°`,document.getElementById("description").innerHTML=`${r}`}else document.getElementById("weather").innerText="Weather data unavailable"}async function S(){try{const n=await fetch("http://localhost:8080/api/slideshow");if(!n.ok)throw new Error("Failed to fetch slideshow images");const e=await n.json();v(e)}catch(n){console.error("Error fetching slideshow images:",n)}}function k(n){const e=document.createElement("img");e.src=`http://localhost:8080${n}`,e.className="slideshow-img",e.style.width="100%",e.style.maxHeight="100vh",e.style.objectFit="cover";const o=n.split("/").pop().split(".")[0];return e.alt=o,e.title=o,e}let h=0;function v(n){if(n.length===0){console.log("No images found for the slideshow.");return}const e=document.getElementById("slideshow");e.innerHTML="";const o=k(n[h]);e.appendChild(o),setTimeout(()=>{o.style.opacity="1"},100),setTimeout(()=>{for(;e.children.length>1;)e.removeChild(e.firstChild)},100),h=(h+1)%n.length,setTimeout(()=>v(n),3e4)}const g=document.getElementById("welcome-message"),x=document.querySelector("#welcome-message img"),y=["#00ADEF","#912338","#e5a712","#db0272","#8cc63e","#573996"],B=["black","white","black","white","black","white"];let a=0;function D(){g.classList.add("visible"),g.style.backgroundColor=y[a],x.src=B[a]==="white"?"ngci-logo-white-wide.svg":"ngci-logo-black.png",a=(a+1)%y.length}function $(){g.classList.remove("visible")}setInterval(function(){D(),setTimeout($,3e4)},6e5);C();setInterval(C,60*60*1e3);b();setInterval(b,5*60*1e3);let l=!0;T(l);setInterval(()=>{T(l),l=!l},1e3);S();E();setInterval(E,3*60*1e3); diff --git a/public/assets/index-HtVCQZEd.js b/public/assets/index-HtVCQZEd.js new file mode 100644 index 0000000..0fde532 --- /dev/null +++ b/public/assets/index-HtVCQZEd.js @@ -0,0 +1 @@ +(function(){const e=document.createElement("link").relList;if(e&&e.supports&&e.supports("modulepreload"))return;for(const n of document.querySelectorAll('link[rel="modulepreload"]'))r(n);new MutationObserver(n=>{for(const s of n)if(s.type==="childList")for(const i of s.addedNodes)i.tagName==="LINK"&&i.rel==="modulepreload"&&r(i)}).observe(document,{childList:!0,subtree:!0});function o(n){const s={};return n.integrity&&(s.integrity=n.integrity),n.referrerPolicy&&(s.referrerPolicy=n.referrerPolicy),n.crossOrigin==="use-credentials"?s.credentials="include":n.crossOrigin==="anonymous"?s.credentials="omit":s.credentials="same-origin",s}function r(n){if(n.ep)return;n.ep=!0;const s=o(n);fetch(n.href,s)}})();function D(t,e,o){e.sort((i,d)=>new Date(i.start.dateTime)-new Date(d.start.dateTime));const r=document.createElement("div");r.className="resource-wrapper";const n=document.createElement("div");switch(n.className="title-row",t.split("@")[0]){case"s-er-1431-00":n.innerHTML="ER 1431-00 Open Space";break;case"s-er-1431-03":n.innerHTML="ER 1431-03 Visualization Lab";break;case"s-er-1431-33":n.innerHTML="ER 1431-33 Ideation Room";break;case"s-er-1431-37":n.innerHTML="ER 1431-37 Multipurpose Room";break;case"s-er-1431-39":n.innerHTML="ER 1431-39 Conference Room";break}r.appendChild(n);const s=document.createElement("div");if(s.className="event-row",e.forEach((i,d)=>{if(d<3){const c=document.createElement("div");c.className="flex-cell";const L=i.subject.length>18?i.subject.substring(0,18)+"...":i.subject,M=!i.location.displayName||i.organizer.emailAddress.address===t?"Walk-Up":i.organizer.emailAddress.name,H=p(i.start.dateTime+"Z"),S=p(i.end.dateTime+"Z");if(new Date(i.end.dateTime)>new Date){const g=document.createElement("div");g.textContent=L;const m=document.createElement("div");m.textContent=M,m.className="organizer";const u=document.createElement("div");u.className="time-range",u.innerHTML=`${H} - ${S}`,c.appendChild(g),c.appendChild(m),c.appendChild(u),s.appendChild(c)}}}),s.children.length===0){const i=document.createElement("div");i.className="flex-cell",i.textContent="No upcoming meetings at this time",s.appendChild(i)}r.appendChild(s),o.appendChild(r)}function p(t){const e=new Date(t),o=e.getHours(),r=e.getMinutes().toString().padStart(2,"0");return`${o}:${r}`}async function E(){console.log("fetching events");const e=await(await fetch("http://localhost:8080/api/events")).json(),o=document.getElementById("resources-container");o.innerHTML="",Object.keys(e).forEach(n=>{D(n,e[n],o)})}function T(t){let e=p(new Date);t||(e=e.replace(":"," ")),document.getElementById("time").innerHTML=e}function v(t){const e=document.getElementById(t),o=e.textContent.length;o<=83?e.style.fontSize="5em":o<=166?e.style.fontSize="4em":e.style.fontSize="3em"}async function C(){try{const t=await fetch("http://localhost:8080/api/quotes");if(t.ok){const e=await t.json();if(e&&e.quote&&e.author)document.getElementById("quote").innerHTML=`${e.quote}`,v("quote"),document.getElementById("author").innerHTML=`${e.author}`;else throw new Error("Invalid quote data received")}else console.error("Server responded with status:",t.status),w()}catch(t){console.error("An error occurred:",t),w()}}function w(){document.getElementById("quote").innerHTML="Wishing you an utmost wonderful day!",v("quote"),document.getElementById("author").innerHTML="Next-Generation Cities Institute"}async function b(){const e=await(await fetch("http://localhost:8080/api/weather")).json();if(e.cod===200){const o=e.main.temp,r=e.weather[0].description,s=`https://openweathermap.org/img/wn/${e.weather[0].icon}.png`;document.getElementById("weather-icon-container").innerHTML=`Weather Icon`,document.getElementById("temperature").innerHTML=`${o}°`,document.getElementById("description").innerHTML=`${r}`}else document.getElementById("weather").innerText="Weather data unavailable"}async function N(){try{const t=await fetch("http://localhost:8080/api/slideshow");if(!t.ok)throw new Error("Failed to fetch slideshow images");const e=await t.json();I(e)}catch(t){console.error("Error fetching slideshow images:",t)}}function k(t){const e=document.createElement("img");e.src=`http://localhost:8080${t}`,e.className="slideshow-img",e.style.width="100%",e.style.maxHeight="100vh",e.style.objectFit="cover";const o=t.split("/").pop().split(".")[0];return e.alt=o,e.title=o,e}let h=0;function I(t){if(t.length===0){console.log("No images found for the slideshow.");return}const e=document.getElementById("slideshow");e.innerHTML="";const o=k(t[h]);e.appendChild(o),setTimeout(()=>{o.style.opacity="1"},100),setTimeout(()=>{for(;e.children.length>1;)e.removeChild(e.firstChild)},100),h=(h+1)%t.length,setTimeout(()=>I(t),3e4)}const f=document.getElementById("welcome-message"),B=document.querySelector("#welcome-message img"),y=["#00ADEF","#912338","#e5a712","#db0272","#8cc63e","#573996"],x=["black","white","black","white","black","white"];let a=0;function $(){f.classList.add("visible"),f.style.backgroundColor=y[a],B.src=x[a]==="white"?"ngci-logo-white-wide.svg":"ngci-logo-black.png",a=(a+1)%y.length}function q(){f.classList.remove("visible")}setInterval(function(){$(),setTimeout(q,3e4)},6e5);C();setInterval(C,60*60*1e3*24);b();setInterval(b,5*60*1e3);let l=!0;T(l);setInterval(()=>{T(l),l=!l},1e3);N();E();setInterval(E,3*60*1e3); diff --git a/public/index.html b/public/index.html index e8d1a02..8d0cfc0 100644 --- a/public/index.html +++ b/public/index.html @@ -6,7 +6,7 @@ NGCI Daily Schedule - + diff --git a/quotes.json b/quotes.json new file mode 100644 index 0000000..461a509 --- /dev/null +++ b/quotes.json @@ -0,0 +1,210 @@ +[ + { + "quote": "Architecture is the very mirror of life. You only have to cast your eyes on buildings to feel the presence of the past, the spirit of a place.", + "author": "I.M. Pei" + }, + { + "quote": "We don’t need a handful of people doing zero waste perfectly. We need millions of people doing it imperfectly.", + "author": "Anne Marie Bonneau" + }, + { + "quote": "By being sweet to the pedestrian and the cyclist you hit five birds with one stone – you get a lively, attractive, safe, sustainable city that’s good for health.", + "author": "Jan Gehl" + }, + { + "quote": "The ultimate test of man’s conscience may be his willingness to sacrifice something today for future generations whose words of thanks will not be heard.", + "author": "Gaylord Nelson" + }, + { + "quote": "When we destroy something created by man, we call it vandalism. When we destroy something created by nature, we call it progress.", + "author": "Ed Begley Jr." + }, + { + "quote": "You cannot get through a single day without having an impact on the world around you. What you do makes a difference and you have to decide what kind of a difference you want to make.", + "author": "Jane Goodall" + }, + { + "quote": "As an architect, you design for the present, with an awareness of the past, for a future which is essentially unknown.", + "author": "Norman Foster" + }, + { + "quote": "Every day I wake up in Copenhagen I know the city will be a little bit better than yesterday.", + "author": "Jan Gehl" + }, + { + "quote": "The architect’s role is to fight for a better world, where he can produce an architecture that serves everyone and not just a group of privileged people.", + "author": "Oscar Niemeyer" + }, + { + "quote": "Going back to a simpler life based on living by sufficiency rather than excess is not a step backwards.", + "author": "Yvon Chouinard" + }, + { + "quote": "Consume less; share better.", + "author": "Hervé Kempf" + }, + { + "quote": "We never know the worth of water till the well is dry.", + "author": "Thomas Fuller" + }, + { + "quote": "First life, then spaces, then buildings – the other way around never works.", + "author": "Jan Gehl" + }, + { + "quote": "It seems to me that the natural world is the greatest source of excitement; the greatest source of visual beauty.", + "author": "David Attenborough" + }, + { + "quote": "Space and light and order. Those are the things that men need just as much as they need bread or a place to sleep.", + "author": "Le Corbusier" + }, + { + "quote": "The Sun never knew how great it was until it hit the side of a building.", + "author": "Louis Kahn" + }, + { + "quote": "Simplicity is the ultimate sophistication.", + "author": "Leonardo da Vinci" + }, + { + "quote": "Our planet’s alarm is going off, and it is time to wake up and take action!", + "author": "Leonardo DiCaprio" + }, + { + "quote": "An endless number of green buildings don’t make a sustainable city.", + "author": "Jan Gehl" + }, + { + "quote": "We are all crew on spaceship Earth.", + "author": "Marshall McLuhan" + }, + { + "quote": "The best way to predict the future is to design it.", + "author": "Buckminster Fuller" + }, + { + "quote": "A city is more than a place in space, it is a drama in time.", + "author": "Patrick Geddes" + }, + { + "quote": "A great building must begin with the unmeasurable, must go through measurable means when it is being designed and in the end must be unmeasurable.", + "author": "Louis Kahn" + }, + { + "quote": "The mother art is architecture. Without an architecture of our own we have no soul of our own civilization.", + "author": "Frank Lloyd Wright" + }, + { + "quote": "Sustainability is no longer about doing less harm. It’s about doing more good.", + "author": "Jochen Zeitz" + }, + { + "quote": "Sustainable development is the pathway to the future we want for all.", + "author": "Ban Ki-moon" + }, + { + "quote": "The greatest threat to our planet is the belief that someone else will save it.", + "author": "Robert Swan" + }, + { + "quote": "The future depends on what you do today.", + "author": "Mahatma Gandhi" + }, + { + "quote": "Buildings should serve people, not the other way around.", + "author": "John Portman" + }, + { + "quote": "Urbanization is not an evil, but it becomes a problem when it is unplanned.", + "author": "Sheikh Hasina" + }, + { + "quote": "Architecture should speak of its time and place, but yearn for timelessness.", + "author": "Frank Gehry" + }, + { + "quote": "We shape our buildings; thereafter, they shape us.", + "author": "Winston Churchill" + }, + { + "quote": "We cannot solve our problems with the same thinking we used when we created them.", + "author": "Albert Einstein" + }, + { + "quote": "Less is more.", + "author": "Ludwig Mies van der Rohe" + }, + { + "quote": "Nature is not a place to visit. It is home.", + "author": "Gary Snyder" + }, + { + "quote": "The environment is where we all meet; where we all have a mutual interest; it is the one thing all of us share.", + "author": "Lady Bird Johnson" + }, + { + "quote": "The first rule of sustainability is to align with natural forces.", + "author": "Paul Hawken" + }, + { + "quote": "We do not inherit the earth from our ancestors, we borrow it from our children.", + "author": "Native American Proverb" + }, + { + "quote": "When we build, let us think that we build forever.", + "author": "John Ruskin" + }, + { + "quote": "A society grows great when old men plant trees whose shade they know they shall never sit in.", + "author": "Greek Proverb" + }, + { + "quote": "In the end, our society will be defined not only by what we create, but by what we refuse to destroy.", + "author": "John Sawhill" + }, + { + "quote": "What is the use of a house if you haven't got a tolerable planet to put it on?", + "author": "Henry David Thoreau" + }, + { + "quote": "Sustainability is about ecology, economy, and equity.", + "author": "Ralph Bicknese" + }, + { + "quote": "The Earth is what we all have in common.", + "author": "Wendell Berry" + }, + { + "quote": "Adopt the pace of nature: her secret is patience.", + "author": "Ralph Waldo Emerson" + }, + { + "quote": "Cities have the capability of providing something for everybody, only because they are created by everybody.", + "author": "Jane Jacobs" + }, + { + "quote": "Good buildings come from good people, and all problems are solved by good design.", + "author": "Stephen Gardiner" + }, + { + "quote": "Environmental pollution is an incurable disease. It can only be prevented.", + "author": "Barry Commoner" + }, + { + "quote": "Our future is at stake, and we have no option but to act decisively on climate change.", + "author": "Angela Merkel" + }, + { + "quote": "The future will either be green or not at all.", + "author": "Bob Brown" + }, + { + "quote": "The future belongs to those who believe in the beauty of their dreams.", + "author": "Eleanor Roosevelt" + }, + { + "quote": "To waste, to destroy our natural resources will result in undermining in the days of our children.", + "author": "Theodore Roosevelt" + } +] diff --git a/server.js b/server.js index 3cd2813..66c533f 100644 --- a/server.js +++ b/server.js @@ -1,3 +1,4 @@ +// Import necessary modules const express = require('express'); const http = require('http'); const fs = require('fs'); @@ -6,72 +7,85 @@ const path = require('path'); const cors = require('cors'); require('dotenv').config(); - +// Import custom modules const msGraphHelper = require('./msGraphHelper'); const settings = require('./settings'); +// Set the port const HTTP_PORT = process.env.HTTP_PORT || 8080; +// Initialize Express app const app = express(); -const slideshowDir = './slideshow'; - -app.use(express.static(path.join(__dirname, 'public'))); +const slideshowDir = path.join(__dirname, 'slideshow'); +// Middleware configurations +app.use(express.static(path.join(__dirname, 'public'))); app.use(cors({ - origin: 'http://localhost:5173' + origin: 'http://localhost:5173', })); app.use(express.json()); -app.use(express.static('public')); -// GRAPH API SECTION - USER AUTH -// -// msGraphHelper.initializeGraphForUserAuth(settings, async (deviceCodeResponse) => { -// if (!deviceCodeResponse) { -// throw new Error("Device code response is undefined."); -// } -// console.log(deviceCodeResponse.message); -// }); -// -// GRAPH API SECTION - APP ONLY AUTH -// +// Initialize Microsoft Graph API for App Only Auth msGraphHelper.initializeGraphForAppOnlyAuth(settings); + +// Read resource UPNs once at startup const data = fs.readFileSync('./resourceUPNs.json', 'utf8'); const resourceUPNs = JSON.parse(data); -app.get('/api/events', async (req, res) => { +// Cache quotes to avoid reading the file on every request +let quotesCache = []; +const quotesFilePath = path.join(__dirname, 'quotes.json'); +fs.readFile(quotesFilePath, 'utf8', (err, data) => { + if (err) { + console.error('Error reading quotes:', err.message); + } else { + try { + const parsedData = JSON.parse(data); + if (Array.isArray(parsedData) && parsedData.length > 0) { + quotesCache = parsedData; + console.log('Quotes loaded into cache.'); + } else { + console.error('Quotes file is empty or malformed.'); + } + } catch (parseError) { + console.error('Error parsing quotes:', parseError.message); + } + } +}); +// API endpoint to get events +app.get('/api/events', async (req, res) => { try { - let now = new Date(); - let startDateTime = new Date(now); - // startDateTime.setHours(8, 0, 0, 0); - let endDateTime = new Date(now); + const now = new Date(); + const startDateTime = new Date(now); + const endDateTime = new Date(now); endDateTime.setHours(20, 0, 0, 0); if (startDateTime > endDateTime) { - // Exit early since there are no relevant events to display + // No relevant events to display return res.json({}); } - let events = {}; + const events = {}; for (const resource of resourceUPNs) { try { - const data = - await msGraphHelper.getCalendarView(resource, startDateTime.toISOString(), endDateTime.toISOString()); - // fs.readFileSync(`./events/${resource}.json`, 'utf8'); - const resourceEvents = data; - events[resource] = resourceEvents; - // console.log(`${new Date()}: Grabbed events for ${resource}`); + const data = await msGraphHelper.getCalendarView( + resource, + startDateTime.toISOString(), + endDateTime.toISOString() + ); + events[resource] = data; } catch (error) { - console.error(error); + console.error(`Error fetching events for ${resource}:`, error); } } res.json(events); } catch (err) { res.status(500).json({ message: err.message }); } - }); +// API endpoint to get weather information app.get('/api/weather', async (req, res) => { try { const lat = 45.49; @@ -85,47 +99,52 @@ app.get('/api/weather', async (req, res) => { const json = await response.json(); res.json(json); } else { - res.status(500).json({ message: 'Error in /weather' }); + res.status(500).json({ message: 'Error fetching weather data' }); } } catch (err) { res.status(500).json({ message: err.message }); } }); -app.get('/api/quotes', async (req, res) => { +// API endpoint to get a random quote +app.get('/api/quotes', (req, res) => { try { - const url = `https://api.quotable.io/quotes?limit=150&tags=urban|city|technology|future` - const response = await fetch(url); - - if (response.ok) { - const json = await response.json(); - res.json(json); - } else { - res.status(500).json({ message: 'Error in /quotes' }); + if (quotesCache.length === 0) { + return res.status(500).json({ message: 'No quotes available' }); } + + const randomIndex = Math.floor(Math.random() * quotesCache.length); + const randomQuote = quotesCache[randomIndex]; + + res.json(randomQuote); // Send only one quote } catch (err) { - res.status(500).json({ message: err.message }); + res.status(500).json({ message: 'Error retrieving quote' }); } }); +// Serve slideshow images app.use('/slideshow', express.static(slideshowDir)); + +// API endpoint to get slideshow images app.get('/api/slideshow', (req, res) => { fs.readdir(slideshowDir, (err, files) => { if (err) { - console.error('Failed to list slideshow images: ', err.message); + console.error('Failed to list slideshow images:', err.message); res.status(500).json({ message: err.message }); return; - } else { - const imagePaths = files - .filter(file => /\.(jpg|jpeg|png|gif)$/i.test(file)) - .map(file => `/slideshow/${file}`); - - res.json(imagePaths); } + + const imagePaths = files + .filter(file => /\.(jpg|jpeg|png|gif)$/i.test(file)) + .map(file => `/slideshow/${file}`); + + res.json(imagePaths); }); }); - +// Create and start the HTTP server const httpServer = http.createServer(app); -httpServer.listen(HTTP_PORT, () => console.log(`HTTP Server listening on http://localhost:${HTTP_PORT}`)); +httpServer.listen(HTTP_PORT, () => { + console.log(`HTTP Server listening on http://localhost:${HTTP_PORT}`); +});