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

846 feature request class page redesign #848

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
187 changes: 187 additions & 0 deletions src/web/src/components/CoursePageListing.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
<template>
<b-list-group flush>
<b-list-group-item
class="selected"
v-for="section in sortedSections"
:key="section.crn"
@click.stop="toggleCourseSection(section)"
:style="{
'border-left': section.selected
? `4px solid ${getBorderColor(course.name)}`
: 'none',
'background-color': section.selected
? `${getBackgroundColor(course.name)} !important`
: $store.state.darkMode
? 'var(--dark-primary)'
: 'white',
color: section.selected
? 'black'
: $store.state.darkMode
? 'var(--dark-primary-text)'
: 'black',
}"
>
<b-row class="mb-2" align-h="between">
<b-col cols="auto">
<div class="mb-1 d-inline">
{{ section.crn }} - {{ section.sessions[0].section }} - {{ getInstructor(section.sessions) }}
</div>
<div class="d-inline" style="position: relative; top: -2px; margin-left: 10px;">
<course-section-seats-badge
v-if="section.seats_total > 0"
:seatsOpen="section.seats_open"
:seatsFilled="section.seats_filled"
:seatsTotal="section.seats_total"
/>
</div>
</b-col>
</b-row>

<span
v-for="courseSession in section.sessions"
:key="
courseSession.crn +
courseSession.day_of_week +
courseSession.time_start
"
>
{{ DAY_SHORTNAMES[courseSession.day_of_week + 1] }}:
{{ readableTime(courseSession.time_start) }} -
{{ readableTime(courseSession.time_end) }}
<br />
</span>
</b-list-group-item>
</b-list-group>
</template>

<script>
import "@/typedef";
import { DAY_SHORTNAMES, readableTime, readableDate } from "@/utils";
import { getBackgroundColor, getBorderColor } from "@/services/ColorService";
import {
faTimes,
faPlus,
faChevronDown,
faChevronUp,
} from "@fortawesome/free-solid-svg-icons";
import CourseSectionSeatsBadge from "./CourseSectionSeatsBadge.vue";
// Course Listing by default is a collapsible display of a course and its
// sections and sessions
// However, there are slots available to customize the information displayed
// So far there are two slots with the corresponding scoped props
// 1) toggleCollapseButton { course, toggleCollapse() }
// 2) collapseContent { course }
export default {
name: "CourseListing",
components: {
CourseSectionSeatsBadge,
},
props: {
course: Object,
// If true, collapse is open when created
// If lazyLoadCollapse is true, this is ignored
openInitial: {
type: Boolean,
default: false,
},
// If true, do not render/add collapse content to the DOM
// until collapse is opened
// default false
lazyLoadCollapse: {
type: Boolean,
default: false,
},
// Method name of default action
// When body of CourseListing is clicked on, the
// defaultAction is called
// Kind of hacky, doesnt allow parameters, but keeps it
// relatively flexible
defaultAction: {
type: String,
default: "toggleCollapse",
},
//if this is false the add course + button wont appear
//this is useful for the course explorer
showAddButton: {
type: Boolean,
default: true,
},
},
data() {
return {
faTimes,
faPlus,
faChevronDown,
faChevronUp,
DAY_SHORTNAMES,
// v-model with collapse
// true or false for open or close respectively collapse
showCollapse: !this.lazyLoadCollapse && this.openInitial,
// initially false, set to true on first collapse toggle
// Used for lazy loading
loaded: false,
showAdd: this.showAddButton,
};
},
methods: {
readableTime,
readableDate,
getBackgroundColor,
getBorderColor,
// Just a wrapper, can't call `[defaultAction]()` in html
callDefaultAction() {
this[this.defaultAction]();
},
/**
* Toggle collapse state
* @param {boolean} collapse If provided, set collapse state
*/
toggleCollapse(collapse) {
if (!this.loaded) {
this.loaded = true;
}
this.showCollapse =
collapse !== undefined ? collapse : !this.showCollapse;
},
/**
* Toggle use selection of course section
* If a user is clicking on course section for the first time,
* add course section to schedules
* If the course section had already been clicked
* remove course section from schedules
* @param {CourseSection} section
*/
toggleCourseSection(section) {
if (section.selected) {
this.$emit("removeCourseSection", section);
} else {
this.$emit("addCourseSection", this.course, section);
}
},
//used in the course explorer to show a courses info modal
showInfoModal() {
this.$emit("showCourseInfo", this.course);
},
getInstructor(sessions) {
for (let i = 0; i < sessions.length; i++) {
if (sessions[i].instructor !== "Staff") {
return sessions[i].instructor;
}
}
},
},
computed: {
sortedSections() {
return this.course.sections
.slice()
.sort((a, b) => a.sessions[0].section - b.sessions[0].section);
},
},
};
</script>

