Skip to content

Commit 6d65c64

Browse files
author
Suhas Hariharan
authored
Merge pull request #232 from sas-fossdev/last-seen-grades-ui
added last seen grades feature and opt-out feature, updated various links in extension options
2 parents c1bf0f7 + bd570f4 commit 6d65c64

File tree

6 files changed

+336
-60
lines changed

6 files changed

+336
-60
lines changed

src/js/components/ClassGrade.vue

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<!--
22
- @copyright Copyright (c) 2020 Gary Kim <[email protected]>
3-
-
3+
- @copyright Copyright (c) 2020 Suhas Hariharan <[email protected]>
44
- @author Gary Kim <[email protected]>
55
-
66
- @license GNU AGPL version 3 only
@@ -68,7 +68,6 @@
6868
</template>
6969

7070
<script>
71-
import { extractFinalPercent, assignments } from "../helpers";
7271
import Course from "../models/Course";
7372
7473
import { VPopover } from 'v-tooltip';
@@ -107,17 +106,6 @@ export default {
107106
return [];
108107
},
109108
},
110-
async mounted () {
111-
if (!(await browser.storage.local.get({ percent_main_page: true })).percent_main_page) {
112-
return;
113-
}
114-
const page = document.implementation.createHTMLDocument();
115-
page.documentElement.innerHTML = await (await fetch(this.course.link, { credentials: "same-origin" })).text();
116-
this.finalPercent = extractFinalPercent(page.querySelector('table.linkDescList').innerHTML) || "";
117-
if (this.showMissing) {
118-
this.assignments = assignments(page.querySelector('body'));
119-
}
120-
},
121109
};
122110
</script>
123111

src/js/components/ExtensionInfo.vue

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<!--
22
- @copyright Copyright (c) 2018-2020 Gary Kim <[email protected]>
3-
-
3+
- @copyright Copyright (c) 2020 Suhas Hariharan <[email protected]>
44
- @author Gary Kim <[email protected]>
55
-
66
- @license GNU AGPL version 3 only
@@ -44,25 +44,25 @@
4444
<p>
4545
<a
4646
class="saspes-link"
47-
href="https://github.com/gary-kim/saspes/"
47+
href="https://github.com/sas-fossdev/saspes"
4848
target="_blank"
4949
@click="link_analytics"
5050
>Website/Source Code</a> |
5151
<a
52-
href="https://github.com/gary-kim/saspes/blob/master/CHANGELOG.md"
52+
href="https://github.com/sas-fossdev/saspes/blob/master/CHANGELOG.md"
5353
class="saspes-link"
5454
target="_blank"
5555
@click="link_analytics"
5656
>Changelog</a> |
5757
<a
5858
class="saspes-link"
59-
href="https://github.com/gary-kim/saspes/issues"
59+
href="https://github.com/sas-fossdev/saspes/issues"
6060
target="_blank"
6161
@click="link_analytics"
6262
>Issue Tracker</a> |
6363
<a
6464
class="saspes-link"
65-
href="https://github.com/gary-kim/saspes/blob/master/LICENSE"
65+
href="https://github.com/sas-fossdev/saspes/blob/master/LICENSE"
6666
target="_blank"
6767
@click="link_analytics"
6868
>License (AGPL-3.0-only)</a> |

src/js/components/LastGrades.vue

