✦ Internal Documentation

ULAB Faculty Companion

A Chrome side-panel extension that gives ULAB faculty a set of tools built directly on top of URMS — finding common free time across students, running automated advising checks, and (carefully) bulk-confirming staged registrations. Everything runs locally in the browser using your existing URMS session; nothing is sent to a third-party server.

Overview

URMS (the university's registration/attendance portal) requires a lot of repetitive manual work — checking each student's attendance one by one to find shared free periods, or opening every advisee's page individually to check probation status, failed courses, and prerequisites. This extension automates that by driving the same requests the URMS pages themselves make, using the browser's existing logged-in session, and presenting the results in one place.

The extension is a Chrome Side Panel app (not a popup) — click the toolbar icon once to pin it open, and it stays available alongside whatever tab you're working in. Each tool is a self-contained feature module registered into a shared sidebar shell (see Architecture), so new tools can be added without touching existing ones.

Manifest V3 Chrome Side Panel API No backend / no analytics chrome.storage.local only

How It Works

The general shape is the same for every data-driven feature (Time, Advising, Bulk Save):

  1. Open the side panel and pick a feature from the icon rail on the left.
  2. Paste a student list (an attendance sheet export, an Advising Student export, etc.) into the paste box, then confirm/edit the parsed rows.
  3. The extension calls URMS directly — for each student, it POSTs to the same StudentRegistration endpoint the site's own pages use (e.g. clicking "Load" on a student), using fetch(url, { credentials: 'include' }) so your browser attaches the URMS session cookies you already have. There's no separate login step; if you're not logged in to URMS in that Chrome profile, these requests fail the same way loading the page manually would.
  4. The response HTML is parsed in-browser (via DOMParser) to pull out whatever that feature needs — a weekly schedule, a probation banner, a grade history table, or (for Bulk Save) the currently-staged course rows.
  5. Analysis runs entirely client-side — e.g. Student Advising cross-references a student's course history against the selected program's catalogue in features/advising/catalogues/ (CSE, BBA, English, MSJ, EEE, or Bangla) to compute retakes, prerequisite gaps, lab/theory violations, and degree-progress credit sums. Nothing is sent anywhere for this step.
  6. Results are handed off to a report tab for anything too large for the side panel: written to chrome.storage.local, then a full browser tab is opened (via the background service worker) that reads that same storage key back out and renders it.

Bulk Save follows the same Load step, but then writes — it submits the staged data straight back to URMS, replicating the page's own Save action. See Bulk Save for exactly how that's different and what to verify. Course Catalogue Viewer and Marks Management don't fetch anything from URMS at all — the former just renders a local data file, the latter is a plain link to an external site.

Installation (Load Unpacked)

This extension is not published on the Chrome Web Store — it's loaded locally as an unpacked extension:

  1. Open chrome://extensions in Chrome.
  2. Enable Developer mode (top-right toggle).
  3. Click Load unpacked and select this project's root folder.
  4. Pin the extension to the toolbar, then click its icon to open the side panel.
  5. Make sure you're logged in to urms-awp.ulab.edu.bd in the same Chrome profile — the extension reuses that session's cookies for every request.

After pulling code changes, click the reload icon on the extension's card in chrome://extensions to pick them up.

Architecture

Side Panel shell

manifest.json declares side_panel.default_path pointing at sidebar/sidebar.html. background.js is a minimal service worker with two jobs: call chrome.sidePanel.setPanelBehavior so clicking the toolbar icon opens the panel, and listen for chrome.runtime.onMessage requests from feature modules asking to open one of their report pages in a full tab.

Feature module pattern

Each feature lives in its own folder under features/ and registers itself onto a shared window.ULAB_FEATURES array with an id, icon, title, subtitle, and a mount(container) function:

window.ULAB_FEATURES.push({
    id: 'time',
    icon: '🕐',
    title: 'Free Time Finder',
    subtitle: '...',
    mount(container) { /* render the feature's UI into container */ }
});

sidebar/sidebar.js reads that array, renders one icon per feature in the left rail, and calls the matching module's mount() when clicked. This means adding a new tool is just: create a folder, register a feature object, add a <script> tag in sidebar.html — nothing about the shell itself needs to change.

Report pages

Features that produce a large result set (Time, Advising, Bulk Save, the Catalogue Viewer) open a dedicated full-tab HTML report instead of cramming a wide table into the narrow side panel. The mounted sidebar UI writes its results to chrome.storage.local, sends a chrome.runtime.sendMessage to the background worker, which opens the report tab via chrome.tabs.create; the report page then reads the same storage key back out.

Shared styling

features/common/wizard.css holds the paste/confirm/run wizard styling shared by every feature that follows the "paste a student list → confirm → run" pattern (Time, Advising, Bulk Save), so they look and behave consistently without duplicating CSS per feature.

🕐 Free Time Finder

Finds common free class periods across a group of students by pulling each student's schedule directly from URMS's StudentRegistration endpoint (the same call the site's own Add/Drop page makes) — no PDF parsing, no page-injection required.

Workflow

  1. Paste a list of students (9-digit ID + name per line, copied from an attendance sheet or typed manually).
  2. Confirm/edit the parsed list and set a free-time threshold (e.g. "75%+ of students free").
  3. Run — the extension fetches each student's weekly schedule and evaluates it against the university's fixed class slots (Slot 1–7).
  4. A report tab opens showing, per day, which slots are free for everyone vs. free for the threshold percentage, plus each student's individual schedule.

🎓 Student Advising

Automates the manual "open every advisee's page and check for problems" routine. Paste the university's own Advising Student list export, and for each student the extension checks:

CheckHow it's determined
Probation status & tierParsed from the probation banner on the student's own page (e.g. "Probation number-2" → Tier 2).
Courses needing a retakeAny course with a failing grade and no later passing grade — cleared if they've passed it since, or are currently re-registered for it.
Prerequisite violationsFor every course added this semester, checks the catalogue's declared prerequisites against the student's passing-grade history.
Lab without theorySeparate from the above — flags a lab course added without its paired theory course ever being taken or concurrently registered (not a formal "prerequisite" in the catalogue, but university policy).
Degree progressSums earned + in-progress credits per degree-requirement category (GED, Major Core, Major Elective, Other Engineering, Optional/Minor, Basic Science, Mathematics — 140 credits total) and flags shortfalls. ESK is intentionally excluded — confirmed not part of the CSE degree requirement.

Every check resolves course codes through the catalogue whether a student's record shows the current UNESCO code or an older local code (e.g. CSE1301) — history rows, added courses, and prerequisite lookups are all normalized to the same canonical code before comparing, so a course doesn't silently fail to match just because one semester's row used a different code format than another. Student Advising first asks which program (CSE, BBA, English, MSJ, EEE, or Bangla) the batch belongs to; the prerequisite and lab/theory data for each comes from its own file under features/advising/catalogues/ — see Course Catalogue Viewer to browse any of them directly.

Communication tools

The report page includes:

  • A Hide clean students filter, to focus on advisees that actually need attention.
  • Per-student and bulk email generation — opens a modal with the recipient address(es) and a plain-text message, with buttons to copy either and a button to open a blank Gmail compose window to paste them into.
  • CSV export of the full report.
Automated, not authoritative. Every generated warning and email carries a disclaimer that this is a best-effort automated check derived from a hand-transcribed prerequisite map — always spot-check anything the advisor is going to act on.

💾 Bulk Save writes data

Unlike the read-only features above, Bulk Save submits real registration data to URMS. For each pasted student it replicates exactly what a human clicking that student's own "Save" button does: loads their Add/Drop page, reads the currently-staged Course/Section/CourseCredit rows and the live RegDateString/FineAmount/Comments/etc. values straight off that response, and posts them back unchanged.

This does not add, remove, or edit any course. It only confirms whatever is already staged on the student's own page. It runs fully unattended once started — there is no per-student pause — so review the pasted list carefully before clicking "I understand — Run Bulk Save."

Result detection

Each student's outcome is classified from the actual server response, not assumed:

StatusMeaning
SavedResponse contained URMS's own "Saved successfully" banner.
FailedAn HTTP error, or a validation-error block was found in the response.
UnconfirmedNeither a success banner nor an error was detected — genuinely ambiguous, flagged for manual verification rather than assumed to have worked.
SkippedNo courses were staged for that student — nothing to confirm.

A report tab lists every student's outcome with a CSV export.

📖 Course Catalogue Viewer

A searchable, full-tab table of every course the extension knows about — code, UNESCO code, title, resolved prerequisites, and lab→theory pairing, with a program picker (CSE/BBA/English/MSJ/EEE/Bangla) at the top. It reads live from features/advising/catalogues/, the same files Student Advising uses, so if a warning in Advising looks wrong, this is the first place to check.

The catalogue was transcribed by hand from the university's course catalogue PDF using pdftotext -table (which keeps prerequisite columns aligned to their row far more reliably than plain -layout mode). It is not sourced from a live, authoritative feed — treat it as a best-effort reference and report mismatches against the PDF for correction. Each course also carries its legacy local code (e.g. CSE1301) alongside its UNESCO code — see Data Flow & Permissions for why both matter.

📊 Marks Management

A simple launcher — clicking Manage Marks opens the external Marks Management System in a new browser tab. This extension doesn't read from, write to, or otherwise integrate with that site; it's just a shortcut.

File Structure

. ├── manifest.json # MV3 manifest, side_panel + host_permissions ├── background.js # service worker: opens side panel, opens report tabs ├── icons/ # toolbar/store icons, generated from ulab-logo.png ├── sidebar/ │ ├── sidebar.html # side panel shell │ ├── sidebar.js # feature rail + router │ └── sidebar.css ├── features/ │ ├── common/ │ │ └── wizard.css # shared paste/confirm/run wizard styling │ ├── time/ # Free Time Finder │ ├── advising/ # Student Advising + catalogues/<program>.js data │ ├── bulk-save/ # Bulk Save │ └── catalogue-viewer/ # Course Catalogue Viewer └── docs/ ├── index.html # this page └── privacy-policy.html

Data Flow & Permissions

manifest.json declares host_permissions for https://urms-awp.ulab.edu.bd/* and the storage + sidePanel permissions — nothing else. Every feature's requests use fetch(url, { credentials: 'include' }) from the extension's own side panel / tab context, which sends whatever URMS session cookies already exist in that Chrome profile. There is no separate login flow, token storage, or credential handling by the extension itself.

Fetched data (schedules, advising details, save results) is written to chrome.storage.local only, purely to hand results off between the side panel and a report tab. It never leaves the browser, is never sent to any server other than URMS, and is overwritten the next time a feature runs.

See the Privacy Policy for the full statement.

Known Limitations

  • The prerequisite/lab-theory catalogue is hand-transcribed from a PDF and may contain errors — verify anything surprising against the source PDF or the live Catalogue Viewer.
  • Bulk Save's success/failure detection depends on a specific HTML banner/error class existing in URMS's response; if URMS changes that markup, detection could silently degrade to "Unconfirmed" for everything (safe) or misclassify (in the worst case) — spot-check after any URMS UI change.
  • All features depend on an active, logged-in URMS session in the same Chrome profile; there's no in-extension login or session-refresh handling.
  • The extension is unpacked/unsigned and not distributed via the Chrome Web Store.
  • Major Elective and Optional/Minor credits in Degree Progress are estimated from UNESCO-code patterns, not an exhaustive course list (concentration electives and other-department courses number in the dozens and aren't individually enumerated) — treat "short by N credits" for those two categories as approximate. One known pattern exception: CSE4455 "Data Mining" is misclassified as Optional/Minor.
  • Legacy local course codes (e.g. CSE1301) are matched alongside UNESCO codes for every course explicitly listed in the catalogue, but a course renumbered under a different UNESCO code over time would need that old UNESCO code added to its oldCodes array by hand — the catalogue PDF doesn't document any such renumbering.

Changelog

Dated by when each batch of work landed in this repository, newest first.

2026-07-21

  • Added multi-program support to Student Advising — a new program picker (CSE, BBA, English & Humanities, MSJ, EEE, or Bangla) now runs first, and every catalogue lookup (degree-progress credit sums, category labels, prerequisite/lab-theory checks) uses that program's own catalogue instead of always assuming CSE. Capstone Eligibility stays CSE-only by design — its subtitle now says so explicitly.
  • Refactored the catalogue data model: features/advising/catalogue.js was split into a shared catalogue-factory.js builder plus one file per program under features/advising/catalogues/ (cse.js, bba.js, english.js, msj.js, eee.js, bangla.js), each registering into a window.ULAB_CATALOGUES registry. The Course Catalogue tab gained a matching program dropdown.
  • Added a full course catalogue for the Bangla Language and Literature department — previously excluded because the source PDF prints its course codes in Bangla numerals; resolved by cross-referencing a real URMS course-code export (courses-scrapped-urms.txt) that lists the department's actual Latin BLL#### codes.
  • Added real UNESCO codes to the BBA, English, MSJ, and EEE catalogues — these programs' section of the main catalogue PDF only prints local course codes, so each course's UNESCO code (and, where it had changed, its legacy local code) was cross-matched by title against that same URMS course-code export. Unmatched courses keep their local code as a fallback and are flagged as unverified in each file's header comment.
  • Added a PDF upload option to Student Advising and Bulk Save, as an alternative to copy/pasting the printed Advising Student table — upload a "Save as PDF" export of that page instead, and its text is extracted client-side (via a locally vendored pdf.js, no network calls) and fed into the same paste/parse pipeline both features already had.

2026-07-15

  • Added 📊 Marks Management — a launcher that opens the external Marks Management System in a new tab.
  • Fixed a regression where catalogue.js's exported degreeRequirements was accidentally dropped while adding legacy-code support, crashing Advising with "Cannot read properties of undefined (reading 'credits')".
  • Added legacy course-code matching — every catalogue lookup (title, category, prerequisites, lab/theory pairing) now resolves a course whether a student's record shows the current UNESCO code or the older local code (e.g. CSE1301); Advising's retake/prerequisite/lab-theory analysis canonicalizes course codes before comparing so mixed formats across semesters don't silently fail to match.
  • Added Degree Progress tracking to Student Advising — per-category credit sums (earned + in-progress) against the catalogue's degree-requirement table, with Major Elective/Optional-Minor credits estimated by UNESCO-code pattern since those courses aren't individually enumerated.
  • Investigated and removed ESK (Essential Skills) from degree-requirement tracking — confirmed not part of the CSE degree requirement despite appearing in the catalogue's course listing. This also fixed a false positive where an "ESK not started" warning fired for nearly every student regardless of actual progress.
  • Improved Advising results page performance for large batches (100+ students) — each student's report body (several nested tables) is now built lazily on first expand instead of for every card up front.
  • Added a "Hide clean students" filter and an email modal (copy address, copy message, open a blank Gmail compose tab) for per-student and bulk advising emails, replacing the old shared-textarea output.
  • Changed default theme to light across all report/viewer pages (Time, Advising, Bulk Save, Catalogue Viewer).
  • Added 📖 Course Catalogue Viewer, 🧪 lab-without-theory detection, and 💾 Bulk Save (with URMS's own "Saved successfully" banner as the authoritative success signal, plus a distinct "Unconfirmed" state for genuinely ambiguous responses).
  • Corrected several prerequisite mappings (CSE3120, CSE3201/3202, CSE3203, CSE3200, CSE3205/3206, CSE3301, the Capstone chain) that had shifted onto the wrong course after re-extracting the catalogue PDF with pdftotext -table instead of -layout.
  • Added this documentation site and the privacy policy.

Earlier

  • Initial scaffold: Manifest V3 side panel shell, feature-module pattern, and the 🕐 Free Time Finder and 🎓 Student Advising features built on top of it.