Skip to content

Commit

Permalink
Migrate to SCSS, refactor styles
Browse files Browse the repository at this point in the history
Add base styles for buttons, modals, forms, etc.
Split original styles file into multiple grouped files
Modify styles and classes to be more consistent
Set up webpack for CSS compilation
Move style files out of static folder
  • Loading branch information
smartspot2 committed Sep 9, 2023
1 parent a8f0728 commit 1736204
Show file tree
Hide file tree
Showing 85 changed files with 7,515 additions and 5,360 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ typings/
# NPM Built
main.js
main.js.LICENSE.txt
style.min.css
main.css

# Mac OS X dir files
.DS_Store
2 changes: 2 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# ignore Django templates
**/templates/**/*.html
47 changes: 28 additions & 19 deletions csm_web/frontend/src/components/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,14 @@ import Policies from "./Policies";
import { Resources } from "./resource_aggregation/Resources";
import Section from "./section/Section";

// Images
import LogoNoText from "../../static/frontend/img/logo_no_text.svg";
import LogOutIcon from "../../static/frontend/img/log_out.svg";

// Styles
import "../css/header.scss";
import "../css/home.scss";

interface ErrorType {
message: string;
stack: string;
Expand Down Expand Up @@ -113,26 +118,30 @@ function Header(): React.ReactElement {

return (
<header>
<Link to="/">
<LogoNoText id="logo" />
</Link>
<NavLink className={homeNavlinkClass} to="/">
<h3 className="site-title">Scheduler</h3>
</NavLink>
<NavLink to="/resources" className={navlinkClass}>
<h3 className="site-title">Resources</h3>
</NavLink>
{activeMatcherRoles["COORDINATOR"].size > 0 || activeMatcherRoles["MENTOR"].size > 0 ? (
<NavLink to="/matcher" className={navlinkClass}>
<h3 className="site-title">Matcher</h3>
<div className="site-title-group">
<Link to="/">
<LogoNoText id="logo" />
</Link>
<NavLink className={homeNavlinkClass} to="/">
<h3 className="site-title">Scheduler</h3>
</NavLink>
<NavLink to="/resources" className={navlinkClass}>
<h3 className="site-title">Resources</h3>
</NavLink>
) : null}
<NavLink to="/policies" className={navlinkClassSubtitle}>
<h3 className="site-subtitle">Policies</h3>
</NavLink>
<a id="logout-btn" href="/logout" title="Log out">
<LogOutIcon width="1.25em" height="1.25em" />
</a>
{activeMatcherRoles["COORDINATOR"].size > 0 || activeMatcherRoles["MENTOR"].size > 0 ? (
<NavLink to="/matcher" className={navlinkClass}>
<h3 className="site-title">Matcher</h3>
</NavLink>
) : null}
</div>
<div className="site-title-group">
<NavLink to="/policies" className={navlinkClassSubtitle}>
<h3 className="site-subtitle">Policies</h3>
</NavLink>
<a id="logout-btn" href="/logout" title="Log out">
<LogOutIcon width="1.25em" height="1.25em" />
</a>
</div>
</header>
);
}
Expand Down
22 changes: 18 additions & 4 deletions csm_web/frontend/src/components/CourseMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ import LoadingSpinner from "./LoadingSpinner";
import { DateTime } from "luxon";
import { DEFAULT_LONG_LOCALE_OPTIONS, DEFAULT_TIMEZONE } from "../utils/datetime";

// Styles
import "../css/course-menu.scss";

const CourseMenu = () => {
const { data: jsonCourses, isSuccess: coursesLoaded } = useCourses();
const { data: jsonUserInfo, isSuccess: userInfoLoaded } = useUserInfo();
Expand Down Expand Up @@ -147,16 +150,27 @@ const CourseMenuContent = ({

let sidebar = null;
if (hasRestrictedCourses) {
/**
* Helper to get the current tab class
*/
const getTabClass = (expected: CourseMenuSidebarTabs) => {
if (selectedTab === expected) {
return "tab active";
} else {
return "tab";
}
};

sidebar = (
<div className="course-menu-sidebar">
<div className="tab-list">
<button
className={"course-menu-sidebar-tab" + (selectedTab === CourseMenuSidebarTabs.RESTRICTED ? " active" : "")}
className={getTabClass(CourseMenuSidebarTabs.RESTRICTED)}
onClick={() => setSelectedTab(CourseMenuSidebarTabs.RESTRICTED)}
>
Restricted
</button>
<button
className={"course-menu-sidebar-tab" + (selectedTab === CourseMenuSidebarTabs.UNRESTRICTED ? " active" : "")}
className={getTabClass(CourseMenuSidebarTabs.UNRESTRICTED)}
onClick={() => setSelectedTab(CourseMenuSidebarTabs.UNRESTRICTED)}
>
Unrestricted
Expand Down Expand Up @@ -204,7 +218,7 @@ const EnrollmentMenu = ({ courses }: EnrollmentMenuProps) => {
{courses !== null ? (
<div id="course-menu">
{Array.from(courses.entries()).map(([id, course]) => (
<Link className="csm-btn" to={`${id}`} key={id}>
<Link className="primary-btn" to={`${id}`} key={id}>
{course.name}
</Link>
))}
Expand Down
18 changes: 14 additions & 4 deletions csm_web/frontend/src/components/Home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ import { Profile, Course } from "../utils/types";
import LoadingSpinner from "./LoadingSpinner";
import { formatSpacetimeInterval } from "../utils/datetime";

// Images
import PlusIcon from "../../static/frontend/img/plus.svg";

// Styles
import scssColors from "../css/base/colors-export.module.scss";

const Home = () => {
const { data: profiles, isSuccess: profilesLoaded, isError: profilesLoadError } = useProfiles();
const { data: courses, isSuccess: coursesLoaded, isError: coursesLoadError } = useCourses();
Expand Down Expand Up @@ -63,8 +69,9 @@ const Home = () => {
<div id="home-courses">
<div id="home-courses-heading">
<h3 className="page-title">My courses</h3>
<Link className="csm-btn" to="/courses">
<span className="inline-plus-sign">+ </span>Add Course
<Link className="primary-btn" to="/courses">
<PlusIcon className="icon inline-plus-icon" />
Add Course
</Link>
</div>
{content}
Expand All @@ -82,8 +89,11 @@ const CourseCard = ({ profiles }: CourseCardProps): React.ReactElement => {
const relation = role.toLowerCase();

const Card = (): React.ReactElement => {
// default to black if not found
const courseColor = scssColors[course.toLowerCase()] ?? "black";
const relationColor = scssColors[relation.toLowerCase()] ?? "white";
return (
<div className="course-card" style={{ borderTopColor: `var(--csm-theme-${course.toLowerCase()})` }}>
<div className="course-card" style={{ borderTopColor: courseColor }}>
<div className="course-card-contents">
<h3 className="course-card-name">{course}</h3>
<p className="course-card-title">{courseTitle}</p>
Expand All @@ -97,7 +107,7 @@ const CourseCard = ({ profiles }: CourseCardProps): React.ReactElement => {
))}
</Link>
))}
<div className="relation-label" style={{ backgroundColor: `var(--csm-${relation})` }}>
<div className="relation-label" style={{ backgroundColor: relationColor }}>
{relation}
</div>
</div>
Expand Down
17 changes: 9 additions & 8 deletions csm_web/frontend/src/components/Modal.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import React, { useContext } from "react";

// Images
import XIcon from "../../static/frontend/img/x.svg";

const ModalContext = React.createContext(Function.prototype);

interface ModalProps {
Expand All @@ -16,15 +19,13 @@ export default function Modal({ children, closeModal, className = "" }: ModalPro
return (
<ModalContext.Provider value={closeModal}>
<div className="modal-overlay" onClick={closeModal} />
<div className={`modal ${className}`}>
<div className="modal-contents">
<div className="modal-close-x">
<button className="inline-plus-sign" aria-label="close" onClick={closeModal}>
<span>&times;</span>
</button>
</div>
{children}
<div className={`modal `}>
<div className="modal-close-container">
<button className="modal-close-x" aria-label="close" onClick={closeModal}>
<XIcon className="icon" />
</button>
</div>
<div className={`modal-contents ${className}`}>{children}</div>
</div>
</ModalContext.Provider>
);
Expand Down
5 changes: 5 additions & 0 deletions csm_web/frontend/src/components/Policies.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import React from "react";

// Styles
import "../css/policies.scss";

// Data
import SECTIONS from "../../static/frontend/data/enrollment_policies";

export default class Policies extends React.Component {
Expand Down
16 changes: 11 additions & 5 deletions csm_web/frontend/src/components/course/Course.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,12 @@ import { WhitelistModal } from "./WhitelistModal";
import { SettingsModal } from "./SettingsModal";
import { DEFAULT_LONG_LOCALE_OPTIONS } from "../../utils/datetime";

// Images
import PencilIcon from "../../../static/frontend/img/pencil.svg";
import PlusIcon from "../../../static/frontend/img/plus.svg";

// Styles
import "../../css/course.scss";

const DAY_OF_WEEK_ABREVIATIONS: { [day: string]: string } = Object.freeze({
Monday: "M",
Expand Down Expand Up @@ -156,16 +161,17 @@ const Course = ({ courses, priorityEnrollment, enrollmentTimes }: CourseProps):
{userIsCoordinator && (
<div id="course-coord-buttons">
<button
className="csm-btn create-section-btn"
className="primary-btn"
onClick={() => {
setShowModal(true);
setWhichModal(COURSE_MODAL_TYPE.createSection);
}}
>
<span className="inline-plus-sign">+ </span>Create Section
<PlusIcon className="icon" />
Create Section
</button>
<button
className="csm-btn export-data-btn"
className="primary-btn"
onClick={() => {
setShowModal(true);
setWhichModal(COURSE_MODAL_TYPE.exportData);
Expand All @@ -174,7 +180,7 @@ const Course = ({ courses, priorityEnrollment, enrollmentTimes }: CourseProps):
Export Data
</button>
<button
className="csm-btn course-settings-btn"
className="primary-btn"
onClick={() => {
setShowModal(true);
setWhichModal(COURSE_MODAL_TYPE.settings);
Expand All @@ -184,7 +190,7 @@ const Course = ({ courses, priorityEnrollment, enrollmentTimes }: CourseProps):
</button>
{course.isRestricted && (
<button
className="csm-btn edit-whitelist-btn"
className="primary-btn"
onClick={() => {
setShowModal(true);
setWhichModal(COURSE_MODAL_TYPE.whitelist);
Expand Down
42 changes: 26 additions & 16 deletions csm_web/frontend/src/components/course/CreateSectionModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ export const CreateSectionModal = ({ courseId, closeModal, reloadSections }: Cre
/**
* Handle form submission.
*/
const handleSubmit = (event: React.FormEvent<HTMLFormElement>): void => {
const handleSubmit = (event: React.MouseEvent<HTMLButtonElement>): void => {
event.preventDefault();
const data = {
mentorEmail,
Expand All @@ -109,14 +109,15 @@ export const CreateSectionModal = ({ courseId, closeModal, reloadSections }: Cre
};

return (
<Modal closeModal={closeModal}>
<form id="create-section-form" className="csm-form" onSubmit={handleSubmit}>
<Modal className="create-section-modal" closeModal={closeModal}>
<form id="create-section-form" className="csm-form">
<div id="create-section-form-contents">
<div id="non-spacetime-fields">
<label>
<label className="form-label">
Mentor Email
<input
onChange={e => handleChange(-1, "mentorEmail", e.target.value)}
className="form-input"
type="email"
list="user-email-list"
required
Expand All @@ -130,9 +131,10 @@ export const CreateSectionModal = ({ courseId, closeModal, reloadSections }: Cre
{userEmailsLoaded ? userEmails.map(email => <option key={email} value={email} />) : null}
</datalist>
</label>
<label>
<label className="form-label">
Capacity
<input
className="form-input"
required
name="capacity"
type="number"
Expand All @@ -143,9 +145,10 @@ export const CreateSectionModal = ({ courseId, closeModal, reloadSections }: Cre
onChange={e => handleChange(-1, "capacity", e.target.value)}
/>
</label>
<label>
<label className="form-label">
Description
<input
className="form-input"
name="description"
type="text"
value={description}
Expand All @@ -157,9 +160,10 @@ export const CreateSectionModal = ({ courseId, closeModal, reloadSections }: Cre
<React.Fragment key={index}>
<h4 className="spacetime-fields-header">Weekly occurence {index + 1}</h4>
<div className="spacetime-fields">
<label>
<label className="form-label">
Location
<input
className="form-input"
onChange={e => handleChange(index, "location", e.target.value)}
required
title="You cannot leave this field blank"
Expand All @@ -169,9 +173,10 @@ export const CreateSectionModal = ({ courseId, closeModal, reloadSections }: Cre
value={location}
/>
</label>
<label>
<label className="form-label">
Day
<select
className="form-select"
onChange={e => handleChange(index, "dayOfWeek", e.target.value)}
name={`dayOfWeek|${index}`}
value={dayOfWeek}
Expand All @@ -184,35 +189,40 @@ export const CreateSectionModal = ({ courseId, closeModal, reloadSections }: Cre
))}
</select>
</label>
<label>
<label className="form-label">
Time
<TimeInput
className="form-date"
onChange={e => handleChange(index, "startTime", e.target.value)}
required
name={`startTime|${index}`}
value={startTime}
/>
</label>
<label>
<label className="form-label">
Duration (min)
<input
className="form-input"
type="number"
name={`duration|${index}`}
value={duration}
min={0}
onChange={e => handleChange(index, "duration", e.target.value)}
/>
</label>
{index === spacetimes.length - 1 && (
<button className="csm-btn" id="add-occurence-btn" onClick={appendSpacetime}>
Add another occurence
</button>
)}
</div>
</React.Fragment>
))}
<input type="submit" value="Create Section" />
</div>
</form>
<div className="create-section-submit-container">
<button className="secondary-btn" id="add-occurence-btn" onClick={appendSpacetime}>
Add another occurence
</button>
<button className="primary-btn" onClick={handleSubmit}>
Submit
</button>
</div>
</Modal>
);
};
Loading

0 comments on commit 1736204

Please sign in to comment.