Skip to content

Commit cde033b

Browse files
author
Suhas Hariharan
committed
fixed other changes and replaced with API calls
Signed-off-by: Suhas Hariharan <[email protected]>
1 parent 405a0f8 commit cde033b

File tree

3 files changed

+85
-31
lines changed

3 files changed

+85
-31
lines changed

src/js/components/CumulativeGPA.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,7 @@ export default {
228228
if (include_current_semester) {
229229
all_courses.push(current_courses);
230230
}
231+
console.log(all_courses);
231232
let total_count = 0;
232233
let total_gpa = 0;
233234
for (let i = 0; i < all_courses.length; i++) {

src/js/helpers.js

Lines changed: 67 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ const grade_gpa = {
4848
* @param {string} grade The grade to convert.
4949
* @returns {number} The corresponding grade point average.
5050
*/
51-
function gradeToGPA (grade) {
51+
function gradeToGPA(grade) {
5252
if (grade in grade_gpa) {
5353
return grade_gpa[grade];
5454
}
@@ -72,7 +72,7 @@ const grade_fp = {
7272
* @param {string} grade The grade to convert.
7373
* @returns {number} The corresponding final percent.
7474
*/
75-
function gradeToFP (grade) {
75+
function gradeToFP(grade) {
7676
if (grade in grade_fp) {
7777
return grade_fp[grade];
7878
}
@@ -93,7 +93,7 @@ const fprange = {
9393
'0-15': 'F',
9494
};
9595

96-
function fpToGrade (finalPercent) {
96+
function fpToGrade(finalPercent) {
9797
return getKeyRange(fprange, parseFloat(parseFloat(finalPercent).toFixed(2)));
9898
}
9999

@@ -102,7 +102,7 @@ function fpToGrade (finalPercent) {
102102
* @param {Course[]} courses The courses for which the overall grade point average should be calculated.
103103
* @returns {string} The grade point average to the hundredth place.
104104
*/
105-
function calculate_gpa (courses) {
105+
function calculate_gpa(courses) {
106106
let courses_with_grades = 0;
107107
let sum = 0;
108108
for (var i = 0; i < courses.length; i++) {
@@ -117,7 +117,7 @@ function calculate_gpa (courses) {
117117
}
118118
return (sum / courses_with_grades).toFixed(2);
119119

120-
function course_boost (course_name, grade) {
120+
function course_boost(course_name, grade) {
121121
if (gradeToGPA(grade) < 1.8) {
122122
return 0;
123123
}
@@ -128,7 +128,7 @@ function calculate_gpa (courses) {
128128
}
129129
}
130130

131-
function calculate_credit_hours (course_name) {
131+
function calculate_credit_hours(course_name) {
132132
const double_effect_courses = [`English 10/American History`, `English 9/World History`];
133133
if (double_effect_courses.includes(course_name)) {
134134
return 2;
@@ -144,7 +144,7 @@ function calculate_credit_hours (course_name) {
144144
* @param {String} html course page html
145145
* @returns {Number|undefined} The final percent
146146
*/
147-
function extractFinalPercent (html) {
147+
function extractFinalPercent(html) {
148148
let number;
149149
try {
150150
let current_string = html.match(/(?=document\.write).*/g)[1];
@@ -166,7 +166,7 @@ function extractFinalPercent (html) {
166166
* @param {String} semester string representing semester that the request is for
167167
* @returns {Number|undefined} The final percent
168168
*/
169-
async function getFinalPercent (frn, semester) {
169+
async function getFinalPercent(frn, semester) {
170170
let number;
171171
try {
172172
await fetch(`https://powerschool.sas.edu.sg/guardian/scores_ms_guardian.html?frn=${frn}&fg=${semester}`, { credentials: "same-origin" }).then(response => response.text()).then(response => {
@@ -188,11 +188,11 @@ async function getFinalPercent (frn, semester) {
188188
* @param {Node} table node representing table
189189
* @returns {String[]} List of all categories
190190
*/
191-
function extractGradeCategories (table) {
191+
function extractGradeCategories(table) {
192192
const table_rows = table.getElementsByTagName("tr");
193193
const category_set = new Set();
194194
for (let i = 1; i < table_rows.length - 1; i++) {
195-
category_set.add(table_rows[i].getElementsByTagName("td")[1].getElementsByTagName("a")[0].innerText);
195+
category_set.add(table_rows[i].getElementsByTagName("td")[1].getElementsByTagName("span")[1].innerText);
196196
}
197197
return Array.from(category_set);
198198
}
@@ -201,32 +201,32 @@ function extractGradeCategories (table) {
201201
* Extract all assignments from a class.
202202
* @returns {ClassAssignment[]} List of all assignments
203203
*/
204-
function extractAssignmentList () {
205-
const table = document.querySelector("#content-main > div.box-round > table:nth-child(4) > tbody");
204+
function extractAssignmentList() {
205+
const table = document.querySelector("table.zebra.grid > tbody");
206206
const assignments = [];
207207
[...table.querySelectorAll('tr')].slice(1, -1).forEach((e, i) => {
208208
const curr = e.querySelectorAll('td');
209-
assignments.push(new ClassAssignment(i, curr[0].innerHTML, curr[1].innerText, curr[2].innerHTML, isIndicatorPresent(curr[3]), isIndicatorPresent(curr[4]), isIndicatorPresent(curr[5]), isIndicatorPresent(curr[6]), isIndicatorPresent(curr[7]), curr[9].innerHTML, curr[11].innerHTML));
209+
assignments.push(new ClassAssignment(i, curr[0].innerHTML, curr[1].innerText, curr[2].innerHTML, isIndicatorPresent(curr[4]), isIndicatorPresent(curr[5]), isIndicatorPresent(curr[6]), isIndicatorPresent(curr[7]), isIndicatorPresent(curr[8]), curr[11].innerHTML, curr[12].innerHTML.trim()));
210210
});
211211
return assignments;
212212
}
213213
/**
214-
* Return whether the given row contains an indicator of any kind(i.e missing, late)
214+
* Return whether the given row contains an indicator of any kind(i.e missing, late)
215215
* @param {Element} node Node representing individual row of each assignment
216216
* @returns {boolean} boolean representing whether input has child nodes and are set to visible.
217217
*/
218-
function isIndicatorPresent (node) {
219-
return node.hasChildNodes() && node.childNodes[0].style.display !== 'none';
218+
function isIndicatorPresent(node) {
219+
return node.hasChildNodes() && node.querySelector("div.ps-icon");
220220
}
221221
/**
222222
* Return Assignment instances for the given class page.
223223
* @param {Element} node Root node element of the class page.
224224
* @returns {Assignment[]} Assignments in this course
225225
*/
226-
function assignments (node) {
226+
function assignmentsFromNode(node) {
227227
const tr = [];
228228
// Find assignments table, get it's rows, take out the header and legend rows.
229-
[...node.querySelector('table[align=center').querySelectorAll('tr')].slice(1, -1).forEach((e, i) => {
229+
[...node.querySelector('table.zebra.grid').querySelectorAll('tr')].slice(1, -1).forEach((e, i) => {
230230
const curr = e.querySelectorAll('td');
231231
const assignment = new Assignment(curr[2]?.innerText || "", curr[curr.length - 1]?.innerText || "", i);
232232
const missingIcon = e.querySelector('img[src="/images/icon_missing.gif"]');
@@ -238,19 +238,58 @@ function assignments (node) {
238238
return tr;
239239
}
240240

241+
/**
242+
* Return Assignment instances for the given class page.
243+
* @param {String} student_id student id for the current user
244+
* @param {String} sectino_id section id for the course being requested
245+
* @param {String} start_date start date in YYYY-MM-DD format
246+
* @param {String} end_date end date in YYYY-MM-DD format
247+
* @returns {Assignment[]} Assignments in this course
248+
*/
249+
function assignmentsFromAPI(studentId, sectionId, startDate, endDate) {
250+
const assignmentList = [];
251+
try {
252+
fetch('https://powerschool.sas.edu.sg/ws/xte/assignment/lookup', {
253+
method: "POST", headers: {
254+
'Content-Type': 'application/json'
255+
},
256+
body: JSON.stringify({
257+
"student_ids": [studentId],
258+
"section_ids": [sectionId],
259+
"start_date": startDate,
260+
"end_date": endDate
261+
}), credentials: "same-origin"
262+
}).then(response => response.json()).then(response => {
263+
for (let i = 0; i < response.length; i++) {
264+
if (response[i]._assignmentsections?.length) {
265+
const assignmentData = response[i]._assignmentsections[0];
266+
const assignment = new Assignment(assignmentData.name, assignmentData._assignmentscores[0]?.actualscoreentered || "", i);
267+
if (assignmentData._assignmentscores[0]?.ismissing || null) {
268+
assignment.addStatus(Assignment.statuses.MISSING);
269+
}
270+
assignmentList.push(assignment);
271+
}
272+
}
273+
});
274+
} catch (e) {
275+
return [];
276+
}
277+
return assignmentList;
278+
}
279+
241280
/**
242281
* Return course title of active class page
243282
* @returns {String} Course title
244283
*/
245-
function extractCourseTitle () {
246-
return document.getElementsByTagName('h2')[0].innerHTML;
284+
function extractCourseTitle() {
285+
return document.querySelector("tbody:nth-child(1) > tr:nth-child(2) > td:nth-child(1)").innerText
247286
}
248287

249288
/**
250289
* Retrieve category weighting for class from local storage
251290
* @returns {Map<String, Object>} Map of weighting assigned to each category for course
252291
*/
253-
async function getSavedCategoryWeighting () {
292+
async function getSavedCategoryWeighting() {
254293
const courseName = extractCourseTitle() + "-catmap";
255294
const catmap = await browser.storage.local.get(courseName);
256295
if (catmap === undefined || (Object.keys(catmap).length === 0 && catmap.constructor === Object) || catmap[courseName] === undefined) return false;
@@ -261,7 +300,7 @@ async function getSavedCategoryWeighting () {
261300
* Save category weighting for class to local storage
262301
* @param {Map<String, Object>} catmap Map of weighting assigned to each category for course
263302
*/
264-
async function saveCategoryWeighting (catmap) {
303+
async function saveCategoryWeighting(catmap) {
265304
const courseName = extractCourseTitle();
266305
const data = {};
267306
data[courseName + "-catmap"] = catmap;
@@ -274,7 +313,7 @@ async function saveCategoryWeighting (catmap) {
274313
* @param {String} username users full name
275314
* @returns {Promise<Course[]>} list of courses objects for that user
276315
*/
277-
async function getSavedGrades (username) {
316+
async function getSavedGrades(username) {
278317
const courses = [];
279318
const user_data = (await browser.storage.local.get("user_data")).user_data;
280319
if (user_data !== undefined) {
@@ -303,7 +342,7 @@ async function getSavedGrades (username) {
303342
* @param {String} username users full name
304343
* @param {Course[]} courses list of course objects to save
305344
*/
306-
async function saveGradesLocally (username, courses) {
345+
async function saveGradesLocally(username, courses) {
307346
const data = await getLocalConfig() || {};
308347

309348
if (data.opted_in === undefined) {
@@ -338,7 +377,7 @@ async function saveGradesLocally (username, courses) {
338377
* @async
339378
* @returns {Config} an object representing the user's config from the browser's local storage
340379
*/
341-
async function getLocalConfig () {
380+
async function getLocalConfig() {
342381
const data = await browser.storage.local.get(null);
343382
return data;
344383
}
@@ -347,7 +386,7 @@ async function getLocalConfig () {
347386
* Retrieves the default extension config for new users.
348387
* @returns {Config} an object representing the default config.
349388
*/
350-
function getDefaultConfig () {
389+
function getDefaultConfig() {
351390
const data = { opted_in: { changed: false, value: false }, percent_main_page: { changed: false, value: true } };
352391
return data;
353392
}
@@ -366,7 +405,8 @@ export {
366405
getFinalPercent,
367406
extractGradeCategories,
368407
extractAssignmentList,
369-
assignments,
408+
assignmentsFromNode,
409+
assignmentsFromAPI,
370410
calculate_credit_hours,
371411
getSavedGrades,
372412
saveGradesLocally,

src/js/saspowerschoolff.js

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ import $ from 'jquery';
3232
const browser = require('webextension-polyfill');
3333

3434
import {
35-
assignments,
35+
assignmentsFromNode,
36+
assignmentsFromAPI,
3637
calculate_gpa,
3738
getFinalPercent,
3839
extractGradeCategories,
@@ -59,6 +60,7 @@ import Course from './models/Course';
5960
import CumulativeGPA from "./components/CumulativeGPA";
6061

6162
var gt;
63+
var gt_mounted;
6264

6365
main();
6466
function main () {
@@ -111,6 +113,7 @@ async function main_page () {
111113

112114
async function class_page () {
113115
// Show final percent
116+
await new Promise(r => setTimeout(r, 750)); // adds delay prior to running to ensure that class page JS is finished running.
114117
const currentUrl = new URL(document.location.href);
115118
const number = await getFinalPercent(currentUrl.searchParams.get("frn"), currentUrl.searchParams.get("fg")) || "";
116119
if (!number) {
@@ -135,6 +138,10 @@ async function class_page () {
135138
document.getElementById('saspes-categories').style.display = "none";
136139
gt.setCategoryWeighting(false);
137140
} else {
141+
if (!gt_mounted) {
142+
gt_mounted = true;
143+
gt.$mount('table.zebra.grid');
144+
}
138145
document.getElementById('saspes-hypo-assignment').style.display = "none";
139146
document.getElementById('saspes-categories').style.display = "block";
140147
gt.setCategoryWeighting(true);
@@ -340,7 +347,13 @@ async function getCourses (second_semester, sem1_col, sem2_col) {
340347
fetch(currentUrlString, { credentials: "same-origin" }).then(response => response.text()).then(response => {
341348
const page = document.implementation.createHTMLDocument();
342349
page.documentElement.innerHTML = response;
343-
const assignment_list = assignments(page.querySelector('body'));
350+
const sectionId = page.querySelector("div[data-pss-student-assignment-scores]").getAttribute("data-sectionid");
351+
let startDate = currentUrl.searchParams.get("begdate");
352+
startDate = startDate.split("/")[2] + "-" + startDate.split("/")[0] + "-" + startDate.split("/")[1];
353+
let endDate = currentUrl.searchParams.get("enddate");
354+
endDate = endDate.split("/")[2] + "-" + endDate.split("/")[0] + "-" + endDate.split("/")[1];
355+
const studentId = page.querySelector("div .xteContentWrapper").getAttribute("data-ng-init").split("\n")[0].split("= '")[1].replace("';","").substring(3);
356+
const assignment_list = assignmentsFromAPI(studentId, sectionId, startDate, endDate);
344357
courses.push(new Course(temp.trim(), currentUrlString, $course.text(), finalPercent, assignment_list));
345358
if (gradeToGPA($course.text()) !== -1) {
346359
new (Vue.extend(ClassGrade))({
@@ -425,13 +438,13 @@ function addHypoGradeCalc (courses) {
425438
*/
426439
async function addVueGrades () {
427440
const assignments = extractAssignmentList();
428-
const cat = extractGradeCategories(document.querySelector("#content-main > div.box-round > table:nth-child(4) > tbody"));
441+
const cat = extractGradeCategories(document.querySelector("table.zebra.grid > tbody"));
429442
gt = new (Vue.extend(GradeTable))({ // remake grade table to easily read grades
430443
propsData: {
431444
categories: cat,
432445
assignments: assignments,
433446
},
434-
}).$mount('#content-main > div.box-round > table:nth-child(4)');
447+
});
435448
document.querySelector('div.box-round').insertAdjacentHTML('afterend', `<div id="saspes-categories"></div>`);
436449
new (Vue.extend(CategoryWeighting))({ // category weighting widget
437450
propsData: {

0 commit comments

Comments
 (0)