Skip to content

Commit

Permalink
fix(website/export): Parse hidden courses (#3925)
Browse files Browse the repository at this point in the history
  • Loading branch information
zwliew authored Jan 3, 2025
1 parent 63c1cc5 commit fec9bfa
Show file tree
Hide file tree
Showing 8 changed files with 50 additions and 33 deletions.
4 changes: 2 additions & 2 deletions export/api/export/image.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ import _ from 'lodash';
import { validateExportData } from '../../src/data';
import { makeExportHandler } from '../../src/handler';
import * as render from '../../src/render-serverless';
import type { PageData } from '../../src/types';
import type { ExportData } from '../../src/types';

type Data = {
exportData: PageData;
exportData: ExportData;
options: render.ViewportOptions;
};

Expand Down
4 changes: 2 additions & 2 deletions export/api/export/pdf.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { validateExportData } from '../../src/data';
import { makeExportHandler } from '../../src/handler';
import * as render from '../../src/render-serverless';
import type { PageData } from '../../src/types';
import type { ExportData } from '../../src/types';

const handler = makeExportHandler<PageData>(
const handler = makeExportHandler<ExportData>(
(request) => {
const exportData = JSON.parse(request.query.data as never);
validateExportData(exportData);
Expand Down
8 changes: 5 additions & 3 deletions export/src/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import Joi from 'joi';
import type { Middleware } from 'koa';

import config from './config';
import type { PageData, State } from './types';
import type { ExportData, State } from './types';

async function fetchModule(moduleCode: string) {
const fileName = `${moduleCode}.json`;
Expand Down Expand Up @@ -58,7 +58,7 @@ export const parseExportData: Middleware<State> = (ctx, next) => {
return next();
};

export function validateExportData(data: PageData) {
export function validateExportData(data: ExportData) {
if (!_.isObject(data)) throw new Error('data should be an object');

const timetableSchema = Joi.object().pattern(
Expand All @@ -73,8 +73,10 @@ export function validateExportData(data: PageData) {
const pageDataSchema = Joi.object({
semester: Joi.number().integer().greater(0).less(5),
timetable: timetableSchema,
colors: Joi.object().pattern(Joi.string(), Joi.number().integer().min(0)),
hidden: Joi.array().items(Joi.string()),
settings: Joi.object({
hiddenInTimeTable: Joi.array().items(Joi.string()),
colorScheme: Joi.string().valid('LIGHT_COLOR_SCHEME', 'DARK_COLOR_SCHEME'),
}),
theme: themeSchema,
});
Expand Down
8 changes: 4 additions & 4 deletions export/src/render-serverless.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import puppeteer, { Page } from 'puppeteer-core';

import { getModules } from './data';
import config from './config';
import type { PageData } from './types';
import type { ExportData } from './types';

// Arbitrarily high number - just make sure it doesn't clip the timetable
const VIEWPORT_HEIGHT = 2000;
Expand Down Expand Up @@ -42,7 +42,7 @@ export async function open(url: string) {
return page;
}

async function injectData(page: Page, data: PageData) {
async function injectData(page: Page, data: ExportData) {
const moduleCodes = Object.keys(data.timetable);
const modules = await getModules(moduleCodes);

Expand All @@ -59,7 +59,7 @@ async function injectData(page: Page, data: PageData) {
return (await appEle.boundingBox()) || undefined;
}

export async function image(page: Page, data: PageData, options: ViewportOptions = {}) {
export async function image(page: Page, data: ExportData, options: ViewportOptions = {}) {
if (options.pixelRatio || (options.height && options.width)) {
await setViewport(page, options);
}
Expand All @@ -70,7 +70,7 @@ export async function image(page: Page, data: PageData, options: ViewportOptions
});
}

export async function pdf(page: Page, data: PageData) {
export async function pdf(page: Page, data: ExportData) {
await injectData(page, data);
await page.emulateMediaType('screen');

Expand Down
8 changes: 4 additions & 4 deletions export/src/render.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import type { Middleware } from 'koa';

import { getModules } from './data';
import config from './config';
import type { PageData, State } from './types';
import type { ExportData, State } from './types';

// Arbitrarily high number - just make sure it doesn't clip the timetable
const VIEWPORT_HEIGHT = 2000;
Expand Down Expand Up @@ -67,7 +67,7 @@ export const openPage: Middleware<State> = async (ctx, next) => {
await ctx.state.page.close();
};

async function injectData(page: Page, data: PageData) {
async function injectData(page: Page, data: ExportData) {
const moduleCodes = Object.keys(data.timetable);
const modules = await getModules(moduleCodes);

Expand All @@ -84,7 +84,7 @@ async function injectData(page: Page, data: PageData) {
return (await appEle.boundingBox()) || undefined;
}

export async function image(page: Page, data: PageData, options: ViewportOptions = {}) {
export async function image(page: Page, data: ExportData, options: ViewportOptions = {}) {
if (options.pixelRatio || (options.height && options.width)) {
await setViewport(page, options);
}
Expand All @@ -95,7 +95,7 @@ export async function image(page: Page, data: PageData, options: ViewportOptions
});
}

export async function pdf(page: Page, data: PageData) {
export async function pdf(page: Page, data: ExportData) {
await injectData(page, data);
await page.emulateMediaType('screen');

Expand Down
36 changes: 24 additions & 12 deletions export/src/types.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,31 @@
import type { Page } from 'puppeteer-core';

// These types are duplicated from `website/`.
// TODO: Move these types to a shared package.
export type TimetableOrientation = 'HORIZONTAL' | 'VERTICAL';
export type Semester = number;
export type SemTimetableConfig = {
[moduleCode: string]: ModuleLessonConfig;
};
export type ColorIndex = number;
export type ColorMapping = { [moduleCode: string]: ColorIndex };
export type ModuleCode = string;
export type ThemeState = Readonly<{
id: string;
timetableOrientation: TimetableOrientation;
showTitle: boolean;
}>;
export type ColorScheme = 'LIGHT_COLOR_SCHEME' | 'DARK_COLOR_SCHEME';

export interface PageData {
readonly semester: number;
readonly timetable: {
[moduleCode: string]: ModuleLessonConfig;
};
// `ExportData` is duplicated from `website/src/types/export.ts`.
export interface ExportData {
readonly semester: Semester;
readonly timetable: SemTimetableConfig;
readonly colors: ColorMapping;
readonly hidden: ModuleCode[];
readonly theme: ThemeState;
readonly settings: {
readonly hiddenInTimetable: string[];
};
readonly theme: {
id: string;
timetableOrientation: TimetableOrientation;
showTitle: boolean;
colorScheme: ColorScheme;
};
}

Expand All @@ -22,6 +34,6 @@ export interface ModuleLessonConfig {
}

export interface State {
data: PageData;
data: ExportData;
page: Page;
}
12 changes: 7 additions & 5 deletions website/src/entry/export/TimetableOnly.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Component } from 'react';
import { MemoryRouter } from 'react-router-dom';
import { Provider } from 'react-redux';

import { Semester } from 'types/modules';
import { ModuleCode, Semester } from 'types/modules';
import { SemTimetableConfig } from 'types/timetables';
import { fillColorMapping } from 'utils/colors';
import TimetableContent from 'views/timetable/TimetableContent';
Expand All @@ -18,21 +18,23 @@ type State = {
semester: Semester;
timetable: SemTimetableConfig;
colors: ColorMapping;
hidden: ModuleCode[];
};

export default class TimetableOnly extends Component<Props, State> {
override state = {
semester: 1,
timetable: {},
colors: {},
hidden: [],
};

override render() {
const { store } = this.props;
const theme = store.getState().theme.id;

const { semester, timetable, colors } = this.state;
const timetableColors = fillColorMapping(timetable, colors);
const { semester, timetable, colors, hidden } = this.state;
const filledColors = fillColorMapping(timetable, colors);

return (
<MemoryRouter initialEntries={['https://nusmods.com']}>
Expand All @@ -42,8 +44,8 @@ export default class TimetableOnly extends Component<Props, State> {
header={null}
semester={semester}
timetable={timetable}
colors={timetableColors}
hiddenImportedModules={null}
colors={filledColors}
hiddenImportedModules={hidden}
readOnly
/>
</div>
Expand Down
3 changes: 2 additions & 1 deletion website/src/entry/export/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ window.store = store;
// For Puppeteer to import data
const timetableRef = createRef<TimetableOnly>();
window.setData = function setData(modules, data, callback) {
const { semester, timetable, colors } = data;
const { semester, timetable, colors, hidden } = data;

if (document.body) {
document.body.classList.toggle('mode-dark', data.settings.colorScheme === DARK_COLOR_SCHEME);
Expand All @@ -43,6 +43,7 @@ window.setData = function setData(modules, data, callback) {
semester,
timetable,
colors,
hidden,
},
callback,
);
Expand Down

0 comments on commit fec9bfa

Please sign in to comment.