Skip to content

Commit

Permalink
fix: website: today: Hide "hidden" courses in Today page (#3927)
Browse files Browse the repository at this point in the history
  • Loading branch information
zwliew authored Jan 3, 2025
1 parent 7caec09 commit 63c1cc5
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 121 deletions.
8 changes: 8 additions & 0 deletions website/src/selectors/timetables.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,11 @@ export const getSemesterTimetableColors = createSelector(
(colors) => (semester: Semester | null) =>
semester === null ? EMPTY_OBJECT : colors[semester] ?? EMPTY_OBJECT,
);

/**
* Extract hidden courses for a specific semester.
*/
export const getSemesterTimetableHidden = createSelector(
({ timetables }: State) => timetables.hidden,
(hidden) => (semester: Semester | null) => semester === null ? [] : hidden[semester] ?? [],
);
163 changes: 49 additions & 114 deletions website/src/views/today/TodayContainer/TodayContainer.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { waitFor } from 'test-utils/async';
import { EVEN_WEEK, EVERY_WEEK } from 'test-utils/timetable';
import { captureException } from 'utils/error';

import { State } from 'types/state';
import { Props, DaySection, TodayContainerComponent, mapStateToProps } from './TodayContainer';
import forecasts from './__mocks__/forecasts.json';
import DayEvents from '../DayEvents';
Expand Down Expand Up @@ -137,7 +138,7 @@ describe(TodayContainerComponent, () => {
const componentProps: Props = {
colors: COLORS,
matchBreakpoint: false,
timetableWithLessons: LESSONS,
visibleTimetableWithLessons: LESSONS,

...props,
};
Expand Down Expand Up @@ -165,7 +166,7 @@ describe(TodayContainerComponent, () => {

const wrapper = make({
currentTime: now,
timetableWithLessons: {},
visibleTimetableWithLessons: {},
});

expect(getLessons(wrapper)).toHaveLength(0);
Expand Down Expand Up @@ -206,13 +207,13 @@ describe(TodayContainerComponent, () => {
const now = new Date('2016-08-22T18:00:00+08:00');
make({ currentTime: now });

expect(mockWeather.twoHour).toBeCalled();
expect(mockWeather.tomorrow).toBeCalled();
expect(mockWeather.fourDay).toBeCalled();
expect(mockWeather.twoHour).toHaveBeenCalled();
expect(mockWeather.tomorrow).toHaveBeenCalled();
expect(mockWeather.fourDay).toHaveBeenCalled();

await waitFor(() => mockCaptureException.mock.calls.length > 0);

expect(mockCaptureException).toBeCalled();
expect(mockCaptureException).toHaveBeenCalled();
});

test('should show icons for the next four days', async () => {
Expand Down Expand Up @@ -251,152 +252,86 @@ describe(TodayContainerComponent, () => {
});

describe(mapStateToProps, () => {
const state = {
moduleBank: { modules: {} },
timetables: {
lessons: {
[1]: {
CS3216: {},
},
[2]: {
CS1010S: {},
GEX10105: {},
},
[3]: {
CS1231: {},
},
[4]: {
CS2040: {},
},
},
colors: {
[1]: COLORS,
[2]: COLORS,
[3]: COLORS,
[4]: COLORS,
},
hidden: { [2]: ['GEX1015'] },
},
} as any as State;

test('should use correct semester (test 1, special case)', () => {
// On week -1 of sem 2 the semester should be 2, not 1
const ownProps: any = {
const ownProps = {
// Week -1 of sem 2 of AY2018/2019
currentTime: new Date('2019-01-09T00:00:00.000Z'),
};

const state: any = {
moduleBank: { modules: {} },
timetables: {
lessons: {
[1]: {
CS3216: {},
},
[2]: {
CS1010S: {},
},
},
colors: {
[1]: COLORS,
[2]: COLORS,
},
},
};

// Should return sem 2 timetable, not sem 1
expect(mapStateToProps(state, ownProps).timetableWithLessons).toHaveProperty('CS1010S');
expect(mapStateToProps(state, ownProps).visibleTimetableWithLessons).toHaveProperty('CS1010S');
// Should hide "hidden" courses
expect(mapStateToProps(state, ownProps).visibleTimetableWithLessons).not.toHaveProperty(
'GEX1015',
);
});
});

describe(mapStateToProps, () => {
test('should use correct semester (test 2)', () => {
// On week -1 of orientation week, it should be special term II
const ownProps: any = {
const ownProps = {
currentTime: new Date('2024-08-04T00:00:00.000Z'),
};

const state: any = {
moduleBank: { modules: {} },
timetables: {
lessons: {
[4]: {
CS3216: {},
},
[1]: {
CS1010S: {},
},
},
colors: {
[4]: COLORS,
[1]: COLORS,
},
},
};

// Should return special term II timetable, not sem 1
expect(mapStateToProps(state, ownProps).timetableWithLessons).toHaveProperty('CS3216');
expect(mapStateToProps(state, ownProps).visibleTimetableWithLessons).toHaveProperty('CS2040');
});
});

describe(mapStateToProps, () => {
test('should use correct semester (test 3)', () => {
// On orientation week, it should be sem1
const ownProps: any = {
const ownProps = {
currentTime: new Date('2024-08-05T00:00:00.000Z'),
};

const state: any = {
moduleBank: { modules: {} },
timetables: {
lessons: {
[4]: {
CS3216: {},
},
[1]: {
CS1010S: {},
},
},
colors: {
[4]: COLORS,
[1]: COLORS,
},
},
};

// Should return sem1 timetable
expect(mapStateToProps(state, ownProps).timetableWithLessons).toHaveProperty('CS1010S');
expect(mapStateToProps(state, ownProps).visibleTimetableWithLessons).toHaveProperty('CS3216');
});
});

describe(mapStateToProps, () => {
test('should use correct semester (test 4)', () => {
// On week -1 of special term I, it should be sem2
const ownProps: any = {
const ownProps = {
currentTime: new Date('2025-05-11T00:00:00.000Z'),
};

const state: any = {
moduleBank: { modules: {} },
timetables: {
lessons: {
[2]: {
CS3216: {},
},
[3]: {
CS1010S: {},
},
},
colors: {
[2]: COLORS,
[3]: COLORS,
},
},
};

// Should return sem2 timetable
expect(mapStateToProps(state, ownProps).timetableWithLessons).toHaveProperty('CS3216');
expect(mapStateToProps(state, ownProps).visibleTimetableWithLessons).toHaveProperty('CS1010S');
});
});

describe(mapStateToProps, () => {
test('should use correct semester (test 5)', () => {
// On week -1 of special term II, it should be special term I
const ownProps: any = {
const ownProps = {
currentTime: new Date('2025-06-22T00:00:00.000Z'),
};

const state: any = {
moduleBank: { modules: {} },
timetables: {
lessons: {
[3]: {
CS3216: {},
},
[4]: {
CS1010S: {},
},
},
colors: {
[3]: COLORS,
[4]: COLORS,
},
},
};

// Should return special term I timetable
expect(mapStateToProps(state, ownProps).timetableWithLessons).toHaveProperty('CS3216');
expect(mapStateToProps(state, ownProps).visibleTimetableWithLessons).toHaveProperty('CS1231');
});
});
22 changes: 15 additions & 7 deletions website/src/views/today/TodayContainer/TodayContainer.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as React from 'react';
import { connect } from 'react-redux';
import { get, minBy, range } from 'lodash';
import { get, minBy, range, omit } from 'lodash';
import NUSModerator, { AcadWeekInfo } from 'nusmoderator';
import classnames from 'classnames';
import {
Expand Down Expand Up @@ -28,7 +28,11 @@ import {
} from 'utils/timetables';
import { captureException } from 'utils/error';
import Title from 'views/components/Title';
import { getSemesterTimetableColors, getSemesterTimetableLessons } from 'selectors/timetables';
import {
getSemesterTimetableColors,
getSemesterTimetableHidden,
getSemesterTimetableLessons,
} from 'selectors/timetables';
import ExternalLink from 'views/components/ExternalLink';
import * as weatherAPI from 'apis/weather';
import config from 'config';
Expand Down Expand Up @@ -61,7 +65,7 @@ export type OwnProps = TimerData;

export type Props = OwnProps &
Readonly<{
timetableWithLessons: SemTimetableConfigWithLessons;
visibleTimetableWithLessons: SemTimetableConfigWithLessons;
colors: ColorMapping;
matchBreakpoint: boolean;
}>;
Expand Down Expand Up @@ -174,9 +178,9 @@ export class TodayContainerComponent extends React.PureComponent<Props, State> {
};

groupLessons() {
const { colors, currentTime } = this.props;
const { colors, currentTime, visibleTimetableWithLessons } = this.props;

const timetableLessons: Lesson[] = timetableLessonsArray(this.props.timetableWithLessons);
const timetableLessons: Lesson[] = timetableLessonsArray(visibleTimetableWithLessons);

// Inject color into module
const coloredTimetableLessons = timetableLessons.map(
Expand Down Expand Up @@ -363,11 +367,15 @@ export const mapStateToProps = (state: StoreState, ownProps: OwnProps) => {
const semester = semesterNameMap[weekInfo.sem];
const timetable = getSemesterTimetableLessons(state)(semester);
const colors = getSemesterTimetableColors(state)(semester);
const timetableWithLessons = hydrateSemTimetableWithLessons(timetable, modules, semester);
const hidden = getSemesterTimetableHidden(state)(semester);
const visibleTimetableWithLessons = omit(
hydrateSemTimetableWithLessons(timetable, modules, semester),
hidden,
);

return {
colors,
timetableWithLessons,
visibleTimetableWithLessons,
};
};

Expand Down

0 comments on commit 63c1cc5

Please sign in to comment.