Lines changed: 241 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,241 @@
1+
<!--
2+
- @copyright Copyright (c) 2020 Suhas Hariharan <[email protected]>
3+
- @author Suhas Hariharan <[email protected]>
4+
-
5+
- @license GNU AGPL version 3 only
6+
-
7+
- SAS Powerschool Enhancement Suite - A browser extension to improve the experience of SAS Powerschool.
8+
-
9+
- This program is free software: you can redistribute it and/or modify
10+
- it under the terms of the GNU Affero General Public License as
11+
- published by the Free Software Foundation, version 3.
12+
-
13+
- This program is distributed in the hope that it will be useful,
14+
- but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16+
- GNU Affero General Public License for more details.
17+
-
18+
- You should have received a copy of the GNU Affero General Public License
19+
- along with this program. If not, see <https://www.gnu.org/licenses/>.
20+
-->
21+
22+
<template>
23+
<div
24+
id="saspes-last-grades"
25+
class="last-grade-div-fixed"
26+
>
27+
<div
28+
:style="{ left: opened ? 0 : width + 'px'}"
29+
class="last-grade-div"
30+
>
31+
<div
32+
class="last-grade-open"
33+
@click="toggleOpen"
34+
>
35+
Last Seen Grades
36+
<div
37+
id="last-arrow"
38+
class="arrow"
39+
:class="{ 'arrow-left': !opened, 'arrow-right': opened }"
40+
/>
41+
</div>
42+
<div
43+
ref="panel"
44+
class="last-grade-panel"
45+
>
46+
<table id="last-table">
47+
<br>
48+
<tr align="center">
49+
<td> <h3> Last Seen Grades for {{ username }} </h3> </td>
50+
</tr><tr>
51+
<td> Course Name </td>
52+
<td> Letter Grade </td>
53+
<td> Final Percent(Out of 90) </td>
54+
</tr><tr
55+
v-for="course in courses"
56+
:key="course.name"
57+
>
58+
<td>
59+
<a
60+
:href="course.link"
61+
target="_blank"
62+
>
63+
{{ course.name }}
64+
</a>
65+
</td>
66+
<td align="center">
67+
{{ course.grade }}
68+
</td>
69+
<td align="center">
70+
{{ course.finalPercent }}
71+
</td>
72+
</tr>
73+
</table>
74+
<br>
75+
<h3>With the above grades, semester GPA would be: {{ gpa }}.</h3>
76+
<br>
77+
<div style="margin-left:2.5%; margin-right:2.5%">
78+
<i style="font-size: 13px">This will allow you to see grades while PowerSchool is closed, for example during exam periods.<br> However if you'd prefer to disable this, you can access the extension options in the top right hand<br> and uncheck this option.</i>
79+
</div>
80+
<br>
81+
</div>
82+
</div>
83+
</div>
84+
</template>
85+
<script>
86+
import { avaliableGrades, calculate_gpa } from '../helpers';
87+
88+
export default {
89+
name: "LastSeenGrades",
90+
props: {
91+
username: {
92+
type: String,
93+
required: true,
94+
},
95+
initialCourses: {
96+
type: Array,
97+
required: true,
98+
},
99+
},
100+
data: () => ({
101+
// Due to an issue with Vue reactivity not working on Course instances, using a standard JS object instead
102+
courses: [
103+
{
104+
name: "",
105+
link: "",
106+
grade: "",
107+
finalPercent: "",
108+
},
109+
],
110+
gradeOptions: [...avaliableGrades, ""],
111+
opened: false,
112+
width: 7000,
113+
}),
114+
computed: {
115+
gpa () {
116+
return calculate_gpa(this.courses);
117+
},
118+
},
119+
beforeMount () {
120+
this.resetData();
121+
},
122+
mounted () {
123+
this.width = this.$refs.panel.offsetWidth + 1;
124+
},
125+
methods: {
126+
toggleOpen () {
127+
this.opened = !this.opened;
128+
if (!this.opened) {
129+
this.resetData();
130+
}
131+
},
132+
resetData () {
133+
const toSet = [];
134+
for (let i = 0; i < this.initialCourses.length; i++) {
135+
const course = this.initialCourses[i];
136+
if (course.grade !== "[ i ]") {
137+
toSet.push({
138+
name: course.name,
139+
link: course.link,
140+
grade: course.grade,
141+
finalPercent: course.finalPercent,
142+
});
143+
}
144+
}
145+
this.courses = toSet;
146+
},
147+
},
148+
};
149+
</script>
150+
<style lang="less" scoped>
151+
.arrow {
152+
margin-left:10%;
153+
border: solid black;
154+
border-width: 0 5px 5px 0;
155+
display: inline-block;
156+
padding: 3px;
157+
transition-property: transform;
158+
transition-duration: 1s;
159+
}
160+
.arrow-left {
161+
transform: rotate(135deg);
162+
}
163+
.arrow-right {
164+
transform: rotate(315deg);
165+
}
166+
.last-grade-open {
167+
background-color: white;
168+
box-shadow: -4px 4px 5px 0 rgba(0,0,0,0.2);
169+
color: black;
170+
padding: 5px 10px 5px 10px;
171+
text-align: center;
172+
text-decoration: none;
173+
transition: padding 0.5s;
174+
width: 120px;
175+
height: 30px;
176+
display: flex;
177+
align-items: center;
178+
border-radius: 20px 0px 0px 20px;
179+
position: relative;
180+
overflow: hidden;
181+
left: 0;
182+
top: 30px;
183+
z-index: 2;
184+
185+
&:hover {
186+
cursor: pointer;
187+
188+
&:not(.currently-open) {
189+
padding: 5px 25px 5px 10px;
190+
}
191+
192+
& + .last-grade-panel {
193+
box-shadow: 3px 8px 20px 0 rgba(0,0,0,0.2);
194+
}
195+
}
196+
197+
}
198+
.last-grade-panel {
199+
background-color: white;
200+
box-shadow: 1px 4px 10px 0 rgba(0,0,0,0.2);
201+
z-index: -1;
202+
display: inline-block;
203+
border-radius: 15px 0px 0px 15px;
204+
transition: box-shadow 0.3s;
205+
position: relative;
206+
left: 0;
207+
overflow: hidden;
208+
209+
&:hover {
210+
box-shadow: 3px 8px 20px 0 rgba(0,0,0,0.2);
211+
}
212+
}
213+
.last-grade-div {
214+
background: transparent;
215+
position: relative;
216+
padding: 0;
217+
display: flex;
218+
flex-direction: row;
219+
align-items: start;
220+
justify-content: start;
221+
z-index: 999;
222+
transition: left 1s;
223+
left: 100vw;
224+
225+
select {
226+
border-radius: 5px 5px 5px 5px;
227+
min-width: 5.5em;
228+
}
229+
}
230+
.last-grade-div-fixed {
231+
position: fixed;
232+
right: 0;
233+
top: 20px;
234+
background: transparent;
235+
pointer-events: none;
236+
237+
& * {
238+
pointer-events: initial;
239+
}
240+
}
241+
</style>

