2929import $ from 'jquery' ;
3030const browser = require ( 'webextension-polyfill' ) ;
3131
32- import { calculate_gpa , extractFinalPercent , gradeToGPA , analytics_message , saveGradesLocally } from './helpers' ;
32+ import {
33+ calculate_gpa ,
34+ extractFinalPercent ,
35+ gradeToGPA ,
36+ analytics_message ,
37+ saveGradesLocally ,
38+ } from './helpers' ;
3339
3440// Vue Components
3541import Vue from 'vue' ;
@@ -71,44 +77,156 @@ function main () {
7177}
7278
7379function main_page ( ) {
80+ const student_name = getStudentName ( ) ;
81+ const { sem1_col, sem2_col } = getSemesterCols ( ) ;
82+ const second_semester = isSecondSemester ( ) ;
83+ const current_term = getCurrentTerm ( ) ;
84+ const courses = getCourses ( second_semester , sem1_col , sem2_col ) ;
85+
86+ showCurrentGPA ( second_semester , courses ) ;
87+
88+ if ( second_semester ) {
89+ showFirstSemGPA ( ) ;
90+ }
91+
92+ $ ( "table[border='0'][cellpadding='3'][cellspacing='1'][width='100%']" ) . prepend ( `<td id="cumulative-gpa"></td>` ) ;
93+ // passing courses in to possibly include current semester GPA if term has not finished yet.
94+ new ( Vue . extend ( CumulativeGPA ) ) ( {
95+ propsData : {
96+ courses : courses ,
97+ currentTerm : current_term ,
98+ secondSemester : second_semester ,
99+ } ,
100+ } ) . $mount ( "#cumulative-gpa" ) ;
101+
102+ saveGradesLocally ( student_name , courses ) ;
103+ addHypoGradeCalc ( courses ) ;
104+ }
105+
106+ function class_page ( ) {
107+ // Show final percent
108+ const number = extractFinalPercent ( $ ( "table.linkDescList" ) . html ( ) ) ;
109+ if ( ! number ) {
110+ return ;
111+ }
112+ document . querySelector ( "table.linkDescList" ) . append ( html2node ( `<tr><td><strong>Final Percent: </strong></td><td>` + number . toFixed ( 2 ) + ` <div class="tooltip saspes">ⓘ<span class="tooltiptext saspes">85: A+ | 75: A <br />65: B+ | 55: B <br />45: C+ | 35: C <br/>25: D+ | 15: D</span></div></td></tr>` ) ) ;
113+
114+ addHypoAssignment ( number ) ;
115+ }
116+
117+ function login_page ( ) {
118+ $ ( '<div id="saspes-info"></div>' ) . insertAfter ( 'div#content' ) ;
119+ browser . storage . local . get ( { showExtensionInfo : true } ) . then ( result => {
120+ new ( Vue . extend ( ExtensionInfo ) ) ( {
121+ data : {
122+ showInfo : result . showExtensionInfo ,
123+ } ,
124+ } ) . $mount ( '#saspes-info' ) ;
125+ } ) ;
126+ }
127+
128+ function html2node ( html_string ) {
129+ return html2nodelist ( html_string ) [ 0 ] ;
130+ }
131+ function html2nodelist ( html_string ) {
132+ const temp = document . createElement ( 'template' ) ;
133+ temp . innerHTML = html_string ;
134+ return temp . content . childNodes ;
135+ }
136+
137+ /**
138+ * Returns the student name found in the main page's html
139+ * @returns {string } The student's name
140+ */
141+ function getStudentName ( ) {
74142 const student_name = document . querySelector ( '#userName' ) . querySelector ( 'span' ) . innerText ;
75- let second_semester = false ;
76- const courses = [ ] ;
77- const courses_first_semester = [ ] ;
143+ }
144+
145+ /**
146+ * Return the semester 1 and semester 2 column indexes from the main page HTML.
147+ * @returns { number, number } { sem1_col, sem2_col } The first and second semester column indexes.
148+ */
149+ function getSemesterCols ( ) {
150+ let sem1_col = 0 ;
151+ let sem2_col = 0 ;
78152 const $grade_rows = $ ( '#quickLookup table.grid' ) . find ( 'tr' ) ;
79- let s1col = 0 ;
80- let s2col = 0 ;
81- let current_term = "" ;
82- let attendance_href = "" ;
83153 if ( $grade_rows . eq ( 1 ) . html ( ) . match ( "S2" ) != null ) {
84- second_semester = true ;
85154 let curr = 0 ;
86155 $grade_rows . eq ( 1 ) . find ( 'th' ) . get ( ) . forEach ( e => {
87156 switch ( e . innerText ) {
88157 case "S1" :
89- s1col = curr ;
158+ sem1_col = curr ;
90159 break ;
91160 case "S2" :
92- s2col = curr ;
161+ sem2_col = curr ;
93162 break ;
94163 default :
95164 break ;
96165 }
97166 curr += parseInt ( e . getAttribute ( 'colspan' ) ) || 1 ;
98167 } ) ;
99- second_semester = false ;
168+ }
169+ return { sem1_col, sem2_col } ;
170+ }
171+
172+ /**
173+ * Check whether it is currently second semester or not.
174+ * @param {number } sem2_col The column index corresponding to the second semester
175+ * @returns {bool } Whether it is currently second semester
176+ */
177+ function isSecondSemester ( sem2_col ) {
178+ const $grade_rows = $ ( '#quickLookup table.grid' ) . find ( 'tr' ) ;
179+ if ( $grade_rows . eq ( 1 ) . html ( ) . match ( "S2" ) != null ) {
100180 for ( let t = 0 ; t < $grade_rows . length ; t ++ ) {
101- if ( gradeToGPA ( $grade_rows . eq ( t ) . find ( 'td' ) . get ( s2col ) ) !== - 1 ) {
102- second_semester = true ;
181+ if ( gradeToGPA ( $grade_rows . eq ( t ) . find ( 'td' ) . get ( sem2_col ) ) !== - 1 ) {
182+ return true ;
103183 }
104184 }
105185 }
186+ return false ;
187+ }
188+
189+ /**
190+ * Show the current semester's GPA.
191+ * @param second_semester If the current semester is the second semester
192+ * @param courses an array of Courses that the student is taking
193+ */
194+ function showCurrentGPA ( second_semester , courses ) {
195+ $ ( "table[border='0'][cellpadding='3'][cellspacing='1'][width='100%']" ) . prepend ( `<tr><td align="center">Current Semester GPA (${ second_semester ? 'S2' : 'S1' } ): ${ calculate_gpa ( courses ) } </td></tr>` ) ;
196+ }
197+
198+ /**
199+ * Returns the current semester by parsing HTML.
200+ * @return {string } representing the current semester
201+ */
202+ function getCurrentTerm ( ) {
203+ const $grade_rows = $ ( '#quickLookup table.grid' ) . find ( 'tr' ) ;
204+ let attendance_href = "" ;
205+ let current_term = "" ;
206+ if ( ( attendance_href = $grade_rows . eq ( $grade_rows . length - 1 ) ?. find ( 'a[href*="attendancedates"]' ) ?. [ 0 ] ?. href ) ) { // Check that attendance_href exists and if it does, run the next line.
207+ current_term = new URL ( attendance_href ) . searchParams . get ( "term" ) ;
208+ }
209+
210+ return current_term ;
211+ }
212+
213+ /**
214+ * Returns an array of the current courses of the user and creates Vue objects for the courses.
215+ * @param second_semester If the current semester is the second semester
216+ * @param sem1_col The column of the first semester
217+ * @param sem2_col The column of the second semester
218+ * @returns {Course[] } array of Course objects representing the Courses of the user
219+ */
220+ function getCourses ( second_semester , sem1_col , sem2_col ) {
221+ const $grade_rows = $ ( '#quickLookup table.grid' ) . find ( 'tr' ) ;
222+ const courses = [ ] ;
223+
106224 for ( let i = 0 ; i < $grade_rows . length ; i ++ ) {
107225 let $course ;
108226 if ( second_semester ) {
109227 const $cells = $grade_rows . eq ( i ) . find ( 'td' ) ;
110- $course = $cells . eq ( s2col ) . find ( 'a[href^="scores.html"]' ) ;
111- const $first_grade = $cells . eq ( s1col ) . find ( 'a[href^="scores.html"]' ) ;
228+ $course = $cells . eq ( sem2_col ) . find ( 'a[href^="scores.html"]' ) ;
229+ const $first_grade = $cells . eq ( sem1_col ) . find ( 'a[href^="scores.html"]' ) ;
112230 if ( $first_grade . length === 1 ) {
113231 if ( gradeToGPA ( $first_grade . text ( ) ) !== - 1 ) {
114232 new ( Vue . extend ( ClassGrade ) ) ( {
@@ -134,51 +252,53 @@ function main_page () {
134252 }
135253 }
136254 }
137- if ( ( attendance_href = $grade_rows . eq ( $grade_rows . length - 1 ) ?. find ( 'a[href*="attendancedates"]' ) ?. [ 0 ] ?. href ) ) { // Check that attendance_href exists and if it does, run the next line.
138- current_term = new URL ( attendance_href ) . searchParams . get ( "term" ) ;
139- }
140- $ ( "table[border='0'][cellpadding='3'][cellspacing='1'][width='100%']" ) . prepend ( `<tr><td align="center">Current Semester GPA (${ second_semester ? 'S2' : 'S1' } ): ${ calculate_gpa ( courses ) } </td></tr>` ) ;
141255
142- if ( second_semester ) {
143- fetch ( "https://powerschool.sas.edu.sg/guardian/termgrades.html" )
144- . then ( ( response ) => {
145- return response . text ( ) ;
146- } )
147- . then ( ( data ) => {
148- const el = document . createElement ( "html" ) ;
149- let element_list = [ ] ;
150- el . innerHTML = data ;
151- element_list = el . getElementsByClassName ( "box-round" ) [ 0 ] . getElementsByTagName ( "table" ) [ 0 ] ;
152- element_list = element_list . getElementsByTagName ( "tbody" ) [ 0 ] . getElementsByTagName ( "tr" ) ;
153- if ( element_list . length > 2 ) {
154- for ( let i = 2 ; i < element_list . length ; i ++ ) {
155- const $prev_course = element_list [ i ] ;
156- if ( $prev_course ?. innerText ?. trim ( ) === "S2" ) {
157- break ;
158- }
159- if ( $prev_course ?. getElementsByTagName ( "td" ) . length > 1 ) {
160- courses_first_semester . push ( new Course ( $prev_course . getElementsByTagName ( "td" ) [ 0 ] . textContent . trim ( ) ,
161- $prev_course . getElementsByTagName ( "td" ) [ 2 ] . getElementsByTagName ( "a" ) [ 0 ] . href ,
162- $prev_course . getElementsByTagName ( "td" ) [ 1 ] . textContent . trim ( ) ,
163- ) ) ;
164- }
256+ return courses ;
257+ }
258+
259+ /**
260+ * Show the first semester GPA.
261+ */
262+ function showFirstSemGPA ( ) {
263+ const courses_first_semester = [ ] ;
264+ getFirstSemCourses ( )
265+ . then ( ( data ) => {
266+ const el = document . createElement ( "html" ) ;
267+ let element_list = [ ] ;
268+ el . innerHTML = data ;
269+ element_list = el . getElementsByClassName ( "box-round" ) [ 0 ] . getElementsByTagName ( "table" ) [ 0 ] ;
270+ element_list = element_list . getElementsByTagName ( "tbody" ) [ 0 ] . getElementsByTagName ( "tr" ) ;
271+ if ( element_list . length > 2 ) {
272+ for ( let i = 2 ; i < element_list . length ; i ++ ) {
273+ const $prev_course = element_list [ i ] ;
274+ if ( $prev_course ?. innerText ?. trim ( ) === "S2" ) {
275+ break ;
276+ }
277+ if ( $prev_course ?. getElementsByTagName ( "td" ) . length > 1 ) {
278+ courses_first_semester . push ( new Course ( $prev_course . getElementsByTagName ( "td" ) [ 0 ] . textContent . trim ( ) ,
279+ $prev_course . getElementsByTagName ( "td" ) [ 2 ] . getElementsByTagName ( "a" ) [ 0 ] . href ,
280+ $prev_course . getElementsByTagName ( "td" ) [ 1 ] . textContent . trim ( ) ,
281+ ) ) ;
165282 }
166- $ ( "table[border='0'][cellpadding='3'][cellspacing='1'][width='100%']" ) . prepend ( `<tr><td align="center">Last Semester GPA (S1): ${ calculate_gpa ( courses_first_semester ) } </td></tr>` ) ;
167283 }
168- } ) ;
169- }
170- $ ( "table[border='0'][cellpadding='3'][cellspacing='1'][width='100%']" ) . prepend ( `<td id="cumulative-gpa"></td>` ) ;
171- // passing courses in to possibly include current semester GPA if term has not finished yet.
172- new ( Vue . extend ( CumulativeGPA ) ) ( {
173- propsData : {
174- courses : courses ,
175- currentTerm : current_term ,
176- secondSemester : second_semester ,
177- } ,
178- } ) . $mount ( "#cumulative-gpa" ) ;
284+ $ ( "table[border='0'][cellpadding='3'][cellspacing='1'][width='100%']" ) . prepend ( `<tr><td align="center">Last Semester GPA (S1): ${ calculate_gpa ( courses_first_semester ) } </td></tr>` ) ;
285+ }
286+ } ) ;
287+ }
179288
180- saveGradesLocally ( student_name , courses ) ;
181- // Hypo Grade Calculator
289+ /**
290+ * Get the first semester courses and grades HTML.
291+ * @returns {Promise } the html from the first semester course and grades page
292+ */
293+ async function getFirstSemCourses ( ) {
294+ return await ( await fetch ( "https://powerschool.sas.edu.sg/guardian/termgrades.html" ) ) . text ( ) ;
295+ }
296+
297+ /**
298+ * Adds the hypothetical grade calculator.
299+ * @param courses The courses of the student
300+ */
301+ function addHypoGradeCalc ( courses ) {
182302 const HypoGradesDiv = document . createElement ( 'div' ) ;
183303 HypoGradesDiv . classList . add ( "hypo-grade-div-fixed" ) ;
184304 HypoGradesDiv . id = "saspes-hypo-grades" ;
@@ -190,37 +310,15 @@ function main_page () {
190310 } ) . $mount ( ".hypo-grade-div-fixed" ) ;
191311}
192312
193- function class_page ( ) {
194- // Show final percent
195- const number = extractFinalPercent ( $ ( "table.linkDescList" ) . html ( ) ) ;
196- if ( ! number ) {
197- return ;
198- }
199- document . querySelector ( "table.linkDescList" ) . append ( html2node ( `<tr><td><strong>Final Percent: </strong></td><td>` + number . toFixed ( 2 ) + ` <div class="tooltip saspes">ⓘ<span class="tooltiptext saspes">85: A+ | 75: A <br />65: B+ | 55: B <br />45: C+ | 35: C <br/>25: D+ | 15: D</span></div></td></tr>` ) ) ;
200-
313+ /**
314+ * Add a hypothetical assignment calculator widget.
315+ * @param number The current final percent of the student.
316+ */
317+ function addHypoAssignment ( number ) {
201318 document . querySelector ( 'div.box-round' ) . insertAdjacentHTML ( 'afterend' , `<div id="saspes-hypo-assignment"></div>` ) ;
202319 new ( Vue . extend ( HypoAssignment ) ) ( {
203320 propsData : {
204321 currentFP : number ,
205322 } ,
206323 } ) . $mount ( '#saspes-hypo-assignment' ) ;
207324}
208- function login_page ( ) {
209- $ ( '<div id="saspes-info"></div>' ) . insertAfter ( 'div#content' ) ;
210- browser . storage . local . get ( { showExtensionInfo : true } ) . then ( result => {
211- new ( Vue . extend ( ExtensionInfo ) ) ( {
212- data : {
213- showInfo : result . showExtensionInfo ,
214- } ,
215- } ) . $mount ( '#saspes-info' ) ;
216- } ) ;
217- }
218-
219- function html2node ( html_string ) {
220- return html2nodelist ( html_string ) [ 0 ] ;
221- }
222- function html2nodelist ( html_string ) {
223- const temp = document . createElement ( 'template' ) ;
224- temp . innerHTML = html_string ;
225- return temp . content . childNodes ;
226- }
0 commit comments