Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding a loader #1575

Merged
merged 15 commits into from
Jan 30, 2025
2 changes: 1 addition & 1 deletion infinitefeed/templates/infinitefeed/infinitefeed.html
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,5 @@


<div id="loader" class="hide" {% if inactive %}inactive="True"{%endif%}>
<ion-icon name="refresh" class="spin"></ion-icon>
<img src="{% static '/ubyssey/images/throbber.svg' %}" class="spin" alt="Loading icon">
</div>
2,085 changes: 2,085 additions & 0 deletions package-lock.json

Large diffs are not rendered by default.

3,454 changes: 1,489 additions & 1,965 deletions ubyssey/static_src/package-lock.json

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions ubyssey/static_src/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,20 +50,22 @@
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-textarea-autosize": "^2.5.1",
"webpack": "^4.47.0",
"webpack-cli": "^3.3.12",
"webpack": "^5.97.1",
"webpack-cli": "^6.0.1",
"webpack-merge": "^4.2.1"
},
"engines": {
"node": ">=0.10"
},
"license": "MIT",
"dependencies": {
"@svgr/webpack": "^8.1.0",
"axios": "^1.7.4",
"global": "^4.3.2",
"gsap": "^3.12.5",
"js-cookie": "^2.2.0",
"node-sass": "^4.9.3",
"react-loader-spinner": "^6.1.6",
"react-router": "^6.26.1",
"react-router-dom": "^6.26.1",
"tough-cookie": "^2.3.4"
Expand Down
15 changes: 15 additions & 0 deletions ubyssey/static_src/src/images/throbber.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
145 changes: 86 additions & 59 deletions ubyssey/static_src/src/js/components/Events/calendar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ import {
useNavigate,
} from "react-router-dom";
// import ReactDOM from 'react-dom';
import axios from "axios";
import Throbber from '../../../images/throbber.svg';
import axios from 'axios';

const BP_DESKTOP_SIZE = 1199;

function useQuery() {
Expand All @@ -18,7 +20,6 @@ function useQuery() {
try {
return new URLSearchParams(search || "");
} catch (error) {
console.error("Failed to parse query params:", error);
return new URLSearchParams(); // Return an empty URLSearchParams object on failure
}
}, [search]);
Expand Down Expand Up @@ -68,6 +69,7 @@ export function QueryEventsCalendar() {
const [start, setStart] = useState(getInitialStartDate());
const [isDarkMode, setIsDarkMode] = useState(false);
const [isMonthToggled, setIsMonthToggled] = React.useState(false);
const [isLoading, setIsLoading] = React.useState(true);

function getDate(month, year) {
let newStartDate = new Date(year, month - 1, 1); // Month is 0-indexed
Expand Down Expand Up @@ -104,7 +106,6 @@ export function QueryEventsCalendar() {
const year = parseInt(urlParams.get("year"));
return getDate(month, year);
} else{
console.log("No month and year");
const today = new Date();
today.setHours(0, 0, 0, 0);

Expand All @@ -120,7 +121,6 @@ export function QueryEventsCalendar() {
let newStart = new Date(start);

// Adjust the month based on the direction
console.log(direction);
if (direction === 'next') {
newStart = new Date(newStart.getTime() + (40*d));
} else {
Expand All @@ -142,10 +142,8 @@ export function QueryEventsCalendar() {
// Function to update the start date to the week of the first day of the previous or next month
const handleMonthNavigation = (direction) => {

console.log("Handling month navigation");
let newStart, newMonth, newYear;
newStart = calculateNewStart(direction, start);
console.log("Handling month navigation");
newMonth = newStart.month;
newYear = newStart.year;

Expand All @@ -155,7 +153,6 @@ export function QueryEventsCalendar() {
window.history.pushState(null, '', `?${searchParams.toString()}`);

// Set the new start date and other logic
console.log("Navigating to", newMonth, newYear);
let newStartDate = new Date(newYear, newMonth - 1, 1); // Month is 0-indexed

if (
Expand Down Expand Up @@ -213,6 +210,7 @@ export function QueryEventsCalendar() {
}

setEvents(res);
setIsLoading(false);
})
.catch((err) => console.log(err));
}
Expand Down Expand Up @@ -248,13 +246,13 @@ export function QueryEventsCalendar() {
aria-label="auto"
aria-live="polite"
>
<svg className="sun-and-moon" aria-hidden="true" width="1.75em" height="1.75em" viewBox="0 0 24 24">
<mask className="moon" id="moon-mask">
<svg class="sun-and-moon" aria-hidden="true" width="1.75em" height="1.75em" viewBox="0 0 24 24">
<mask class="moon" id="moon-mask{{id}}">
<rect x="0" y="0" width="100%" height="100%" fill="white" />
<circle cx="24" cy="10" r="6" fill="black" />
</mask>
<circle className="sun" cx="12" cy="12" r="6" mask="url(#moon-mask)" fill="currentColor" />
<g className="sun-beams" stroke="currentColor">
<circle class="sun" cx="12" cy="12" r="6" mask="url(#moon-mask{{id}})" fill="currentColor" />
<g class="sun-beams" stroke="currentColor">
<line x1="12" y1="1" x2="12" y2="3" />
<line x1="12" y1="21" x2="12" y2="23" />
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64" />
Expand All @@ -264,7 +262,7 @@ export function QueryEventsCalendar() {
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36" />
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22" />
</g>
</svg>
</svg>
</button>
</div>
<h1 class="title">Events around campus</h1>
Expand All @@ -273,7 +271,7 @@ export function QueryEventsCalendar() {
</header>

<div id="calendar-rows">
<EventsCalendar events={events} start={start} setStart={setStart} numberOfWeeks={numberOfWeeks} setNumberOfWeeks={setNumberOfWeeks} isDarkMode={isDarkMode} setIsMobile={setIsDarkMode} getInitialStartDate={startDate} handleMonthNavigation={handleMonthNavigation} setIsMonthToggled={setIsMonthToggled} isMonthToggled={isMonthToggled}/>
<EventsCalendar events={events} start={start} setStart={setStart} numberOfWeeks={numberOfWeeks} setNumberOfWeeks={setNumberOfWeeks} isDarkMode={isDarkMode} setIsMobile={setIsDarkMode} getInitialStartDate={startDate} handleMonthNavigation={handleMonthNavigation} setIsMonthToggled={setIsMonthToggled} isMonthToggled={isMonthToggled} isLoading={isLoading}/>
</div>
</div>

Expand Down Expand Up @@ -542,7 +540,7 @@ function EventsOptions({getInitialStartDate, handleMonthNavigation, setIsMonthTo
);
}

function EventsCalendar({events, start, setStart, numberOfWeeks, setNumberOfWeeks, isDarkMode, setIsDarkMode, getInitialStartDate, handleMonthNavigation, setIsMonthToggled, isMonthToggled}) {
function EventsCalendar({events, start, setStart, numberOfWeeks, setNumberOfWeeks, isDarkMode, setIsDarkMode, getInitialStartDate, handleMonthNavigation, setIsMonthToggled, isMonthToggled, isLoading}) {

let query = useQuery();
const s = 1000
Expand Down Expand Up @@ -798,58 +796,79 @@ function EventsCalendar({events, start, setStart, numberOfWeeks, setNumberOfWeek
</>
)}
</div>
<div class={"events-calendar--rows" + (!isMonthToggled ? " today-calendar" : "")}>{calendar.map((week, week_index) =>

{isPhablet && isLoading &&
<div className="loader-container">
<LoaderComponent width={50}/>
</div>}

{calendar.map((week, week_index) => (
<div className={"events-calendar--row" + (week.this_week ? " enlarged" : "")}>
{week_index===0 &&
<h2 class="events-calendar--month">
{week_index === 0 && (
<h2 className="events-calendar--month">
<span className="full">{week.month}</span>
<span className="short">{week.month_short}</span>
</h2>
}
{week.days.map((day, day_index) =>
<>
{(day.day === 1 && week_index !== 0 && !(isMonthToggled && isPhablet)) && (
<h2 className="events-calendar--month">
<span className="full">{week.month}</span>
<span className="short">{week.month_short}</span>
</h2>
)}

{/* Hide days in first week until day.day === 1 for mobile phone */}
{!(isMonthToggled && week_index === 0 && day.day > 7 && isPhablet) &&
!(week_index >= 4 && isPhablet && day.day < 7 && isMonthToggled) && (
<div className={"day " + day.phase}>
<button onClick={(e) => e.target.parentElement.parentElement.classList.toggle('enlarged')} className="events-calendar--number">
<span className="events-calendar--number-dayOfWeek">{day.day_of_week} </span>{day.day}.
</button>
<ul>
{day.events.map((event) => (
<li className={(eventHash == event.hash && "selected") + " " + eventsTags(event)}>
<Link
title={event.title.replace("<br>", ", ")}
className="calendar-item"
to={"?event=" + event.hash}
event-url={event.event_url}
onClick={(e) => {
e.preventDefault();
searchParams.set("event", event.hash);
setSearchParams(searchParams);
}}
dangerouslySetInnerHTML={{
__html: "<b>" + event.displayTime + "</b> " + ((event.host && event.category=="seminar") ? event.host.replace("UBC ", "").split("for ").slice(-1)[0].split("of ").slice(-1)[0] + ":<br>" : "" ) + event.title,
}}
></Link>
</li>
))}
</ul>
</div>
)}
</>
)}

{week.days.map((day, day_index) => {
const loaderWeek = Math.floor((numberOfWeeks - 1) / 2);
const isMiddleDay = !isPhablet? week_index === loaderWeek && day_index === Math.floor(week.days.length / 2)
: week_index === 0 && day_index === 0;
return (
<div key={day_index} className={"day " + day.phase}>
{isMiddleDay && isLoading && !isPhablet &&
<div className="loader-container">
<LoaderComponent width={60}/>
</div>}
<button
onClick={(e) =>
e.target.parentElement.parentElement.classList.toggle("enlarged")
}
className="events-calendar--number"
>
<span className="events-calendar--number-dayOfWeek">{day.day_of_week} </span>
{day.day}.
</button>
<ul>
{day.events.map((event) => (
<li
key={event.hash}
className={(eventHash === event.hash ? "selected " : "") + eventsTags(event)}
>
<Link
title={event.title.replace("<br>", ", ")}
className="calendar-item"
to={"?event=" + event.hash}
event-url={event.event_url}
onClick={(e) => {
e.preventDefault();
searchParams.set("event", event.hash);
setSearchParams(searchParams);
}}
dangerouslySetInnerHTML={{
__html:
"<b>" +
event.displayTime +
"</b> " +
(event.host && event.category === "seminar"
? event.host
.replace("UBC ", "")
.split("for ")
.slice(-1)[0]
.split("of ")
.slice(-1)[0] + ":<br>"
: "") +
event.title,
}}
></Link>
</li>
))}
</ul>
</div>
);
})}
</div>
)}</div>
))}

<div class="legend">
<ul>
Expand Down Expand Up @@ -974,4 +993,12 @@ function EventInfoBox({event}) {
</div>
</div>
);
}

function LoaderComponent({ width }) {
return (
<div className="loader">
<Throbber />
</div>
);
}
28 changes: 28 additions & 0 deletions ubyssey/static_src/src/styles/components/events/_base.scss
Original file line number Diff line number Diff line change
Expand Up @@ -738,3 +738,31 @@ html[color-css-theme="dark"] .events-calendar--navigation .arrow-button {
margin-right: 1em;
}
}

@media ($bp-smaller-than-desktop) {
.loader-container {
display: flex;
justify-content: center;
align-items: center;
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 120vh;
z-index: 9999;
}
}

@media ($bp-larger-than-desktop) {
.loader-container {
display: flex;
justify-content: center;
align-items: center;
height: 100%;
width: 100%;
position: absolute;
top: 0;
left: 0;
z-index: 10;
}
}
5 changes: 5 additions & 0 deletions ubyssey/static_src/webpack.common.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ module.exports = {
},
],
},
{
test: /\.svg$/i,
issuer: /\.[jt]sx?$/,
use: ["@svgr/webpack"],
},
]
},
plugins: [
Expand Down
4 changes: 3 additions & 1 deletion ubyssey/templates/404.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ <h2>Page Not Found</h2>
<p>The page you have searched is not available.</p>
<p>Questions? Contact EMAIL: <a class="email-link"
href="mailto:webmaster@ubyssey.ca">webmaster@ubyssey.ca</a></p>
<h2 class="load-articles"><ion-icon name="refresh" class="spin"></ion-icon></h2>
<h2 class="load-articles">
<img src="{% static '/ubyssey/images/throbber.svg' %}" class="spin" alt="Loading icon">
</h2>

<div id="feed"></div>
<script src="{% static 'ubyssey/js/error_page.js' %}" type="text/javascript"></script>
Expand Down
Loading