diff --git a/package-lock.json b/package-lock.json index cf3aac9..07d1927 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "@azure/identity": "^3.3.2", "@azure/msal-node": "^2.6.1", "@microsoft/microsoft-graph-client": "^3.0.7", + "cors": "^2.8.5", "dotenv": "^16.3.1", "express": "^4.18.2", "fs": "^0.0.1-security", @@ -213,9 +214,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.5.tgz", - "integrity": "sha512-Nms86NXrsaeU9vbBJKni6gXiEXZ4CVpYVzEjDH9Sb8vmZ3UljyA1GSOJl/6LGPO8EHLuSF9H+IxNXHPX8QHJ4g==", + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.6.tgz", + "integrity": "sha512-Ja18XcETdEl5mzzACGd+DKgaGJzPTCow7EglgwTmHdwokzDFYh/MHua6lU6DV/hjF2IaOJ4oX2nqnjG7RElKOw==", "dependencies": { "regenerator-runtime": "^0.14.0" }, @@ -384,6 +385,18 @@ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -991,6 +1004,14 @@ } } }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/object-inspect": { "version": "1.13.1", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", diff --git a/package.json b/package.json index fc26eb6..e2ad9df 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "@azure/identity": "^3.3.2", "@azure/msal-node": "^2.6.1", "@microsoft/microsoft-graph-client": "^3.0.7", + "cors": "^2.8.5", "dotenv": "^16.3.1", "express": "^4.18.2", "fs": "^0.0.1-security", diff --git a/public/assets/index-Dt4LGvko.css b/public/assets/index-Bq7sOAzP.css similarity index 80% rename from public/assets/index-Dt4LGvko.css rename to public/assets/index-Bq7sOAzP.css index c46a9b4..379bf95 100644 --- a/public/assets/index-Dt4LGvko.css +++ b/public/assets/index-Bq7sOAzP.css @@ -1 +1 @@ -:root{--font-size: 1vw;--width: 65vw;--img-margin: -2vw}@media (orientation: landscape){:root{--font-size: 1vh;--width: 65vh;--img-margin: -2vh}}*{margin:0;padding:0;box-sizing:border-box}html{height:100%;font-size:var(--font-size)}body{height:100%;font-family:Calibri,sans-serif;background-color:#000;color:#fff}.header{text-align:center;width:100%;flex-grow:0}.resource-wrapper{width:100%}.title-row{font-weight:700;font-size:3em;padding:.25em 0}.event-row{display:flex;flex-wrap:nowrap;overflow-x:hidden;font-size:3em}.flex-row{display:flex;flex-direction:row}.flex-cell{display:flex;flex-direction:column;flex-grow:1;flex-basis:33%;justify-content:start;align-items:left;margin-right:.5em}.organizer{font-weight:lighter;font-style:italic}.horizontal-logo{width:100%}#resources-container{width:100%;height:100%;overflow:hidden;display:flex;flex-direction:column;justify-content:space-between;flex-grow:1}#grid{display:grid;grid-template-columns:1fr 2fr 1fr;height:100%;width:100%}#schedule-container{height:100%;grid-column:1;padding:2em;display:flex;flex-direction:column}#schedule-container .header{margin-bottom:3em}#homepage-container{grid-column:3;padding:2em;text-align:center;display:flex;flex-direction:column;height:100%}.top-container{display:flex;flex-direction:column;justify-content:center;align-items:center;height:50%}#time-weather-container{display:grid;grid-template-columns:1fr 1fr;align-items:center;width:100%;font-size:5em;font-weight:700}.time{font-family:Calibri,sans-serif}.separator{font-family:Courier New,monospace}#slideshow{grid-column:2;overflow:hidden}.slideshow-img{transition:opacity .5s ease-in-out;opacity:0}#bottom-section{display:flex;flex-direction:column;justify-content:center;align-items:center}#weather-icon{align-self:end;width:2em;margin:var(--img-margin)}#temperature{align-self:start}#description{font-weight:lighter}#quote{font-size:5em;margin:0 10%;max-height:40vh;text-align:left}#author{margin-top:2.5%;font-size:4em;width:75%;text-align:right}#welcome-message{position:fixed;top:0;left:0;width:100%;height:100vh;background:linear-gradient(124deg,#ff7d68,#f17b7b,#f1d67b,#f0f17b,#7bf190,#7bebf1,#847bf1,#f370ff,#f8a9ff);background-size:1800% 1800%;animation:rainbow 30s ease infinite;justify-content:center;align-items:center;color:#fff;font-size:2em;display:flex;z-index:1001;padding:20em;opacity:0;transition:opacity 1s linear}#welcome-message.visible{opacity:1}@keyframes rainbow{0%{background-position:0% 82%}50%{background-position:100% 19%}to{background-position:0% 82%}} +:root{--font-size: 1vw;--width: 65vw;--img-margin: -2vw}@media (orientation: landscape){:root{--font-size: 1vh;--width: 65vh;--img-margin: -2vh}}*{margin:0;padding:0;box-sizing:border-box}html{height:100%;font-size:var(--font-size)}body{height:100%;font-family:Calibri,sans-serif;background-color:#000;color:#fff}.header{text-align:center;width:100%;flex-grow:0}.resource-wrapper{width:100%}.title-row{font-weight:700;font-size:3em;padding:.25em 0}.event-row{display:flex;flex-wrap:nowrap;overflow-x:hidden;font-size:3em}.flex-row{display:flex;flex-direction:row}.flex-cell{display:flex;flex-direction:column;flex-grow:1;flex-basis:33%;justify-content:start;align-items:left;margin-right:.5em}.organizer{font-weight:lighter;font-style:italic}.horizontal-logo{width:100%}#resources-container{width:100%;height:100%;overflow:hidden;display:flex;flex-direction:column;justify-content:space-between;flex-grow:1}#grid{display:grid;grid-template-columns:1fr 2fr 1fr;height:100%;width:100%}#schedule-container{height:100%;grid-column:1;padding:2em;display:flex;flex-direction:column}#schedule-container .header{margin-bottom:3em}#homepage-container{grid-column:3;padding:2em;text-align:center;display:flex;flex-direction:column;height:100%}.top-container{display:flex;flex-direction:column;justify-content:center;align-items:center;height:50%}#time-weather-container{display:grid;grid-template-columns:1fr 1fr;align-items:center;width:100%;font-size:5em;font-weight:700}.time{font-family:Calibri,sans-serif}.separator{font-family:Courier New,monospace}#slideshow{grid-column:2;overflow:hidden}.slideshow-img{transition:opacity .5s ease-in-out;opacity:0}#bottom-section{display:flex;flex-direction:column;justify-content:center;align-items:center}#weather-icon{align-self:end;width:2em;margin:var(--img-margin)}#temperature{align-self:start}#description{font-weight:lighter}#quote{font-size:5em;margin:0 10%;max-height:40vh;text-align:left}#author{margin-top:2.5%;font-size:4em;width:75%;text-align:right}#welcome-message{position:fixed;top:0;left:0;width:100%;height:100vh;background-color:#00adef;justify-content:center;align-items:center;color:#fff;font-size:2em;display:flex;z-index:1001;padding:20em;opacity:0;transition:opacity 1s linear}#welcome-message.visible{opacity:1} diff --git a/public/assets/index-DDszHAtm.js b/public/assets/index-DWgpMFbj.js similarity index 56% rename from public/assets/index-DDszHAtm.js rename to public/assets/index-DWgpMFbj.js index 8994576..e995a31 100644 --- a/public/assets/index-DDszHAtm.js +++ b/public/assets/index-DWgpMFbj.js @@ -1 +1 @@ -(function(){const e=document.createElement("link").relList;if(e&&e.supports&&e.supports("modulepreload"))return;for(const t of document.querySelectorAll('link[rel="modulepreload"]'))i(t);new MutationObserver(t=>{for(const s of t)if(s.type==="childList")for(const r of s.addedNodes)r.tagName==="LINK"&&r.rel==="modulepreload"&&i(r)}).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 i(t){if(t.ep)return;t.ep=!0;const s=o(t);fetch(t.href,s)}})();function M(n,e,o){e.sort((r,l)=>new Date(r.start.dateTime)-new Date(l.start.dateTime));const i=document.createElement("div");i.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}i.appendChild(t);const s=document.createElement("div");if(s.className="event-row",e.forEach((r,l)=>{if(l<3){const a=document.createElement("div");a.className="flex-cell";const v=r.subject.length>18?r.subject.substring(0,18)+"...":r.subject,C=!r.location.displayName||r.organizer.emailAddress.address===n?"Walk-Up":r.organizer.emailAddress.name,L=h(r.start.dateTime+"Z"),I=h(r.end.dateTime+"Z");if(new Date(r.end.dateTime)>new Date){const p=document.createElement("div");p.textContent=v;const d=document.createElement("div");d.textContent=C,d.className="organizer";const m=document.createElement("div");m.className="time-range",m.innerHTML=`${L} - ${I}`,a.appendChild(p),a.appendChild(d),a.appendChild(m),s.appendChild(a)}}}),s.children.length===0){const r=document.createElement("div");r.className="flex-cell",r.textContent="No upcoming meetings at this time",s.appendChild(r)}i.appendChild(s),o.appendChild(i)}function h(n){const e=new Date(n),o=e.getHours(),i=e.getMinutes().toString().padStart(2,"0");return`${o}:${i}`}async function f(){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=>{M(t,e[t],o)})}function g(n){let e=h(new Date);n||(e=e.replace(":"," ")),document.getElementById("time").innerHTML=e}function b(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 w(){try{const n=await fetch("http://localhost:8080/api/quotes");if(n.ok){const o=(await n.json()).results,i=Math.floor(Math.random()*o.length),t=o[i];document.getElementById("quote").innerHTML=`${t.content}`,b("quote"),document.getElementById("author").innerHTML=`${t.author}`}else console.error("Failed to fetch data")}catch(n){console.error("An error occurred:",n)}}async function y(){const e=await(await fetch("http://localhost:8080/api/weather")).json();if(e.cod===200){const o=e.main.temp,i=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=`${i}`}else document.getElementById("weather").innerText="Weather data unavailable"}async function H(){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();E(e)}catch(n){console.error("Error fetching slideshow images:",n)}}function N(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 u=0;function E(n){if(n.length===0){console.log("No images found for the slideshow.");return}const e=document.getElementById("slideshow");e.innerHTML="";const o=N(n[u]);e.appendChild(o),setTimeout(()=>{o.style.opacity="1"},100),setTimeout(()=>{for(;e.children.length>1;)e.removeChild(e.firstChild)},100),u=(u+1)%n.length,setTimeout(()=>E(n),3e4)}const T=document.getElementById("welcome-message");function S(){T.classList.add("visible")}function x(){T.classList.remove("visible")}setInterval(function(){S(),setTimeout(x,3e4)},6e5);w();setInterval(w,60*60*1e3);y();setInterval(y,5*60*1e3);let c=!0;g(c);setInterval(()=>{g(c),c=!c},1e3);H();f();setInterval(f,3*60*1e3); +(function(){const e=document.createElement("link").relList;if(e&&e.supports&&e.supports("modulepreload"))return;for(const t of document.querySelectorAll('link[rel="modulepreload"]'))i(t);new MutationObserver(t=>{for(const s of t)if(s.type==="childList")for(const r of s.addedNodes)r.tagName==="LINK"&&r.rel==="modulepreload"&&i(r)}).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 i(t){if(t.ep)return;t.ep=!0;const s=o(t);fetch(t.href,s)}})();function H(n,e,o){e.sort((r,d)=>new Date(r.start.dateTime)-new Date(d.start.dateTime));const i=document.createElement("div");i.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}i.appendChild(t);const s=document.createElement("div");if(s.className="event-row",e.forEach((r,d)=>{if(d<3){const c=document.createElement("div");c.className="flex-cell";const C=r.subject.length>18?r.subject.substring(0,18)+"...":r.subject,I=!r.location.displayName||r.organizer.emailAddress.address===n?"Walk-Up":r.organizer.emailAddress.name,L=p(r.start.dateTime+"Z"),M=p(r.end.dateTime+"Z");if(new Date(r.end.dateTime)>new Date){const g=document.createElement("div");g.textContent=C;const m=document.createElement("div");m.textContent=I,m.className="organizer";const u=document.createElement("div");u.className="time-range",u.innerHTML=`${L} - ${M}`,c.appendChild(g),c.appendChild(m),c.appendChild(u),s.appendChild(c)}}}),s.children.length===0){const r=document.createElement("div");r.className="flex-cell",r.textContent="No upcoming meetings at this time",s.appendChild(r)}i.appendChild(s),o.appendChild(i)}function p(n){const e=new Date(n),o=e.getHours(),i=e.getMinutes().toString().padStart(2,"0");return`${o}:${i}`}async function y(){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=>{H(t,e[t],o)})}function E(n){let e=p(new Date);n||(e=e.replace(":"," ")),document.getElementById("time").innerHTML=e}function S(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 T(){try{const n=await fetch("http://localhost:8080/api/quotes");if(n.ok){const o=(await n.json()).results,i=Math.floor(Math.random()*o.length),t=o[i];document.getElementById("quote").innerHTML=`${t.content}`,S("quote"),document.getElementById("author").innerHTML=`${t.author}`}else console.error("Failed to fetch data")}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,i=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=`${i}`}else document.getElementById("weather").innerText="Weather data unavailable"}async function k(){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 D(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=D(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 f=document.getElementById("welcome-message"),N=document.querySelector("#welcome-message img"),w=["#00ADEF","#912338","#e5a712","#db0272","#8cc63e","#573996"],x=["black","white","black","white","black","white"];let a=0;function B(){f.classList.add("visible"),f.style.backgroundColor=w[a],N.src=x[a]==="white"?"ngci-logo-white-wide.svg":"ngci-logo-black.png",a=(a+1)%w.length}function $(){f.classList.remove("visible")}setInterval(function(){B(),setTimeout($,3e4)},6e5);T();setInterval(T,60*60*1e3);b();setInterval(b,5*60*1e3);let l=!0;E(l);setInterval(()=>{E(l),l=!l},1e3);k();y();setInterval(y,3*60*1e3); diff --git a/public/index.html b/public/index.html index e139b93..e5affb4 100644 --- a/public/index.html +++ b/public/index.html @@ -6,13 +6,13 @@ NGCI Daily Schedule - - + +
- +
diff --git a/public/ngci-logo-black.png b/public/ngci-logo-black.png new file mode 100755 index 0000000..96249ba Binary files /dev/null and b/public/ngci-logo-black.png differ diff --git a/server.js b/server.js index 167a3a6..3cd2813 100644 --- a/server.js +++ b/server.js @@ -3,6 +3,7 @@ const http = require('http'); const fs = require('fs'); const fetch = require('isomorphic-fetch'); const path = require('path'); +const cors = require('cors'); require('dotenv').config(); @@ -16,9 +17,23 @@ const slideshowDir = './slideshow'; app.use(express.static(path.join(__dirname, 'public'))); +app.use(cors({ + 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 +// msGraphHelper.initializeGraphForAppOnlyAuth(settings); const data = fs.readFileSync('./resourceUPNs.json', 'utf8'); const resourceUPNs = JSON.parse(data); @@ -42,8 +57,10 @@ app.get('/api/events', async (req, res) => { 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}`); } catch (error) { console.error(error); }