Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/workflows/pr-checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,9 @@ jobs:
exit 1
fi

test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Extension tests
run: for t in extension/*.test.js; do node "$t"; done
19 changes: 18 additions & 1 deletion .github/workflows/publish-extension.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
# manifests only; the tag records what shipped.
#
# A store whose secrets are missing is skipped, not failed, so stores can be
# connected one at a time.
# connected one at a time. A store that rejects an upload (for example Chrome
# while the previous version is still in review) does not stop the other
# stores or the release; the run is marked failed at the end so it shows up.
#
# Secrets (repo settings, Actions):
# CWS_CLIENT_ID, CWS_CLIENT_SECRET, CWS_REFRESH_TOKEN Chrome Web Store API
Expand Down Expand Up @@ -63,6 +65,9 @@ jobs:
echo "version=$version" >> "$GITHUB_OUTPUT"
echo "new=true" >> "$GITHUB_OUTPUT"

- name: Test
run: for t in extension/*.test.js; do node "$t"; done

- name: Build and zip
if: steps.version.outputs.new == 'true'
run: |
Expand All @@ -77,6 +82,8 @@ jobs:
ls -l release

- name: Chrome Web Store
id: cws
continue-on-error: true
if: steps.version.outputs.new == 'true' && env.HAS_CWS == 'true'
env:
CLIENT_ID: ${{ secrets.CWS_CLIENT_ID }}
Expand All @@ -86,13 +93,17 @@ jobs:
run: npx -y chrome-webstore-upload-cli@3 --source "release/elbi-gradesim-chrome-${{ steps.version.outputs.version }}.zip"

- name: Firefox Add-ons
id: amo
continue-on-error: true
if: steps.version.outputs.new == 'true' && env.HAS_AMO == 'true'
env:
WEB_EXT_API_KEY: ${{ secrets.AMO_JWT_ISSUER }}
WEB_EXT_API_SECRET: ${{ secrets.AMO_JWT_SECRET }}
run: npx -y web-ext@8 sign --channel listed --source-dir extension/dist/firefox --artifacts-dir release/amo

- name: Edge Add-ons
id: edge
continue-on-error: true
if: steps.version.outputs.new == 'true' && env.HAS_EDGE == 'true'
env:
EDGE_PRODUCT_ID: ${{ secrets.EDGE_PRODUCT_ID }}
Expand Down Expand Up @@ -120,3 +131,9 @@ jobs:
run: |
tag="extension-v${{ steps.version.outputs.version }}"
gh release create "$tag" release/*.zip --target "$GITHUB_SHA" --title "Elbi GradeSim ${{ steps.version.outputs.version }}" --generate-notes

- name: Fail if a store rejected the upload
if: steps.cws.outcome == 'failure' || steps.amo.outcome == 'failure' || steps.edge.outcome == 'failure'
run: |
echo "::error::Store results: Chrome=${{ steps.cws.outcome }} Firefox=${{ steps.amo.outcome }} Edge=${{ steps.edge.outcome }}. Re-run this workflow once the store accepts uploads again."
exit 1
61 changes: 25 additions & 36 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,69 +2,58 @@

**Human developers:** start with [README.md](README.md).

Org-wide agent defaults: see [room-tba/AGENTS.md](https://github.com/uplbtools/room-tba/blob/main/AGENTS.md). This file tailors that playbook to the **GradeSim browser extension**.
Org-wide agent defaults are in [room-tba/AGENTS.md](https://github.com/uplbtools/room-tba/blob/main/AGENTS.md). This file tailors them to the GradeSim browser extension.

## Doc map

| When | Read |
| --- | --- |
| How grades get in, storage keys, permissions | [extension/README.md](extension/README.md) |
| Build all browsers | `extension/build.sh` |
| Per-browser manifests | `extension/manifests/` |
| Landing / marketing site | [uplbtools/gradesim-website](https://github.com/uplbtools/gradesim-website) |
| Store listings | Chrome Web Store, Firefox Add-ons URLs in README |
| Web app | [uplbtools/gradesim-website](https://github.com/uplbtools/gradesim-website), live at <https://gradesim.uplb.tools> |
| Store listings | README |

## Stack

- **Platform:** Manifest V3 **browser extension** (vanilla JavaScript: no bundler in root)
- **Targets:** Chrome, Firefox, Opera, Edge (separate manifests)
- **Build:** `extension/build.sh [chrome|firefox|opera|edge|all]` → `extension/dist/<browser>/`
- **Host permission:** `amis.uplb.edu.ph`: content scripts read AMIS DOM locally
- **No server**: 100% client-side; no `package.json` scripts at repo root
- Manifest V3 browser extension in plain JavaScript, no bundler and no root `package.json`
- Targets are Chrome, Firefox and Opera manifests. Edge and Brave install the Chrome build.
- `extension/build.sh [chrome|firefox|opera|edge|all]` writes `extension/dist/<browser>/`. `edge` is an alias for `chrome`.
- Grades come from the AMIS JSON API, not page scraping. `content.js` calls `api-amis.uplb.edu.ph/api/students/grades` with the token AMIS keeps in `localStorage`, then stores only the course fields.
- No server. Everything stays in `chrome.storage.local`.

## Branches and release

| Branch | Role |
| --- | --- |
| **`staging`** | Default branch: integration |
| **`main`** | Release line for store submissions |
| `staging` | Default branch. All pull requests go here. |
| `main` | Release line. A push that touches `extension/` publishes to the Chrome, Firefox and Edge stores through `.github/workflows/publish-extension.yml`. |

**Ship flow:** merge to `main`, build with `./build.sh all`, upload zips to each browser store. Store review is human-gated: do not auto-close issues that depend on store approval.

There is no Vercel/CI deploy: verification is local build + manual load in browser dev mode.
Never push or open pull requests to `main` directly. Store review is human-gated, so do not close issues that wait on store approval.

## Verify before done

| Step | When |
| --- | --- |
| `cd extension &&./build.sh chrome` | Minimum before any extension change |
| `./build.sh all` | Before store release |
| Manual AMIS | Load unpacked extension; open AMIS schedule page; confirm GWA/simulator still works |
| Manifest diff | When touching permissions: review all files in `extension/manifests/` |

## Architecture (short)

```
extension/
src/ # Popup, content scripts, curriculum data
manifests/ # Per-browser manifest.json variants
icons/
build.sh # Copies src + manifest → dist/<browser>/
website/ # Legacy copy: canonical website is gradesim-website repo
```
| `for t in extension/*.test.js; do node "$t"; done` | Every change (CI runs it too) |
| `bash extension/build.sh all` | Every extension change |
| `npx -y web-ext@8 lint -s extension/dist/firefox` | Must show 0 errors and 0 warnings |
| Manual AMIS check | Load the unpacked build, log in to AMIS, press Refresh in the popup, confirm grades and GWA |
| Manifest diff | When touching permissions, update every file in `extension/manifests/` |

## Extension rules

- **Privacy:** Never send grades or student data to a server: local `chrome.storage` / `browser.storage` only
- **AMIS DOM scraping:** AMIS markup changes break the extension: prefer defensive selectors; add fixture HTML tests when possible
- **Multi-browser parity:** A manifest or permission change often needs all four manifest files updated
- **No decorative UI motion** in popup: keep the panel calm and readable
- Never send grades or student data to a server.
- Keep the stored grades shape (`gradesData.student_grades`) compatible with the web app importer in gradesim-website `src/lib/importers.ts`.
- Firefox add-on review rejects `innerHTML`, `outerHTML` and `insertAdjacentHTML` with dynamic strings. Build markup with `DOMParser` or DOM calls.
- No decorative motion in the popup. Keep the panel calm and readable.

## Commits

- Conventional Commits: `fix(content): …`, `feat(curriculum): …`, `chore(build): …`
- Note which browsers were manually tested in the PR body
- Conventional Commits, for example `fix(content): ...`, `feat(planner): ...`, `chore(build): ...`
- Note which browsers you tested in the PR body.

## Security

- Do not add broad `<all_urls>` permissions without maintainer approval
- Never exfiltrate AMIS page content to third-party analytics
- Do not add `<all_urls>` or other broad permissions without maintainer approval.
- Never send AMIS content to analytics or third parties.
50 changes: 50 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,55 @@
# Changelog

## 2.1.0 (2026-10-06)

### Features
- The web app at gradesim.uplb.tools can import your grades straight from the extension when you press Import there.
- The planner follows your SP or thesis track.
- First run asks for your program, with a one line terms notice instead of a terms wall. Programs without a checklist yet show as coming soon.
- The What if tab leads with the average you need. When a target is out of reach it shows the best GWA still possible, the best honor still in reach, and a link that opens the planner on the failed course.
- The popup shows when grades were last updated, has Refresh in the main view, and says what to do when AMIS is logged out or does not answer.
- A rough guide notice in the popup and planner for programs with thin prerequisite data.

### Fixes
- A 4.00 or 5.00 stays in the GWA but no longer counts as a completed course. PEd majors' courses are no longer dropped as PE. No honors show before any graded unit, and scholar badges need 15 units with no 5.00, 4.00 or INC.
- The popup fills the screen on Firefox for Android.
- Grades load without reloading AMIS. The extension calls the AMIS grades API once per hour with your login, and Refresh in the popup fetches right away from the open AMIS tab.
- Only the course fields GradeSim uses are saved, not the whole AMIS response.
- Export JSON saves every setting, including planner pins, petitions and theme, with a schema version. Import no longer accepts the terms for you.
- New Clear my data button in Help.
- What if and the planner count remaining units the same way. HK and NSTP complete, GE courses count by code, programs without tracks get no made up free electives, and an average above 3.00 means any passing grade is enough.
- The planner plans 18 units a sem unless you choose 21, free elective cards are never critical, Reset plan asks in a dialog, and a button shows when terms run past the right edge.
- AMIS term ids past 2029 parse.
- A one line unofficial estimate disclaimer sits under the GWA and on the planner.
- Sharper toolbar icons at 16, 32 and 48 px, and one store name, Elbi GradeSim, everywhere.

## [2.0.4] - 2026-10-06

- Same code as 2.0.3, published again.

## [2.0.3] - 2026-10-05

### Fixes
- Planner legend chips are added without `insertAdjacentHTML`, which the Firefox add-on review flags.

## [2.0.2] - 2026-10-05

### Fixes
- Planner markup is built with `DOMParser` instead of `innerHTML`.

## [2.0.1] - 2026-10-05

### Fixes
- Planner icon placeholders are swapped without assigning `outerHTML`.

## [2.0.0] - 2026-10-05

### Features
- Course planner. A curriculum map of your program with prerequisites from the AMIS catalog, the critical path, retakes, petitions and what-if plans, laid out term by term.
- UPLB Tools look. New colors, self-hosted fonts, light and dark themes, and a flat plumbob icon.
- Links point to the new home at gradesim.uplb.tools and its hosted terms and privacy pages.
- Store builds for Chrome, Firefox and Edge are published from CI.

## [1.2.1] - 2026-05-29

### Features
Expand Down
34 changes: 22 additions & 12 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,38 @@ Open a [GitHub issue](https://github.com/uplbtools/gradesim/issues) with:

- Browser and extension version
- Steps to reproduce
- Expected vs actual grade or GWA output
- Expected and actual grade or GWA output

You do not need a pull request for typo reports in curriculum data: an issue is enough.
A typo in curriculum data only needs an issue, not a pull request.

## Developers

### Setup
### Build

```sh
cd extension
./build.sh chrome # or firefox, all
bash extension/build.sh all # chrome, firefox and opera
bash extension/build.sh chrome # one target
```

Load `extension/dist/<browser>/` via your browser’s developer / unpacked extension UI, or install from the [Chrome Web Store](https://chromewebstore.google.com/detail/elbi-gradesim-uplb-gwa-ca/mlhklblbhkikcmobmmajckjcbmdinldb) or [Firefox Add-ons](https://addons.mozilla.org/en-US/firefox/addon/elbi-gradesim/).
Edge, Brave and Opera install the Chrome build, so `build.sh edge` is an alias for `chrome`. Load `extension/dist/<browser>/` as an unpacked extension in developer mode.

### Pull requests
### Test

1. Branch from **`staging`**.
2. Keep commits focused; use [Conventional Commits](https://www.conventionalcommits.org/) (`fix(extension): …`, `docs: …`).
3. Open a PR to **`staging`** and link any related issue.
4. Do not commit secrets or store listing credentials.
```sh
for t in extension/*.test.js; do node "$t"; done
npx -y web-ext@8 lint -s extension/dist/firefox
```

CI runs the tests on every pull request. The Firefox lint should report 0 errors and 0 warnings, since addons.mozilla.org rejects or delays builds that warn.

### Branches and pull requests

1. Branch from `staging`.
2. Keep commits focused and use [Conventional Commits](https://www.conventionalcommits.org/), for example `fix(extension): ...` or `docs: ...`.
3. Open the pull request against `staging`. Its body must close an issue (`Closes #123`).
4. Maintainers merge `staging` into `main` to release. Every push to `main` that touches `extension/` publishes to the Chrome, Firefox and Edge stores, so never open a pull request straight to `main`.
5. Do not commit secrets or store credentials.

## Code of conduct

See [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md). Be helpful to students; verify grade logic against official UPLB rules when possible.
See [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md). Be helpful to students, and check grade logic against official UPLB rules when you can.
79 changes: 8 additions & 71 deletions PRIVACY_POLICY.md
Original file line number Diff line number Diff line change
@@ -1,76 +1,13 @@
# Privacy Policy for Elbi GradeSim

**Last Updated: January 8, 2026**
The full, current policy is at **<https://gradesim.uplb.tools/privacy/>**.

## Overview
In short:

Elbi GradeSim is a browser extension that helps UPLB students calculate their GWA (General Weighted Average) and simulate grades needed for Latin honors. This privacy policy explains how we handle your data.
- Elbi GradeSim reads your grades from the UPLB AMIS grades API using your own logged-in session. It never sees or stores your password.
- It keeps only the course fields it needs, in your browser's extension storage on your device.
- It sends nothing to any server. There are no analytics, ads or tracking.
- It shares your grades with the Elbi GradeSim web app at gradesim.uplb.tools only when you press Import there, and that hand-off stays inside your browser.
- Clear my data in the popup's Help, or removing the extension, deletes everything it stored.

## Data Collection

### What We Access
- **Grades Data**: The extension accesses your grades information from the UPLB AMIS (Academic Management Information System) portal when you are logged in.

### What We DO NOT Collect
- We do NOT collect any personal identification information
- We do NOT collect your AMIS login credentials
- We do NOT track your browsing activity
- We do NOT use analytics or tracking services
- We do NOT share any data with third parties

## Data Storage

- **Local Storage Only**: All your grades data is stored locally on your device using Chrome's built-in storage (`chrome.storage.local`)
- **No External Servers**: Your data is NEVER sent to any external servers
- **No Cloud Sync**: Your data is not synced across devices

## Data Usage

Your grades data is used exclusively for:
1. Calculating your current GWA
2. Displaying your grades history
3. Simulating grades needed for target Latin honors
4. Tracking remaining courses in your curriculum

## Permissions Explained

| Permission | Why We Need It |
|------------|----------------|
| `storage` | To save your grades data locally on your device |
| `host_permissions` for amis.uplb.edu.ph | To access the AMIS portal and read your grades |

## Data Deletion

You can delete all stored data at any time by:
1. Right-clicking the extension icon
2. Selecting "Remove from Chrome"
3. Or going to Chrome Settings > Extensions > Elbi GradeSim > Remove

Alternatively, clear the extension's data via:
Chrome Settings > Privacy and Security > Clear Browsing Data > Cookies and other site data

## Security

- The extension only works on the official UPLB AMIS website (amis.uplb.edu.ph)
- We use your existing AMIS session - we never ask for or store your password
- All data processing happens locally in your browser

## Children's Privacy

This extension is intended for university students and does not knowingly collect information from children under 13.

## Changes to This Policy

We may update this privacy policy from time to time. Any changes will be reflected in the "Last Updated" date.

## Contact

If you have questions about this privacy policy, please open an issue on our GitHub repository.

## Open Source

This extension is open source. You can review the complete source code to verify our privacy practices.

---

**Summary**: Your data stays on YOUR device. We don't collect, store, or share anything.
Questions go to the [GitHub issues](https://github.com/uplbtools/gradesim/issues).
Loading
Loading