Compare commits

...

80 Commits

Author SHA1 Message Date
Hykilpikonna 0345d37b2c [U] Pre-release v0.3.1.382 2019-10-05 14:11:32 -04:00
Hykilpikonna 97818c45f5 [-] Remove drop shadow 2019-10-05 14:10:26 -04:00
Hykilpikonna 1a09c7311e [O] Make font size smaller 2019-10-05 14:10:17 -04:00
Hykilpikonna b658f6f707 [O] Make text italic 2019-10-05 14:10:08 -04:00
Hykilpikonna 1d63e4865b [M] Move main color to theme 2019-10-05 14:05:26 -04:00
Hykilpikonna 78fbd342d9 [O] Apply nowrap to all cards 2019-10-05 14:04:06 -04:00
Hykilpikonna 141c192017 [+] Add github link to splash 2019-10-05 14:00:07 -04:00
Hykilpikonna 87e44b83f7 [+] Add github link constant 2019-10-05 13:59:50 -04:00
Hykilpikonna 1064831379 [O] Separate version as a constant 2019-10-05 13:59:37 -04:00
Hykilpikonna 1e42ef7873 [O] Add text shadow 2019-10-05 13:54:56 -04:00
Hykilpikonna c8327f3774 [O] Replace hex with var 2019-10-05 13:51:26 -04:00
Hykilpikonna 69cd4ff050 [+] Use default theme in base div 2019-10-05 13:51:05 -04:00
Hykilpikonna 027f8bfd34 [+] Create theme css class 2019-10-05 13:50:50 -04:00
Hykilpikonna 70ede22c18 [O] Remove space between number and '%' 2019-10-05 13:45:04 -04:00
Hykilpikonna fd74298b0b [+] Add some right margin 2019-10-05 13:44:35 -04:00
Hykilpikonna d47bae00ff [+] Change color of unread text as well 2019-10-05 13:43:32 -04:00
Hykilpikonna 0c91b1b598 [U] Update css implementation 2019-10-05 13:42:13 -04:00
Hykilpikonna 6ba789c7cf [M] Move unread class up a level 2019-10-05 13:41:56 -04:00
Hykilpikonna 54b70f6a1c [F] Fix inversed condition 2019-10-05 13:39:08 -04:00
Hykilpikonna ac32a02ff4 [O] Make 'update' plural only when count >= 2 2019-10-05 13:38:22 -04:00
Hykilpikonna 993578277e [+] Add 'new update' text 2019-10-05 13:38:00 -04:00
Hykilpikonna 48fb8c7d4c [O] Optimize unread count with caching 2019-10-05 13:36:56 -04:00
Hykilpikonna 0f6f27aa15 [O] Add some paddings to make it larger 2019-10-05 13:34:56 -04:00
Hykilpikonna b2947e9ef6 [+] Add shadow 2019-10-05 13:18:17 -04:00
Hykilpikonna c5ef8a297b [F] Fix css syntax: Stacked class vs stacked element 2019-10-05 13:16:31 -04:00
Hykilpikonna 02ca6b8d47 [+] Add dynamic coloring 2019-10-05 13:15:20 -04:00
Hykilpikonna 98b92b4dfb [+] Add dynamic class based on unread count 2019-10-05 13:14:03 -04:00
Hykilpikonna 1c2afdfa52 [O] Add block around the update number 2019-10-05 13:13:45 -04:00
Hykilpikonna 55b4bd9173 [+] Encapsulate method to count unread assignments 2019-10-05 13:10:34 -04:00
Hykilpikonna e422c03ca5 [-] Remove centering 2019-10-05 13:00:02 -04:00
Hykilpikonna 831ef16a2f [+] Display unread 2019-10-05 12:59:45 -04:00
Hykilpikonna 0deb0ed719 [F] Fix key typo: is_unread instead of unread 2019-10-05 12:56:10 -04:00
Hykilpikonna f3d44ceda2 [+] Parse id and unread 2019-10-05 10:24:42 -04:00
Hykilpikonna cb11db6201 [+] Add field id and unread to Assignment type 2019-10-05 10:23:46 -04:00
Hykilpikonna b52f3d2617 [M] Rename type Grade to type Assignment 2019-10-05 10:22:40 -04:00
Hykilpikonna 39cd5bf1a2 [F] Fix grid misplacement problem 2019-10-02 08:13:17 -04:00
Hykilpikonna 19f03717bc [O] Go back to using grid 2019-10-02 08:12:53 -04:00
Hykilpikonna 6d728c25ae [O] Center grade display 2019-10-01 21:45:36 -04:00
Hykilpikonna c8daa2a06e [+] Fix the numeric grade to 2 digits 2019-10-01 21:41:57 -04:00
Hykilpikonna 4d41e679dd [O] Make grade font size match Veracross 2019-10-01 21:29:56 -04:00
Hykilpikonna acfebf9ff3 [+] Show course card for every course 2019-10-01 21:29:35 -04:00
Hykilpikonna 5af1b1e5a1 [O] Add auto margin top and bottoms 2019-10-01 21:19:22 -04:00
Hykilpikonna bc9a4f00c1 [+] Align left and right 2019-10-01 21:19:08 -04:00
Hykilpikonna f13f3a155c [-] Remove the grid 2019-10-01 21:09:50 -04:00
Hykilpikonna a19edb8aa7 [+] Display numeric grade and letter grade 2019-10-01 21:01:15 -04:00
Hykilpikonna 6a0500acb2 [-] Remove unnecessary span 2019-10-01 20:54:29 -04:00
Hykilpikonna 96af69508f [O] Limit course name length 2019-10-01 20:50:25 -04:00
Hykilpikonna 3fbc9764e9 [O] Make teacher name italicised 2019-10-01 20:50:12 -04:00
Hykilpikonna a79dcb76af [O] Make teacher name font size match Veracross 2019-10-01 20:49:54 -04:00
Hykilpikonna 86c2fd5df7 [+] Add underline effect on hover 2019-10-01 20:49:18 -04:00
Hykilpikonna 07eaeef133 [+] Add margin to the beginning of course name 2019-10-01 20:49:03 -04:00
Hykilpikonna d1bd0a5667 [O] Change font size to match Veracross 2019-10-01 20:48:44 -04:00
Hykilpikonna 49dad14c84 [O] Adjust spacing 2019-10-01 20:47:57 -04:00
Hykilpikonna 50e3c345d5 [O] Clarify css selector 2019-10-01 20:40:18 -04:00
Hykilpikonna a444dbb32a [+] Add cols to display course name and teacher name 2019-10-01 20:39:53 -04:00
Hykilpikonna 03e212bd37 [+] Add margins to the navigation bar 2019-10-01 20:24:54 -04:00
Hykilpikonna 0325eb13d5 [F] Fix css priority issue 2019-10-01 20:17:37 -04:00
Hykilpikonna bfcb80aa64 [+] Add a title but comment it out 2019-10-01 20:10:48 -04:00
Hykilpikonna 91a6c0c6e4 [+] Optimize card formatting 2019-10-01 20:01:56 -04:00
Hykilpikonna 845cc94513 [+] Add a card in course element 2019-10-01 20:01:47 -04:00
Hykilpikonna 21ccaceb53 [+] Add a testing course element 2019-10-01 20:01:37 -04:00
Hykilpikonna b9f63171f2 [+] Create overall-course component 2019-10-01 19:44:51 -04:00
Hykilpikonna 636d92d1a0 [M] Rename and correct some misc css class names 2019-10-01 19:44:24 -04:00
Hykilpikonna 199ab9e00c [M] Rename graph-average to overall-bar 2019-10-01 19:37:20 -04:00
Hykilpikonna 77541764d1 [M] Rename graph-overall to overall-line 2019-10-01 19:36:09 -04:00
Hykilpikonna 53ae74f9c4 [O] Use absolute positioning to center what's in the center 2019-10-01 19:33:11 -04:00
Hykilpikonna 5bc1d6ba48 [O] Put sign-out button on the right 2019-10-01 19:30:41 -04:00
Hykilpikonna 831ddcf84e [-] Remove debug output 2019-10-01 19:27:00 -04:00
Hykilpikonna 35a85d8e83 [U] Release v0.2.3.315 2019-10-01 19:19:27 -04:00
Hykilpikonna 71b0a6e4dd [-] Remove debug output 2019-10-01 19:18:51 -04:00
Hykilpikonna d4fbd04466 [F] Fix grading history lower than actual 2019-10-01 19:18:33 -04:00
Hykilpikonna 31b3814b1e [O] Ignore 0 when calculating the score 2019-10-01 19:02:41 -04:00
Hykilpikonna 1aff2b0a68 [-] Remove debug output 2019-10-01 19:02:10 -04:00
Hykilpikonna 2567fcadbd [+] Encapsulate method to calculate total-mean average 2019-10-01 18:41:42 -04:00
Hykilpikonna d9e0e9f84e [F] Fix another null case 2019-10-01 18:41:14 -04:00
Hykilpikonna 59b31ea43f [F] Fix key word typo 2019-10-01 18:41:04 -04:00
Hykilpikonna 2c8b3e0f84 [F] Fix null case 2019-10-01 18:40:54 -04:00
Hykilpikonna 6910a7b5ea [F] Fix null pointer caused by grading not existing 2019-10-01 18:30:20 -04:00
Hykilpikonna cbdcfc4ca1 [+] Check gradings after checking assignments 2019-10-01 18:30:02 -04:00
Hykilpikonna feabc336c1 [+] Create method to check course gradings 2019-10-01 18:29:50 -04:00
23 changed files with 377 additions and 58 deletions
+11 -5
View File
@@ -1,8 +1,14 @@
#app
{
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
}
.theme-default
{
--unread: #ff6c00;
--main: #0c6dad;
}
+70 -6
View File
@@ -7,12 +7,14 @@ import JsonUtils from '@/utils/json-utils';
import pWaitFor from 'p-wait-for';
import {HttpUtils} from '@/utils/http-utils';
import {CourseUtils} from '@/utils/course-utils';
import {GPAUtils} from '@/utils/gpa-utils';
/**
* Objects of this interface represent assignment grades.
*/
export interface Grade
export interface Assignment
{
id: number,
type: string,
description: string,
date: string,
@@ -20,6 +22,8 @@ export interface Grade
include: boolean,
display: boolean,
unread: boolean,
scoreMax: number,
score: number
}
@@ -47,7 +51,7 @@ export interface Course
weightingMap: {[index: string]: number}
}
assignments: Grade[]
assignments: Assignment[]
}
@Component({
@@ -160,12 +164,11 @@ export default class App extends Vue
// Wait for assignments to be ready.
pWaitFor(() => this.isAssignmentsReady()).then(() =>
{
// When the assignments are ready
// TODO: Display loading
this.assignmentsReady = true;
// Filter courses
this.filteredCourses = CourseUtils.getGradedCourses(this.courses);
// Check grading algorithms
this.checkGradingAlgorithms();
});
}
@@ -184,6 +187,67 @@ export default class App extends Vue
return true;
}
/**
* Check the courses' grading algorithms. (Total-average or percent-type)
*/
private checkGradingAlgorithms()
{
// Loop through all the courses
for (const course of this.filteredCourses)
{
// Check if total-average grade is the same with percent-type grade
if (course.numericGrade == GPAUtils.getTotalMeanAverage(course))
{
course.grading = {method: 'TOTAL_AVERAGE', weightingMap: {}};
}
else
{
// Request grading scheme for this course
this.http.post('/grading', {'assignment_id': course.assignmentsId}).then(response =>
{
// Check success
if (response.success)
{
// Add it to course
course.grading = response.data;
}
else
{
// Show error message TODO: Show it properly
alert(response.data)
}
})
.catch(alert)
}
}
// Wait for done
pWaitFor(() => this.isGradingReady()).then(() =>
{
// When the assignments are ready
// TODO: Display loading
this.assignmentsReady = true;
})
}
/**
* Are grading algorithms ready or not.
*
* @returns boolean Ready or not
*/
private isGradingReady(): boolean
{
for (const course of this.filteredCourses)
{
if (course.grading == undefined)
{
return false;
}
}
return true;
}
/**
* This is called when a navigation tab is clicked
*
+1 -1
View File
@@ -1,5 +1,5 @@
<template>
<div id="app">
<div id="app" class="theme-default">
<login v-if="showLogin" v-on:login:token="onLogin" :http="http"></login>
<navigation :courses="filteredCourses"
v-on:sign-out="signOut()"
+33
View File
@@ -15,3 +15,36 @@
border-bottom-width: 0;
}
}
#sign-out-button
{
// Float right
position: absolute;
right: 0;
// Set width and height
height: 60px;
width: 110px;
}
#nav-title
{
// Float left
position: absolute;
left: 0;
// Set height
height: 60px;
// Center text
align-items: center;
// Margins
margin-left: 14px;
margin-right: 8px;
// Font
font-size: 1.25rem;
display: inline-flex;
}
+6 -1
View File
@@ -1,6 +1,11 @@
<template>
<div id="navigation">
<el-menu class="centered" :default-active="activeIndex" mode="horizontal" @select="onSelect">
<el-menu style="margin-bottom: 10px;"
class="centered" :default-active="activeIndex" mode="horizontal" @select="onSelect">
<!--div id="nav-title">
Veracross Analyzer
</div-->
<el-menu-item index="overall">Overall</el-menu-item>
+7 -1
View File
@@ -8,12 +8,18 @@ export default class Constants
*/
public static API_URL: string = 'https://va.hydev.org/api';
public static VERSION: string = '0.3.1.382';
public static GITHUB: string = 'https://github.com/HyDevelop/VeracrossAnalyzer.Client';
public static SPLASH: string =
'. , ,---. | \n' +
'| |. , |---|,---.,---.| , .,---,,---.,---.\n' +
' \\ / >< | || |,---|| | | .-\' |---\'| \n' +
' `\' \' ` ` \'` \'`---^`---\'`---|\'---\'`---\'` \n' +
' v0.2.2.303 `---\' ';
' `---\' \n' +
` Version v${Constants.VERSION} by Hykilpikonna (YGui21)\n` +
` Github: ${Constants.GITHUB}`;
// Graph Theme
public static THEME =
@@ -1,9 +0,0 @@
<template>
<div id="graph-average">
<ve-bar height="450px" class="graph"
:extend="chartSettings"></ve-bar>
</div>
</template>
<script src="./graph-average.ts" lang="ts"></script>
<style src="./graph-average.scss" lang="scss"></style>
@@ -1,8 +0,0 @@
<template>
<div id="graph-overall">
<ve-line :data="convertChart" :extend="settings"></ve-line>
</div>
</template>
<script src="./graph-overall.ts" lang="ts"></script>
<style src="./graph-overall.scss" lang="scss"></style>
@@ -1,4 +1,4 @@
#graph-average
#overall-bar
{
.graph
{
@@ -5,7 +5,7 @@ import Constants from '@/constants';
@Component({
})
export default class GraphAverage extends Vue
export default class OverallBar extends Vue
{
// @ts-ignore
@Prop({required: true}) courses: Course[];
@@ -82,9 +82,6 @@ export default class GraphAverage extends Vue
}
};
// TODO: Remove this
console.log(settings);
return settings;
}
@@ -0,0 +1,9 @@
<template>
<div id="overall-bar">
<ve-bar height="450px" class="graph"
:extend="chartSettings"></ve-bar>
</div>
</template>
<script src="./overall-bar.ts" lang="ts"></script>
<style src="./overall-bar.scss" lang="scss"></style>
@@ -0,0 +1,106 @@
// Card
.el-card.course-card
{
// Margins
margin-right: 20px;
margin-left: 20px;
// Height limit
max-height: 90px;
// Limit name length
white-space: nowrap;
}
.course-col-name
{
// Align left
text-align: left;
float: left;
.course-name
{
overflow: hidden;
font-size: 22px;
color: var(--main);
}
.course-name:hover
{
text-decoration: underline;
}
.course-teacher
{
font-size: 12px;
color: #999999;
font-style: italic;
}
}
.course-col-grade
{
// Align right
text-align: right;
float: right;
// Adjust position
margin-top: -2px;
.course-grade
{
font-size: 21px;
}
.course-updates
{
font-size: 14px;
.unread-number
{
display: inline-block;
width: 20px;
text-align: center;
border-radius: 5px;
padding-left: 3px;
padding-right: 3px;
margin-right: 3px;
}
.unread-text
{
font-style: italic;
}
}
.course-updates.unread
{
.unread-number
{
background: var(--unread);
color: white;
}
.unread-text
{
color: var(--unread);
}
}
.course-updates.none
{
color: #999999;
.unread-number
{
background: #eeeeee;
}
}
}
.el-card__body
{
margin: auto 0;
}
@@ -0,0 +1,26 @@
import {Component, Prop, Vue} from 'vue-property-decorator';
import {Course} from '@/components/app/app';
import {GPAUtils} from '@/utils/gpa-utils';
import Constants from '@/constants';
@Component({
})
export default class OverallCourse extends Vue
{
// @ts-ignore
@Prop({required: true}) course: Course;
private unread: number = -1;
/**
* Count the number of unread assignments with cache
*/
countUnread(): number
{
if (this.unread == -1)
{
return this.unread = this.course.assignments.filter(a => a.unread).length;
}
else return this.unread;
}
}
@@ -0,0 +1,37 @@
<template>
<div id="overall-course">
<el-card class="course-card">
<el-row>
<el-col :span="6" class="course-col-name">
<div class="course-name">
{{course.name}}
</div>
<div class="course-teacher">
{{course.teacherName}}
</div>
</el-col>
<el-col :span="12">
&nbsp;
</el-col>
<el-col :span="6" class="course-col-grade">
<div class="course-grade">
<span class="letter">{{course.letterGrade}} </span>
<span class="numeric">{{course.numericGrade.toFixed(2)}}</span>
<span class="percent">%</span>
</div>
<div class="course-updates" :class="countUnread() === 0 ? 'none' : 'unread'">
<span class="unread-number">
{{countUnread()}}
</span>
<span class="unread-text">
new update{{countUnread() >= 2 ? 's' : ''}}
</span>
</div>
</el-col>
</el-row>
</el-card>
</div>
</template>
<script src="./overall-course.ts" lang="ts"></script>
<style src="./overall-course.scss" lang="scss"></style>
@@ -3,7 +3,7 @@ import {Course} from '@/components/app/app';
@Component({
})
export default class GraphOverall extends Vue
export default class OverallLine extends Vue
{
// @ts-ignore
@Prop({required: true}) courses: Course[];
@@ -142,17 +142,28 @@ export default class GraphOverall extends Vue
}
});
let score = 0;
// Count total percentage (This is to avoid less than expected cases)
// Eg. If HW = 25% and Quiz = 75%, I have 1 hw and 0 quiz
// Without total percentage, the avg grade I get is 25%.
let totalPercentage = 0;
for (let type in course.grading.weightingMap)
{
if (typeScores[type] != undefined)
{
totalPercentage += course.grading.weightingMap[type];
}
}
// Count
let score = 0;
for (let type in typeScores)
{
score += typeScores[type] * course.grading.weightingMap[type] / typeCounts[type];
console.log(type);
let typeFactor = course.grading.weightingMap[type] / totalPercentage;
score += typeScores[type] * typeFactor / typeCounts[type];
}
// Add average to the row
row[course.name] = score * 100;
if (score != 0) row[course.name] = score * 100;
}
});
@@ -160,8 +171,6 @@ export default class GraphOverall extends Vue
rows.push(row);
});
console.log(rows);
return {
columns: columns,
rows: rows
@@ -0,0 +1,8 @@
<template>
<div id="overall-line">
<ve-line :data="convertChart" :extend="settings"></ve-line>
</div>
</template>
<script src="./overall-line.ts" lang="ts"></script>
<style src="./overall-line.scss" lang="scss"></style>
+2 -2
View File
@@ -47,8 +47,8 @@
font-size: 11px;
}
// Graph average
.graph-average-card
// Cards
.el-card.overall-bar-card
{
margin-right: 20px;
min-width: 170px;
+4 -3
View File
@@ -1,11 +1,12 @@
import {Component, Prop, Vue} from 'vue-property-decorator';
import GraphOverall from '@/pages/overall/graph-overall/graph-overall';
import GraphAverage from '@/pages/overall/graph-average/graph-average';
import OverallLine from '@/pages/overall/overall-line/overall-line';
import OverallBar from '@/pages/overall/overall-bar/overall-bar';
import OverallCourse from '@/pages/overall/overall-course/overall-course';
import {Course} from '@/components/app/app';
import {GPAUtils} from '@/utils/gpa-utils';
@Component({
components: {GraphOverall, GraphAverage}
components: {OverallLine, OverallBar, OverallCourse}
})
export default class Overall extends Vue
{
+6 -5
View File
@@ -14,17 +14,18 @@
</el-card>
</el-col>
<el-col :span="14">
<el-card>
<graph-overall :courses="courses"></graph-overall>
<el-card class="overall-line-card">
<overall-line :courses="courses"></overall-line>
</el-card>
</el-col>
<el-col :span="6">
<el-card class="graph-average-card">
<graph-average :courses="courses"></graph-average>
<el-card class="overall-bar-card">
<overall-bar :courses="courses"></overall-bar>
</el-card>
</el-col>
</el-row>
<div class=""></div>
<overall-course v-for="course in courses" :course="course"></overall-course>
</div>
</template>
+1 -1
View File
@@ -26,7 +26,7 @@ export class CourseUtils
if (course.assignments.length == 0) return;
// Skip if there are no grading scale
if (course.grading.method == 'NOT_GRADED') return;
// if (course.grading.method == 'NOT_GRADED') return;
// Add it to the list
result.push(course);
+25
View File
@@ -102,4 +102,29 @@ export class GPAUtils
return -1;
}
/**
* Calculate the total-mean (total/max) average
*
* @param course Course
*/
public static getTotalMeanAverage(course: Course)
{
let score = 0;
let max = 0;
// Loop through assignments
course.assignments.forEach(assignment =>
{
// If assignment should be displayed
if (assignment.complete != 'Complete') return;
// Record scores
score += assignment.score;
max += assignment.scoreMax;
});
// Return
return score / max * 100;
}
}
+7 -4
View File
@@ -1,4 +1,4 @@
import {Grade} from '@/components/app/app';
import {Assignment} from '@/components/app/app';
export default class JsonUtils
{
@@ -6,16 +6,17 @@ export default class JsonUtils
* This method filters the information provided in an assignments json.
*
* @param assignments Assignments object
* @returns Grade[] Filtered assignment grade object list
* @returns Assignment[] Filtered assignment grade object list
*/
public static filterAssignments(assignments: any): Grade[]
public static filterAssignments(assignments: any): Assignment[]
{
let result: Grade[] = [];
let result: Assignment[] = [];
assignments.assignments.forEach((assignment: any) =>
{
result.push(
{
id: assignment.assignment_id,
type: assignment.assignment_type,
description: assignment.assignment_description,
date: assignment._date,
@@ -23,6 +24,8 @@ export default class JsonUtils
include: assignment.include_in_calculated_grade == 1,
display: assignment.display_grade == 1,
unread: assignment.is_unread == 1,
scoreMax: assignment.maximum_score,
score: +assignment.raw_score
});