<style>
.click-me {
cursor: pointer;
}
</style>
69 changes: 51 additions & 18 deletions src/web/src/pages/CoursePage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,46 @@
<b-row>
<b-col>
<h1 class="mt-4">{{ courseObj.title }}</h1>
<h4 class="mb-1 d-inline">{{ courseName }}</h4>
&nbsp;
<div class="d-inline">
<course-sections-open-badge :course="courseObj" />
</div>
<hr />
</b-col>
</b-row>
<b-row>
<b-col>
<h6 class="mb-1 d-inline">{{ getCredits }} Credits</h6>
</b-col>
</b-row>
<b-row>
<b-col>
<p v-html="transformed" />
<b-col cols="8" class="mb-4">
<b-row>
<b-col>
<h4 class="mb-1 d-inline">{{ courseName }}</h4>
</b-col>
</b-row>
<b-row>
<b-col>
<h6 class="mb-1 d-inline">{{ getCredits }} Credits</h6>
<div class="d-inline" style="position: relative; top: -2px; margin-left: 10px;">
<course-sections-open-badge :course="courseObj" />
</div>
</b-col>
</b-row>
<b-row>
<b-col>
<div class="prerequisites-container">
<p class="prerequisites-text">Prerequisites:</p>
<p class="prerequisites-link" v-html="transformed" />
</div>
</b-col>
</b-row>
<b-row>
<b-col>
<h5>Course Description:</h5>
{{ courseObj.description }}
</b-col>
</b-row>
</b-col>
</b-row>
<b-row>
<b-col class="mb-4">
<b-col cols="4" class="mb-4">
<br />
{{ courseObj.description }}
<h5>Open Sections:</h5>
<CoursePageListing :course="courseObj" v-on="$listeners"/>
</b-col>
</b-row>
<b-button @click="$router.go(-1)">Back</b-button>
<b-button @click="$router.go(-1)" class="mt-3">Back</b-button>
<!-- :to="'/explore/' + courseObj.department"-->
</div>
<CenterSpinner
Expand Down Expand Up @@ -60,11 +76,13 @@ import { COURSES } from "@/store";
import { generateRequirementsText } from "@/utils";
import CenterSpinnerComponent from "../components/CenterSpinner.vue";
import CourseSectionsOpenBadge from "../components/CourseSectionsOpenBadge.vue";
import CoursePageListingComponent from "@/components/CoursePageListing";

export default {
components: {
CenterSpinner: CenterSpinnerComponent,
CourseSectionsOpenBadge,
CoursePageListing: CoursePageListingComponent,
},
name: "CoursePage",
data() {
Expand Down Expand Up @@ -139,7 +157,7 @@ export default {
},
metaInfo() {
return {
title: this.courseObj.name,
title: this.courseObj ? this.courseObj.name : '',
titleTemplate: "%s | YACS",
meta: !this.courseObj
? undefined
Expand All @@ -165,5 +183,20 @@ export default {
],
};
},
mounted() {
console.log(this.courseObj);
},

};
</script>

<style>
.prerequisites-container {
display: flex;
align-items: center; /* Optional: Aligns items vertically in the center */
}

.prerequisites-text {
margin-right: 10px; /* Optional: Adds some space between the text and the link */
}
</style>