ISMIS Helper: cross-browser build, CI, PDF fixes, Chrome download fix #1
@@ -1 +1,4 @@
|
|||||||
node_modules/
|
node_modules/
|
||||||
|
|
||||||
|
docs/
|
||||||
|
dist/
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,145 +0,0 @@
|
|||||||
# ISMIS Helper — Firefox Extension Design
|
|
||||||
|
|
||||||
**Date:** 2026-08-18
|
|
||||||
**Status:** Approved
|
|
||||||
**Target site:** `https://ismis.usc.edu.ph` (USC ISMIS student portal)
|
|
||||||
|
|
||||||
## Overview
|
|
||||||
|
|
||||||
A personal Firefox extension (Manifest V3, no build step) that improves the USC ISMIS
|
|
||||||
student portal experience. It provides three features:
|
|
||||||
|
|
||||||
1. **Auto-login** — auto-fill and auto-submit the login form from a saved profile.
|
|
||||||
2. **Auto-accept Privacy Policy** — dismiss the recurring privacy-policy modal.
|
|
||||||
3. **Study Load PDF** — an on-page "Download PDF" button on the Study Load page that
|
|
||||||
generates a PDF replicating the official ISMIS Study Load document (Letter size,
|
|
||||||
with course descriptions looked up from the Offered Courses endpoint) and
|
|
||||||
downloads it directly.
|
|
||||||
|
|
||||||
A single **master toggle** disables all extension behavior on the portal.
|
|
||||||
|
|
||||||
## Architecture
|
|
||||||
|
|
||||||
Single MV3 extension, plain JavaScript, no bundler. No background script — all logic
|
|
||||||
runs in the content script (scraping and print-document building happen in-page).
|
|
||||||
|
|
||||||
```
|
|
||||||
ismis-helper/
|
|
||||||
├── manifest.json # MV3 manifest, permissions, content script, popup, background
|
|
||||||
├── background.js # message handler: build PDF (pdf-lib) + download via downloads API
|
|
||||||
├── content.js # runs on ismis.usc.edu.ph: auto-login, privacy, button, scrape
|
|
||||||
├── parsers.js # UMD: table/profile/offered-courses parsing + filtering
|
|
||||||
├── pdf.js # UMD: buildStudyLoadPdf (Letter PDF, official layout, pagination)
|
|
||||||
├── popup.html # popup UI (master toggle + profiles)
|
|
||||||
├── popup.js # popup logic
|
|
||||||
├── popup.css # popup styles
|
|
||||||
├── libs/pdf-lib.min.js # vendored pdf-lib library (used by background)
|
|
||||||
└── icons/ # extension icons (16, 32, 48, 128)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Permissions (manifest.json)
|
|
||||||
- `storage` — persist profiles and the master toggle.
|
|
||||||
- `downloads` — save the generated Study Load PDF.
|
|
||||||
- `host_permissions` — `https://ismis.usc.edu.ph/*` for the content script.
|
|
||||||
- Background loads `libs/pdf-lib.min.js` + `pdf.js` via `background.scripts`.
|
|
||||||
|
|
||||||
## Background script
|
|
||||||
- `background.js` handles the `generate-pdf` message from the content script:
|
|
||||||
builds the PDF via `ISMIStools.buildStudyLoadPdf`, wraps the bytes in a Blob,
|
|
||||||
downloads via `browser.downloads.download({ saveAs: true })`, and revokes the
|
|
||||||
object URL when the download reaches `complete`/`interrupted` (and on failure).
|
|
||||||
|
|
||||||
## Component 1 — Auto-login
|
|
||||||
|
|
||||||
- Content script runs on `https://ismis.usc.edu.ph/Account/Login`.
|
|
||||||
- Reads the active (enabled) profile from `browser.storage.local`.
|
|
||||||
- Locates the username and password input fields (`name`/`id` = `Username` /
|
|
||||||
`Password`, with fallback variants).
|
|
||||||
- Fills both fields, then submits the form (auto-submit).
|
|
||||||
- If no profile is enabled, or the master toggle is off, does nothing.
|
|
||||||
|
|
||||||
## Component 2 — Auto-accept Privacy Policy
|
|
||||||
|
|
||||||
- On any portal page, if the privacy modal `#myModal` is present and visible:
|
|
||||||
- Check the `#Confirmation` checkbox ("I have read and understood the Privacy
|
|
||||||
Policy Statement").
|
|
||||||
- Click the `#Submit` button (Continue), which is disabled until the checkbox is
|
|
||||||
checked.
|
|
||||||
- Gated by the master toggle.
|
|
||||||
|
|
||||||
## Component 3 — Profiles
|
|
||||||
|
|
||||||
- Stored in `browser.storage.local` under key `profiles` as an array of:
|
|
||||||
`{ id, name, username, password, enabled }`.
|
|
||||||
- Popup provides add, edit, delete, and enable/disable per profile.
|
|
||||||
- Only one profile can be enabled at a time (enabling one disables the others);
|
|
||||||
that profile is used for auto-login.
|
|
||||||
- Master toggle stored under key `enabled` (boolean).
|
|
||||||
|
|
||||||
## Component 4 — Study Load PDF
|
|
||||||
|
|
||||||
### On-page button
|
|
||||||
- The content script watches the Study Load page (`#StudyLoad`). When the course
|
|
||||||
table appears (after the user selects academic period/year and searches), it
|
|
||||||
injects a **"Download PDF"** button inline with the
|
|
||||||
`12.00 Units / Total Units: 18.00` footer (button on the left, units text on the
|
|
||||||
right, via a flex row), styled like the page's buttons (`btn green`).
|
|
||||||
|
|
||||||
### Scrape
|
|
||||||
- Parse the course table (columns: Group #, Course Code, Schedule, Faculty, Units,
|
|
||||||
Status) via `parseStudyLoadTable`.
|
|
||||||
- **Header info** (full name, student ID, program, year level, semester) is scraped
|
|
||||||
from the **My Profile** page (`/Manage/Student`).
|
|
||||||
|
|
||||||
### Filtering
|
|
||||||
- **DISSOLVED courses are excluded** (`filterStudyLoadCourses`).
|
|
||||||
- Total units = sum of the included courses' units (`sumUnits`).
|
|
||||||
|
|
||||||
### Description lookup
|
|
||||||
- For each unique course code, POST to
|
|
||||||
`https://ismis.usc.edu.ph/CourseSchedule/CourseScheduleOffered` with the
|
|
||||||
`__RequestVerificationToken` and selected `AcademicPeriod`/`AcademicYear`, then
|
|
||||||
parse the returned table for the **Course Description**.
|
|
||||||
- If lookup fails for a course, the description is left blank and generation
|
|
||||||
continues.
|
|
||||||
|
|
||||||
### PDF generation
|
|
||||||
- `pdf.js` (`buildStudyLoadPdf`, using **pdf-lib**) builds a Letter-size (612×792pt)
|
|
||||||
PDF replicating the official layout: title block (STUDENT'S STUDY LOAD, semester,
|
|
||||||
date range, date enrolled), student info row (ID, name, program, year level), the
|
|
||||||
course table (GROUP, COURSE, COURSE DESCRIPTION, TEACHER, UNITS, NOTE — NOTE is
|
|
||||||
the status), and a footer (total units, "Printed by: …"). Multi-page
|
|
||||||
pagination re-draws the table header. NOTE column is wide enough for `REGULAR`.
|
|
||||||
- The content script sends the data to the background (`generate-pdf`), which
|
|
||||||
downloads the PDF via the `downloads` API (`saveAs: true`).
|
|
||||||
|
|
||||||
## Data flow
|
|
||||||
|
|
||||||
```
|
|
||||||
Study Load page ──▶ content script (scrape + filter DISSOLVED + description lookup)
|
|
||||||
│
|
|
||||||
▼ browser.runtime.sendMessage({ type: 'generate-pdf', data })
|
|
||||||
background.js (pdf-lib buildStudyLoadPdf)
|
|
||||||
│
|
|
||||||
▼
|
|
||||||
browser.downloads.download → Study Load PDF file
|
|
||||||
```
|
|
||||||
|
|
||||||
## Error handling
|
|
||||||
|
|
||||||
- Master toggle off → no extension behavior on the portal.
|
|
||||||
- No enabled profile → no auto-login.
|
|
||||||
- Description lookup fails for a course → blank description, PDF still generated.
|
|
||||||
- No enrolled (non-DISSOLVED) courses → error toast, no download.
|
|
||||||
- Download fails → error toast; object URL is revoked.
|
|
||||||
|
|
||||||
## Testing
|
|
||||||
|
|
||||||
- Node `node:test` suites: parsers (table/profile/offered-courses/filter/sum) and
|
|
||||||
pdf (valid Letter PDF output).
|
|
||||||
- Load via `about:debugging` → "Load Temporary Add-on".
|
|
||||||
- Verify auto-login on the login page.
|
|
||||||
- Verify privacy modal auto-accept.
|
|
||||||
- Verify profile add/edit/delete/toggle and master toggle.
|
|
||||||
- Verify the on-page Download PDF button: appears inline with the total-units
|
|
||||||
footer, excludes DISSOLVED courses, and downloads a Letter-size PDF.
|
|
||||||
Reference in New Issue
Block a user