Warning Header (Closes #205) #394
|
@ -34,6 +34,8 @@ export const PALETTE_NAMES = [
|
||||||
"--text",
|
"--text",
|
||||||
|
|
||||||
"--form-invalid",
|
"--form-invalid",
|
||||||
|
"--warning-background",
|
||||||
|
"--warning-text",
|
||||||
|
|
||||||
"--input-background",
|
"--input-background",
|
||||||
"--input-placeholder-text",
|
"--input-placeholder-text",
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
.warning{
|
||||||
|
background-color: var(--warning-background);
|
||||||
|
padding: calc(6rem / 16);
|
||||||
|
color: var(--warning-text);
|
||||||
|
font-size: calc(16rem / 16);
|
||||||
|
text-align: center;
|
||||||
|
opacity: 1;
|
||||||
|
|
||||||
|
/* The following are for a smooth fade in if there ever is a loading required for the warning, is not needed currently */
|
||||||
|
/* max-height: 500px;
|
||||||
|
/* transition: max-height 1000ms ease-in, padding 100ms ease-in; */
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
import { parse } from "date-fns";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
import warnings from "../content/warnings/warnings.json";
|
||||||
|
import { DATE_FORMAT, getLocalDateFromEST } from "../utils";
|
||||||
|
|
||||||
|
import styles from "./WarningHeader.module.css";
|
||||||
|
|
||||||
|
interface Warning {
|
||||||
snedadah marked this conversation as resolved
|
|||||||
|
message: string;
|
||||||
|
startDate: string;
|
||||||
|
endDate: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCurrentWarning(): Warning | null {
|
||||||
|
const today = new Date();
|
||||||
|
const currentWarnings: Warning[] = warnings.filter((warning) => {
|
||||||
|
// convert dates to date objects in EST time zone
|
||||||
|
let startDate = parse(warning.startDate, DATE_FORMAT, new Date());
|
||||||
|
let endDate = parse(warning.endDate, DATE_FORMAT, new Date());
|
||||||
|
|
||||||
|
if (
|
||||||
|
!startDate ||
|
||||||
|
!endDate ||
|
||||||
|
isNaN(startDate.getTime()) || // this checks if the parsed date is not valid (eg. wrong format), since getLocalDateFromEST fails with invalid dates
|
||||||
|
isNaN(endDate.getTime())
|
||||||
|
) {
|
||||||
|
throw new Error('WARNING WITH INVALID DATES: "' + warning.message + '"');
|
||||||
snedadah marked this conversation as resolved
a258wang
commented
Do we really need this comment here? I personally think the comment on line 25, along with the general structure of the code, are already sufficient to convey what is happening and why. Do we really need this comment here? I personally think the comment on line 25, along with the general structure of the code, are already sufficient to convey what is happening and why.
|
|||||||
|
}
|
||||||
|
|
||||||
|
startDate = getLocalDateFromEST(startDate);
|
||||||
|
endDate = getLocalDateFromEST(endDate);
|
||||||
|
|
||||||
|
return (
|
||||||
|
startDate.getTime() <= today.getTime() &&
|
||||||
|
endDate.getTime() >= today.getTime()
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (currentWarnings.length > 1) {
|
||||||
|
// If more than one warning is scheduled, log an error to the console. We cannot throw an error, since the site would go down on the live
|
||||||
|
// website, on the day when more than one warning is scheduled.
|
||||||
|
console.error(
|
||||||
|
"ERROR: MORE THAN ONE WARNING SCHEDULED CURRENTLY! ",
|
||||||
|
currentWarnings
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return currentWarnings.length === 0 ? null : currentWarnings[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function WarningHeader() {
|
||||||
|
const warning = getCurrentWarning();
|
||||||
|
|
||||||
|
if (warning == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return <div className={styles.warning}>{warning.message}</div>;
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"startDate": "February 15 2022 00:00",
|
||||||
|
"endDate": "February 20 2022 18:00",
|
||||||
|
"message": "Warning: There will be a scheduled system maintenance on February 17 from 9pm to 12pm EST"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"startDate": "January 29 2022 21:00",
|
||||||
|
"endDate": "January 30 2022 18:00",
|
||||||
|
"message": "This is a sample warning"
|
||||||
|
}
|
||||||
|
]
|
|
@ -2,14 +2,19 @@ import fs from "fs/promises";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
|
|
||||||
import { parse } from "date-fns";
|
import { parse } from "date-fns";
|
||||||
import { utcToZonedTime, zonedTimeToUtc } from "date-fns-tz";
|
|
||||||
import matter from "gray-matter";
|
import matter from "gray-matter";
|
||||||
import { MDXRemoteSerializeResult } from "next-mdx-remote";
|
import { MDXRemoteSerializeResult } from "next-mdx-remote";
|
||||||
import { serialize } from "next-mdx-remote/serialize";
|
import { serialize } from "next-mdx-remote/serialize";
|
||||||
|
|
||||||
import type { Props } from "../pages/events/[year]/[term]/index";
|
import type { Props } from "../pages/events/[year]/[term]/index";
|
||||||
// do not use alias "@/utils" as generate-calendar imports a function from this file and ts-node is not compatible
|
// do not use alias "@/utils" as generate-calendar imports a function from this file and ts-node is not compatible
|
||||||
import { Term, TERMS, isTerm } from "../utils";
|
import {
|
||||||
|
Term,
|
||||||
|
TERMS,
|
||||||
|
isTerm,
|
||||||
|
DATE_FORMAT,
|
||||||
|
getLocalDateFromEST,
|
||||||
|
} from "../utils";
|
||||||
|
|
||||||
const EVENTS_PATH = path.join("content", "events");
|
const EVENTS_PATH = path.join("content", "events");
|
||||||
|
|
||||||
|
@ -55,8 +60,6 @@ export interface Event {
|
||||||
metadata: Metadata;
|
metadata: Metadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DATE_FORMAT = "MMMM dd yyyy HH:mm";
|
|
||||||
|
|
||||||
export async function getEventBySlug(
|
export async function getEventBySlug(
|
||||||
year: string,
|
year: string,
|
||||||
term: Term,
|
term: Term,
|
||||||
|
@ -284,12 +287,3 @@ function getFutureTerm(year: string, term: Term): { year: string; term: Term } {
|
||||||
term: TERMS[index + 1],
|
term: TERMS[index + 1],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// The date that's returned should be in local time
|
|
||||||
export function getLocalDateFromEST(date: Date) {
|
|
||||||
return utcToZonedTime(
|
|
||||||
// The parsed date is in EST
|
|
||||||
zonedTimeToUtc(date, "America/Toronto"),
|
|
||||||
Intl.DateTimeFormat().resolvedOptions().timeZone
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ import { serialize } from "next-mdx-remote/serialize";
|
||||||
|
|
||||||
import { isTerm, Term, TERMS } from "@/utils";
|
import { isTerm, Term, TERMS } from "@/utils";
|
||||||
|
|
||||||
import { DATE_FORMAT, getLocalDateFromEST } from "./events";
|
import { DATE_FORMAT, getLocalDateFromEST } from "../utils";
|
||||||
|
|
||||||
export const NEWS_PATH = path.join("content", "news");
|
export const NEWS_PATH = path.join("content", "news");
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,8 @@ body {
|
||||||
--text: #000000;
|
--text: #000000;
|
||||||
|
|
||||||
--form-invalid: #9f616a;
|
--form-invalid: #9f616a;
|
||||||
|
--warning-background: #dd0014;
|
||||||
|
--warning-text: #ffffff;
|
||||||
snedadah marked this conversation as resolved
a3thakra
commented
Make sure to add these colors in our theme palette as well. That way it will show up in the themer and will be totally customizable! Themer: https://csclub.uwaterloo.ca/themer Adding a color to the palette should be as easy as adding a string to this array. If that doesn't work, let me know and we can figure something out. Make sure to add these colors in our theme palette as well. That way it will show up in the themer and will be totally customizable!
Themer: https://csclub.uwaterloo.ca/themer
Adding a color to the palette should be as easy as adding a string to [this array](https://git.csclub.uwaterloo.ca/www/www-new/src/branch/main/components/Theme.tsx#L18). If that doesn't work, let me know and we can figure something out.
|
|||||||
|
|
||||||
--input-background: #f0f0f0;
|
--input-background: #f0f0f0;
|
||||||
--input-placeholder-text: #bbbbbb;
|
--input-placeholder-text: #bbbbbb;
|
||||||
|
|
|
@ -20,6 +20,7 @@ import {
|
||||||
} from "@/components/ShapesBackground";
|
} from "@/components/ShapesBackground";
|
||||||
import { Table } from "@/components/Table";
|
import { Table } from "@/components/Table";
|
||||||
import { ThemeProvider } from "@/components/Theme";
|
import { ThemeProvider } from "@/components/Theme";
|
||||||
|
import { WarningHeader } from "@/components/WarningHeader";
|
||||||
|
|
||||||
import styles from "./_app.module.css";
|
import styles from "./_app.module.css";
|
||||||
|
|
||||||
|
@ -44,6 +45,7 @@ export default function App({ Component, pageProps }: AppProps): JSX.Element {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className={styles.appContainer}>
|
<div className={styles.appContainer}>
|
||||||
|
<WarningHeader />
|
||||||
<Navbar />
|
<Navbar />
|
||||||
{/* Wrapping content with a div to allow for a display: block parent */}
|
{/* Wrapping content with a div to allow for a display: block parent */}
|
||||||
<div className={styles.contentContainer}>
|
<div className={styles.contentContainer}>
|
||||||
|
|
|
@ -3,8 +3,9 @@ import path from "path";
|
||||||
|
|
||||||
import { format } from "date-fns";
|
import { format } from "date-fns";
|
||||||
|
|
||||||
|
import { DATE_FORMAT } from "@/utils";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
DATE_FORMAT,
|
|
||||||
getEventsByTerm,
|
getEventsByTerm,
|
||||||
getEventTermsByYear,
|
getEventTermsByYear,
|
||||||
getEventYears,
|
getEventYears,
|
||||||
|
|
12
utils.ts
12
utils.ts
|
@ -1,5 +1,8 @@
|
||||||
|
import { utcToZonedTime, zonedTimeToUtc } from "date-fns-tz";
|
||||||
|
|
||||||
export const TERMS = ["winter", "spring", "fall"] as const;
|
export const TERMS = ["winter", "spring", "fall"] as const;
|
||||||
export type Term = typeof TERMS[number];
|
export type Term = typeof TERMS[number];
|
||||||
|
export const DATE_FORMAT = "MMMM dd yyyy HH:mm";
|
||||||
|
|
||||||
// https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates
|
// https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates
|
||||||
export function isTerm(x: string): x is Term {
|
export function isTerm(x: string): x is Term {
|
||||||
|
@ -9,3 +12,12 @@ export function isTerm(x: string): x is Term {
|
||||||
export function capitalize(str: string) {
|
export function capitalize(str: string) {
|
||||||
return str.slice(0, 1).toUpperCase() + str.slice(1);
|
return str.slice(0, 1).toUpperCase() + str.slice(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Converts a date to local time
|
||||||
|
export function getLocalDateFromEST(date: Date): Date {
|
||||||
|
return utcToZonedTime(
|
||||||
|
// The date parameter is in EST
|
||||||
|
zonedTimeToUtc(date, "America/Toronto"),
|
||||||
|
Intl.DateTimeFormat().resolvedOptions().timeZone
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
We should probably move these functions to utils in that case, and then make both events and this file import from there