src/js/helpers.js

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/**
22
*
33
* @copyright Copyright (c) 2018-2020 Gary Kim <[email protected]>
4-
*
4+
* @copyright Copyright (c) 2020 Suhas Hariharan <[email protected]>
55
* @author Gary Kim <[email protected]>
66
*
77
* @license GNU AGPL version 3 only
@@ -169,7 +169,7 @@ function assignments (node) {
169169
// Find assignments table, get it's rows, take out the header and legend rows.
170170
[...node.querySelector('table[align=center').querySelectorAll('tr')].slice(1, -1).forEach((e, i) => {
171171
const curr = e.querySelectorAll('td');
172-
const assignment = new Assignment(curr[2].innerText, curr[curr.length - 1].innerText, i);
172+
const assignment = new Assignment(curr[2]?.innerText || "", curr[curr.length - 1]?.innerText || "", i);
173173
if (e.querySelector('img[src="/images/icon_missing.gif"]')) {
174174
assignment.addStatus(Assignment.statuses.MISSING);
175175
}
@@ -186,12 +186,17 @@ function assignments (node) {
186186
*/
187187
async function getSavedGrades (username) {
188188
const courses = [];
189-
const course_list = (await browser.storage.local.get("USERDATA_" + username))["USERDATA_" + username] || [];
190-
course_list.forEach(course => {
191-
courses.push(new Course(course.name, course.link, course.grade, course.finalPercent, course.assignments));
192-
});
193-
return courses;
189+
const output = await browser.storage.local.get("USERDATA_" + username);
190+
if (output !== undefined && output["USERDATA_" + username] !== undefined) {
191+
const course_list = output["USERDATA_" + username].courses || [];
192+
for (let i = 0; i < course_list.length; i++) {
193+
const course = course_list[i];
194+
courses.push(new Course(course.name, course.link, course.grade, course.finalPercent, course.assignments));
195+
}
196+
return courses;
197+
}
194198
}
199+
195200
/**
196201
* Saves grades for user to browser local storage
197202
* @async
@@ -205,14 +210,8 @@ async function saveGradesLocally (username, courses) {
205210
course_list.push(courses[i].toObject());
206211
}
207212
user_data["USERDATA_" + username] = { "courses": course_list };
213+
user_data.most_recent_user = username;
208214
browser.storage.local.set(user_data);
209-
const user_list = (await browser.storage.local.get({ user_list: [] })).user_list;
210-
if (!user_list.includes(username)) {
211-
user_list.push(username);
212-
const users = {};
213-
users.user_list = user_list;
214-
browser.storage.local.set(users);
215-
}
216215
}
217216

218217
/**

0 commit comments

Comments
 (0)