Compare commits
83 Commits
0.4.3.1006
...
0.4.6.1087
| Author | SHA1 | Date | |
|---|---|---|---|
| c97a202bd5 | |||
| b11332953c | |||
| d5f8649b80 | |||
| fab173afa3 | |||
| 41fbf70428 | |||
| 1df427b4b4 | |||
| 96a0d3bef6 | |||
| 2d917d7858 | |||
| 2e851e5541 | |||
| b5ff93bf58 | |||
| a10350756f | |||
| 133765131c | |||
| 723a72c1ab | |||
| 6567aeda7d | |||
| 2182ff8e74 | |||
| 25865fb372 | |||
| 81ffeb8d85 | |||
| 19203f3629 | |||
| 82ad8f026b | |||
| 38629a9e34 | |||
| 4499232544 | |||
| 960f30295c | |||
| 415373559c | |||
| a7d22e1620 | |||
| f88ef7284f | |||
| 380023668f | |||
| fb90900045 | |||
| ab511a706a | |||
| 407a2889d1 | |||
| 840775314a | |||
| 85c1d93608 | |||
| 8825886c5c | |||
| e924c00f0d | |||
| 03826d108d | |||
| 1e04b4ad70 | |||
| 3ac37d980c | |||
| da8cec72b4 | |||
| 903345b86a | |||
| 9ed297431d | |||
| e763a1ac88 | |||
| 5b3bdc2f1f | |||
| 65b4a68f7e | |||
| 7ff885e28b | |||
| b936f8a0ca | |||
| 93a01aeb5d | |||
| 0326c0bf14 | |||
| cb91a20844 | |||
| 9fdb7461ba | |||
| 15b51020fc | |||
| 2938621b73 | |||
| 624158f3d4 | |||
| 602a8b9c46 | |||
| 62338358d1 | |||
| 9bc69a81af | |||
| c93b1e4eec | |||
| d30728e2e9 | |||
| 7d86b7a2b9 | |||
| bb31e18ad5 | |||
| 73dc5f6a51 | |||
| 6343a10fbc | |||
| 14beb802b0 | |||
| be71c4ea0b | |||
| 4bd34d46be | |||
| 670ac48516 | |||
| 4ce7c625ea | |||
| 551930f47a | |||
| 04ca753466 | |||
| 4169d5235a | |||
| c417698bf2 | |||
| b6bf6373f2 | |||
| f4326cf9e1 | |||
| cca9d5a240 | |||
| 0af3cee18b | |||
| 8d122f0100 | |||
| 62373485f5 | |||
| 472d83e9fb | |||
| 34231dc480 | |||
| 3f6c9c1204 | |||
| d0e627bd83 | |||
| 6e4074b050 | |||
| 963df01b6f | |||
| c807d4aecb | |||
| e2c9d05a7e |
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 60 KiB |
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 6.7 KiB |
Generated
+60
-2
@@ -947,6 +947,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@types/chroma-js": {
|
||||||
|
"version": "1.4.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/chroma-js/-/chroma-js-1.4.3.tgz",
|
||||||
|
"integrity": "sha512-m33zg9cRLtuaUSzlbMrr7iLIKNzrD4+M6Unt5+9mCu4BhR5NwnRjVKblINCwzcBXooukIgld8DtEncP8qpvbNg=="
|
||||||
|
},
|
||||||
"@types/events": {
|
"@types/events": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npm.taobao.org/@types/events/download/@types/events-3.0.0.tgz",
|
"resolved": "https://registry.npm.taobao.org/@types/events/download/@types/events-3.0.0.tgz",
|
||||||
@@ -2510,6 +2515,14 @@
|
|||||||
"integrity": "sha1-oY8eCyacimpdPIbrKYvrFMPde/Y=",
|
"integrity": "sha1-oY8eCyacimpdPIbrKYvrFMPde/Y=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"chroma-js": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/chroma-js/-/chroma-js-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-uiRdh4ZZy+UTPSrAdp8hqEdVb1EllLtTHOt5TMaOjJUvi+O54/83Fc5K2ld1P+TJX+dw5B+8/sCgzI6eaur/lg==",
|
||||||
|
"requires": {
|
||||||
|
"cross-env": "^6.0.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
"chrome-trace-event": {
|
"chrome-trace-event": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npm.taobao.org/chrome-trace-event/download/chrome-trace-event-1.0.2.tgz",
|
"resolved": "https://registry.npm.taobao.org/chrome-trace-event/download/chrome-trace-event-1.0.2.tgz",
|
||||||
@@ -3113,6 +3126,52 @@
|
|||||||
"sha.js": "^2.4.8"
|
"sha.js": "^2.4.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"cross-env": {
|
||||||
|
"version": "6.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/cross-env/-/cross-env-6.0.3.tgz",
|
||||||
|
"integrity": "sha512-+KqxF6LCvfhWvADcDPqo64yVIB31gv/jQulX2NGzKS/g3GEVz6/pt4wjHFtFWsHMddebWD/sDthJemzM4MaAag==",
|
||||||
|
"requires": {
|
||||||
|
"cross-spawn": "^7.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"cross-spawn": {
|
||||||
|
"version": "7.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.1.tgz",
|
||||||
|
"integrity": "sha512-u7v4o84SwFpD32Z8IIcPZ6z1/ie24O6RU3RbtL5Y316l3KuHVPx9ItBgWQ6VlfAFnRnTtMUrsQ9MUUTuEZjogg==",
|
||||||
|
"requires": {
|
||||||
|
"path-key": "^3.1.0",
|
||||||
|
"shebang-command": "^2.0.0",
|
||||||
|
"which": "^2.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"path-key": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-8cChqz0RP6SHJkMt48FW0A7+qUOn+OsnOsVtzI59tZ8m+5bCSk7hzwET0pulwOM2YMn9J1efb07KB9l9f30SGg=="
|
||||||
|
},
|
||||||
|
"shebang-command": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
|
||||||
|
"requires": {
|
||||||
|
"shebang-regex": "^3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"shebang-regex": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="
|
||||||
|
},
|
||||||
|
"which": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/which/-/which-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-N7GBZOTswtB9lkQBZA4+zAXrjEIWAUOB93AvzUiudRzRxhUdLURQ7D/gAIMY1gatT/LTbmbcv8SiYazy3eYB7w==",
|
||||||
|
"requires": {
|
||||||
|
"isexe": "^2.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"cross-spawn": {
|
"cross-spawn": {
|
||||||
"version": "6.0.5",
|
"version": "6.0.5",
|
||||||
"resolved": "https://registry.npm.taobao.org/cross-spawn/download/cross-spawn-6.0.5.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcross-spawn%2Fdownload%2Fcross-spawn-6.0.5.tgz",
|
"resolved": "https://registry.npm.taobao.org/cross-spawn/download/cross-spawn-6.0.5.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcross-spawn%2Fdownload%2Fcross-spawn-6.0.5.tgz",
|
||||||
@@ -6266,8 +6325,7 @@
|
|||||||
"isexe": {
|
"isexe": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npm.taobao.org/isexe/download/isexe-2.0.0.tgz",
|
"resolved": "https://registry.npm.taobao.org/isexe/download/isexe-2.0.0.tgz",
|
||||||
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
|
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"isobject": {
|
"isobject": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
|
|||||||
@@ -8,6 +8,8 @@
|
|||||||
"lint": "vue-cli-service lint"
|
"lint": "vue-cli-service lint"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@types/chroma-js": "^1.4.3",
|
||||||
|
"chroma-js": "^2.1.0",
|
||||||
"core-js": "^2.6.5",
|
"core-js": "^2.6.5",
|
||||||
"echarts": "^4.2.1",
|
"echarts": "^4.2.1",
|
||||||
"element-ui": "^2.11.1",
|
"element-ui": "^2.11.1",
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@
|
|||||||
<!--meta name="viewport" content="width=device-width,initial-scale=1.0"-->
|
<!--meta name="viewport" content="width=device-width,initial-scale=1.0"-->
|
||||||
<meta name="viewport" content="width=1024">
|
<meta name="viewport" content="width=1024">
|
||||||
|
|
||||||
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
|
<link rel="icon" href="<%= BASE_URL %>logo@32px.png">
|
||||||
<title>Veracross Analyzer</title>
|
<title>Veracross Analyzer</title>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 4.4 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 6.7 KiB After Width: | Height: | Size: 60 KiB |
@@ -5,7 +5,7 @@
|
|||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
color: #2c3e50;
|
color: #2c3e50;
|
||||||
margin-bottom: 100px;
|
padding-bottom: 100px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#app-content
|
#app-content
|
||||||
@@ -28,6 +28,59 @@
|
|||||||
--font: 'Avenir', Helvetica, Arial, sans-serif;
|
--font: 'Avenir', Helvetica, Arial, sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dark
|
||||||
|
{
|
||||||
|
--dark-layer-1: #383838;
|
||||||
|
--dark-layer-2: #525252;
|
||||||
|
--dark-layer-3: #6c6c6c;
|
||||||
|
--dark-foreground: #e9e9e9;
|
||||||
|
|
||||||
|
background: var(--dark-layer-1) !important;
|
||||||
|
|
||||||
|
div, ul
|
||||||
|
{
|
||||||
|
background: var(--dark-layer-2) !important;
|
||||||
|
color: var(--dark-foreground) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
span, button
|
||||||
|
{
|
||||||
|
color: var(--dark-foreground) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-card
|
||||||
|
{
|
||||||
|
border: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Overall
|
||||||
|
#overall, #overall-course, .overall-span, #app-content
|
||||||
|
{
|
||||||
|
background: var(--dark-layer-1) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Course card
|
||||||
|
.entry-box, .none .unread-number {background: #a1a1a1 !important}
|
||||||
|
.entry-box.max {background-color: #949494 !important}
|
||||||
|
.entry-box.percent {background-color: #a7a490 !important}
|
||||||
|
.course-name {color: #cffff6 !important}
|
||||||
|
|
||||||
|
.course-card-content.expand, .assignment-entry, .unread-row,
|
||||||
|
.unread-row .el-col, #assignment-type-head, .course-page-graph.el-col
|
||||||
|
{
|
||||||
|
background-color: var(--dark-layer-3) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.overall-span.el-col, .course-page-graph.el-col
|
||||||
|
{
|
||||||
|
div, span
|
||||||
|
{
|
||||||
|
background: #f9f9f9 !important;
|
||||||
|
color: var(--dark-layer-1) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ##############
|
// ##############
|
||||||
// # Global CSS #
|
// # Global CSS #
|
||||||
// ##############
|
// ##############
|
||||||
|
|||||||
@@ -5,6 +5,13 @@
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Logo image
|
||||||
|
#login-logo-image
|
||||||
|
{
|
||||||
|
width: 80%;
|
||||||
|
margin-bottom: -15px;
|
||||||
|
}
|
||||||
|
|
||||||
// Parent overlay
|
// Parent overlay
|
||||||
.login-overlay
|
.login-overlay
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -11,11 +11,11 @@ import VersionUtils from '@/logic/utils/version-utils';
|
|||||||
})
|
})
|
||||||
export default class Login extends Vue
|
export default class Login extends Vue
|
||||||
{
|
{
|
||||||
public username: any = '';
|
public username: string = '';
|
||||||
public password: any = '';
|
public password: string = '';
|
||||||
|
|
||||||
public loading: boolean = false;
|
public loading: boolean = false;
|
||||||
public error: String = '';
|
public error: string = '';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is called when the instance is created.
|
* This is called when the instance is created.
|
||||||
@@ -68,6 +68,9 @@ export default class Login extends Vue
|
|||||||
// Make login button loading
|
// Make login button loading
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
|
|
||||||
|
// Format it
|
||||||
|
this.username = this.username.toLowerCase().replace(/ /g, '').replace(/@.*/g, '');
|
||||||
|
|
||||||
// Fetch request
|
// Fetch request
|
||||||
App.http.post('/login', {username: this.username, password: this.password})
|
App.http.post('/login', {username: this.username, password: this.password})
|
||||||
.then(response =>
|
.then(response =>
|
||||||
|
|||||||
@@ -2,18 +2,18 @@
|
|||||||
<div id="login" class="login-overlay">
|
<div id="login" class="login-overlay">
|
||||||
<div class="login-vertical-center">
|
<div class="login-vertical-center">
|
||||||
<div class="login-panel">
|
<div class="login-panel">
|
||||||
<img alt="Vue logo" src="../../assets/logo.png">
|
<img id="login-logo-image" alt="logo" src="../../assets/logo.png">
|
||||||
|
|
||||||
<h1>Veracross Analyzer</h1>
|
<h1>Veracross Analyzer</h1>
|
||||||
<form id="login-form">
|
<form id="login-form">
|
||||||
<el-input v-model="username"
|
<el-input v-model="username"
|
||||||
placeholder="School Username"
|
placeholder="SJP Username (Eg. flast21)"
|
||||||
:class="{'input-error': error !== ''}"
|
:class="{'input-error': error !== ''}"
|
||||||
@keyup.enter.native="onEnter">
|
@keyup.enter.native="onEnter">
|
||||||
</el-input>
|
</el-input>
|
||||||
|
|
||||||
<el-input v-model="password"
|
<el-input v-model="password"
|
||||||
placeholder="Veracross Password"
|
placeholder="SJP Password"
|
||||||
show-password=""
|
show-password=""
|
||||||
:class="{'input-error': error !== ''}"
|
:class="{'input-error': error !== ''}"
|
||||||
@keyup.enter.native="onEnter">
|
@keyup.enter.native="onEnter">
|
||||||
|
|||||||
@@ -48,24 +48,41 @@
|
|||||||
height: 60px;
|
height: 60px;
|
||||||
|
|
||||||
// Center text
|
// Center text
|
||||||
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
// Margins
|
// Margins
|
||||||
margin-left: 20px;
|
margin-left: 20px;
|
||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
|
|
||||||
// Font
|
|
||||||
font: bold 16px arial;
|
|
||||||
display: inline-flex;
|
|
||||||
|
|
||||||
// Shadow effect
|
|
||||||
-webkit-background-clip: text;
|
|
||||||
background-color: #b1b1b1;
|
|
||||||
color: transparent;
|
|
||||||
text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.85);
|
|
||||||
|
|
||||||
// Make it non-clickable
|
// Make it non-clickable
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
|
||||||
|
#nav-logo
|
||||||
|
{
|
||||||
|
height: 70%;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#nav-logo-text
|
||||||
|
{
|
||||||
|
// Color
|
||||||
|
color: #6bbeff !important;
|
||||||
|
background: linear-gradient(90deg,
|
||||||
|
rgba(90,177,239,1) 0%,
|
||||||
|
rgba(25,212,174,1) 100%) !important;
|
||||||
|
|
||||||
|
// Font
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#nav-logo-text.logo-text
|
||||||
|
{
|
||||||
|
// Override the background
|
||||||
|
-webkit-text-fill-color: transparent !important;
|
||||||
|
-webkit-background-clip: text !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#next-course
|
#next-course
|
||||||
@@ -76,7 +93,7 @@
|
|||||||
bottom: 0;
|
bottom: 0;
|
||||||
left: 25%;
|
left: 25%;
|
||||||
padding-top: 2px;
|
padding-top: 2px;
|
||||||
box-shadow: 0 -2px 9px 0 #ecebeb;
|
box-shadow: 0 -2px 9px 0 #00000029;
|
||||||
}
|
}
|
||||||
|
|
||||||
footer
|
footer
|
||||||
@@ -85,6 +102,8 @@ footer
|
|||||||
left: 0;
|
left: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
|
z-index: 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
#prev-course
|
#prev-course
|
||||||
@@ -95,7 +114,9 @@ footer
|
|||||||
top: 61px;
|
top: 61px;
|
||||||
left: 25%;
|
left: 25%;
|
||||||
padding-bottom: 2px;
|
padding-bottom: 2px;
|
||||||
box-shadow: 0 2px 9px 0 #ecebeb;
|
box-shadow: 0 2px 9px 0 #00000029;
|
||||||
|
|
||||||
|
z-index: 1001;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-course-operations
|
.nav-course-operations
|
||||||
|
|||||||
@@ -106,6 +106,9 @@ export default class Navigation extends Vue
|
|||||||
|
|
||||||
// Update title
|
// Update title
|
||||||
document.title = 'Veracross Analyzer - ' + this.getTitle(newIndex);
|
document.title = 'Veracross Analyzer - ' + this.getTitle(newIndex);
|
||||||
|
|
||||||
|
// Scroll to top
|
||||||
|
window.scrollTo(0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -4,7 +4,8 @@
|
|||||||
:default-active="activeIndex" @select="onSelect">
|
:default-active="activeIndex" @select="onSelect">
|
||||||
|
|
||||||
<div id="nav-title">
|
<div id="nav-title">
|
||||||
Veracross Analyzer
|
<img id="nav-logo" alt="logo" src="../../assets/logo.png">
|
||||||
|
<span id="nav-logo-text" class="logo-text">Veracross Analyzer</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<el-menu-item index="overall">Overall</el-menu-item>
|
<el-menu-item index="overall">Overall</el-menu-item>
|
||||||
@@ -44,6 +45,9 @@
|
|||||||
▼ NEXT COURSE ▼
|
▼ NEXT COURSE ▼
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
|
<!-- Back to top -->
|
||||||
|
<el-backtop style="box-shadow: rgba(0, 0, 0, 0.23) 0 3px 11px 0;"></el-backtop>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -7,7 +7,7 @@ export default class Constants
|
|||||||
public static API_URL: string = 'https://va.hydev.org/api';
|
public static API_URL: string = 'https://va.hydev.org/api';
|
||||||
|
|
||||||
/** Current version */
|
/** Current version */
|
||||||
public static VERSION: string = '0.4.3.1006';
|
public static VERSION: string = '0.4.6.1087';
|
||||||
|
|
||||||
/** Minimum version that still supports the same cookies */
|
/** Minimum version that still supports the same cookies */
|
||||||
public static MIN_SUPPORTED_VERSION: string = '0.3.4.561';
|
public static MIN_SUPPORTED_VERSION: string = '0.3.4.561';
|
||||||
|
|||||||
+4
-2
@@ -36,6 +36,7 @@ export interface AssignmentType
|
|||||||
scoreMax: number
|
scoreMax: number
|
||||||
score: number
|
score: number
|
||||||
percent: number
|
percent: number
|
||||||
|
assignmentCount: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class Course
|
export default class Course
|
||||||
@@ -256,8 +257,9 @@ export default class Course
|
|||||||
? this.grading.weightingMap[type] : scoreMax / totalScoreMax;
|
? this.grading.weightingMap[type] : scoreMax / totalScoreMax;
|
||||||
|
|
||||||
// Return
|
// Return
|
||||||
return {name: type, id: typeAssignments[0].typeId, weight: weight,
|
return {name: type, id: typeAssignments[0].typeId, weight: +(weight * 100).toFixed(2),
|
||||||
scoreMax: scoreMax, score: score, percent: +(score / scoreMax * 100).toFixed(2)}
|
scoreMax: scoreMax, score: score, percent: +(score / scoreMax * 100).toFixed(2),
|
||||||
|
assignmentCount: typeAssignments.length}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ export default class GraphUtils
|
|||||||
return {
|
return {
|
||||||
// Color
|
// Color
|
||||||
color: Constants.THEME.colors,
|
color: Constants.THEME.colors,
|
||||||
|
backgroundColor: 'transparent',
|
||||||
|
|
||||||
// Title
|
// Title
|
||||||
title:
|
title:
|
||||||
@@ -70,4 +71,29 @@ export default class GraphUtils
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Text style for pie graphs or radar graphs
|
||||||
|
*/
|
||||||
|
static pieTextStyle()
|
||||||
|
{
|
||||||
|
return {
|
||||||
|
fontSize: 14,
|
||||||
|
textShadowColor: '#cfcfcf',
|
||||||
|
textShadowBlur: 2,
|
||||||
|
textShadowOffsetX: 1,
|
||||||
|
textShadowOffsetY: 1,
|
||||||
|
backgroundColor: '#f6f6f6',
|
||||||
|
borderRadius: 3,
|
||||||
|
padding: [3, 5]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CSS shadow string (extraCssText) for tooltip
|
||||||
|
*/
|
||||||
|
static tooltipCssShadow()
|
||||||
|
{
|
||||||
|
return {extraCssText: 'box-shadow: 0 0 3px rgba(0, 0, 0, 0.3);'}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,3 +18,9 @@
|
|||||||
// https://stackoverflow.com/questions/17572619/inset-box-shadow-only-on-one-side
|
// https://stackoverflow.com/questions/17572619/inset-box-shadow-only-on-one-side
|
||||||
box-shadow: inset 0 7px 9px -7px rgba(0,0,0,0.1);
|
box-shadow: inset 0 7px 9px -7px rgba(0,0,0,0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.type-graph
|
||||||
|
{
|
||||||
|
padding-top: 23px;
|
||||||
|
height: 420px !important;
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,25 +4,25 @@
|
|||||||
|
|
||||||
<div class="course-card-content expand">
|
<div class="course-card-content expand">
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="24">
|
<el-col :span="24" class="course-page-graph">
|
||||||
<el-card class="large overall-line-card vertical-center">
|
<el-card class="large overall-line-card vertical-center">
|
||||||
<course-scatter :course="course"></course-scatter>
|
<course-scatter :course="course"></course-scatter>
|
||||||
</el-card>
|
</el-card>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="0">
|
|
||||||
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
|
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="12">
|
<el-col :span="12" class="course-page-graph">
|
||||||
<el-card class="large overall-line-card vertical-center" body-style="padding: 0">
|
<el-card class="large overall-line-card vertical-center type-graph"
|
||||||
<CourseTypeRadar :course="course"></CourseTypeRadar>
|
body-style="padding: 0">
|
||||||
|
<TypeRadar :course="course"></TypeRadar>
|
||||||
</el-card>
|
</el-card>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="12" class="course-page-graph">
|
||||||
Hi
|
<el-card class="large overall-line-card vertical-center type-graph"
|
||||||
|
body-style="padding: 0">
|
||||||
|
<TypePie :course="course"></TypePie>
|
||||||
|
</el-card>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
@@ -40,10 +40,11 @@
|
|||||||
import AssignmentEntry from '@/pages/overall/overall-course/assignment-entry/assignment-entry.vue';
|
import AssignmentEntry from '@/pages/overall/overall-course/assignment-entry/assignment-entry.vue';
|
||||||
import AssignmentTypeHead from '@/pages/course/assignment-type-head/assignment-type-head.vue';
|
import AssignmentTypeHead from '@/pages/course/assignment-type-head/assignment-type-head.vue';
|
||||||
import Course, {Assignment} from '@/logic/course';
|
import Course, {Assignment} from '@/logic/course';
|
||||||
import TypeRadar from '@/pages/course/course-type-radar/type-radar';
|
import TypeRadar from '@/pages/course/type-radar/type-radar';
|
||||||
|
import TypePie from '@/pages/course/type-pie/type-pie';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
components: {CourseTypeRadar: TypeRadar, AssignmentEntry, CourseHead, CourseScatter, AssignmentTypeHead}
|
components: {TypeRadar, TypePie, AssignmentEntry, CourseHead, CourseScatter, AssignmentTypeHead}
|
||||||
})
|
})
|
||||||
export default class CoursePage extends Vue
|
export default class CoursePage extends Vue
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import {FormatUtils} from '@/logic/utils/format-utils';
|
|||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import Course, {Assignment} from '@/logic/course';
|
import Course, {Assignment} from '@/logic/course';
|
||||||
import GraphUtils from '@/logic/utils/graph-utils';
|
import GraphUtils from '@/logic/utils/graph-utils';
|
||||||
|
import chroma from 'chroma-js';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
})
|
})
|
||||||
@@ -61,6 +62,8 @@ export default class CourseScatter extends Vue
|
|||||||
// Tooltip
|
// Tooltip
|
||||||
tooltip:
|
tooltip:
|
||||||
{
|
{
|
||||||
|
...GraphUtils.tooltipCssShadow(),
|
||||||
|
|
||||||
trigger: 'axis',
|
trigger: 'axis',
|
||||||
axisPointer:
|
axisPointer:
|
||||||
{
|
{
|
||||||
@@ -68,7 +71,7 @@ export default class CourseScatter extends Vue
|
|||||||
},
|
},
|
||||||
formatter: (ps: any[]) => moment(ps[0].data[0]).format('MMM DD, YYYY') + '<br>' + ps.map(p =>
|
formatter: (ps: any[]) => moment(ps[0].data[0]).format('MMM DD, YYYY') + '<br>' + ps.map(p =>
|
||||||
`${GraphUtils.DOT.replace('{color}', p.color)}
|
`${GraphUtils.DOT.replace('{color}', p.color)}
|
||||||
${FormatUtils.limit(p.data[2], 22)}: ${p.data[1]}%<br>`).join('')
|
${FormatUtils.limit(p.data[2].description, 22)}: ${p.data[1]}%<br>`).join('')
|
||||||
},
|
},
|
||||||
|
|
||||||
// Legend
|
// Legend
|
||||||
@@ -95,28 +98,47 @@ export default class CourseScatter extends Vue
|
|||||||
*/
|
*/
|
||||||
private series()
|
private series()
|
||||||
{
|
{
|
||||||
// Scatter data point style
|
|
||||||
let itemStyle =
|
|
||||||
{
|
|
||||||
normal:
|
|
||||||
{
|
|
||||||
opacity: 0.8,
|
|
||||||
shadowBlur: 10,
|
|
||||||
shadowOffsetX: 0,
|
|
||||||
shadowOffsetY: 0,
|
|
||||||
shadowColor: 'rgba(0, 0, 0, 0.2)'
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Create scatter plots
|
// Create scatter plots
|
||||||
let map = this.mapAssignments();
|
let series: any[] = this.course.assignmentTypes.map((type, i) =>
|
||||||
let series: any[] = Array.from(map, ([type, assignments]) =>
|
|
||||||
{
|
{
|
||||||
return {
|
return {
|
||||||
type: 'scatter',
|
type: 'scatter',
|
||||||
name: type,
|
name: type.name,
|
||||||
data: CourseScatter.assignmentsData(assignments),
|
data: CourseScatter.assignmentsData(this.course.assignments.filter(a => a.typeId == type.id)),
|
||||||
itemStyle: itemStyle
|
symbolSize: (data: any) => Math.max(Math.sqrt(type.weight * data[2].scoreMax / type.scoreMax) * 12, 12),
|
||||||
|
|
||||||
|
label:
|
||||||
|
{
|
||||||
|
emphasis:
|
||||||
|
{
|
||||||
|
show: true,
|
||||||
|
formatter: (p: any) => p.data[2].description,
|
||||||
|
position: 'top'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
itemStyle:
|
||||||
|
{
|
||||||
|
normal:
|
||||||
|
{
|
||||||
|
opacity: 0.7,
|
||||||
|
shadowBlur: 10,
|
||||||
|
shadowOffsetX: 0,
|
||||||
|
shadowOffsetY: 0,
|
||||||
|
shadowColor: 'rgba(0, 0, 0, 0.2)',
|
||||||
|
color:
|
||||||
|
{
|
||||||
|
type: 'radial',
|
||||||
|
x: 0.4,
|
||||||
|
y: 0.3,
|
||||||
|
colorStops:
|
||||||
|
[
|
||||||
|
{offset: 0, color: chroma(Constants.THEME.colors[i]).set('hsl.l', 0.9).css()},
|
||||||
|
{offset: 1, color: Constants.THEME.colors[i]}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -131,27 +153,6 @@ export default class CourseScatter extends Vue
|
|||||||
return series;
|
return series;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Map assignments to {assignmentType, [assignment]} format.
|
|
||||||
*/
|
|
||||||
private mapAssignments(): Map<string, Assignment[]>
|
|
||||||
{
|
|
||||||
// Define map
|
|
||||||
let map = new Map();
|
|
||||||
|
|
||||||
// Move data to map
|
|
||||||
this.course.assignments.forEach(a =>
|
|
||||||
{
|
|
||||||
// Null case, create empty array
|
|
||||||
if (!map.has(a.type)) map.set(a.type, []);
|
|
||||||
|
|
||||||
// Put data
|
|
||||||
map.get(a.type).push(a);
|
|
||||||
});
|
|
||||||
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert assignments to series data
|
* Convert assignments to series data
|
||||||
*
|
*
|
||||||
@@ -160,6 +161,6 @@ export default class CourseScatter extends Vue
|
|||||||
private static assignmentsData(assignments: Assignment[])
|
private static assignmentsData(assignments: Assignment[])
|
||||||
{
|
{
|
||||||
return assignments.filter(a => a.complete == 'Complete')
|
return assignments.filter(a => a.complete == 'Complete')
|
||||||
.map(a => [a.time, (a.score / a.scoreMax * 100).toFixed(2), a.description]);
|
.map(a => [a.time, (a.score / a.scoreMax * 100).toFixed(2), a]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,12 +5,4 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script src="./course-scatter.ts" lang="ts"></script>
|
<script src="./course-scatter.ts" lang="ts"></script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped></style>
|
||||||
#overall-bar
|
|
||||||
{
|
|
||||||
.graph
|
|
||||||
{
|
|
||||||
margin-top: 50px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="course-scatter">
|
|
||||||
<ve-radar height="450px" class="graph" :extend="{a: this.course.name}" :after-config="afterConfig"></ve-radar>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script src="./type-radar.ts" lang="ts"></script>
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
#overall-bar
|
|
||||||
{
|
|
||||||
.graph
|
|
||||||
{
|
|
||||||
margin-top: 50px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
import {Component, Prop, Vue} from 'vue-property-decorator';
|
||||||
|
import Constants from '@/constants';
|
||||||
|
import {FormatUtils} from '@/logic/utils/format-utils';
|
||||||
|
import moment from 'moment';
|
||||||
|
import Course, {Assignment} from '@/logic/course';
|
||||||
|
import GraphUtils from '@/logic/utils/graph-utils';
|
||||||
|
|
||||||
|
@Component
|
||||||
|
export default class TypePie extends Vue
|
||||||
|
{
|
||||||
|
@Prop({required: true}) course: Course;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override options
|
||||||
|
*
|
||||||
|
* @param options Original options (Unused)
|
||||||
|
*/
|
||||||
|
afterConfig(options: any)
|
||||||
|
{
|
||||||
|
return this.chartSettings;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate settings
|
||||||
|
*/
|
||||||
|
get chartSettings()
|
||||||
|
{
|
||||||
|
// Create settings
|
||||||
|
let settings =
|
||||||
|
{
|
||||||
|
...GraphUtils.getBaseSettings('Assignment Type Weight',
|
||||||
|
'How much each type of assignment affect your average'),
|
||||||
|
|
||||||
|
tooltip: GraphUtils.tooltipCssShadow(),
|
||||||
|
|
||||||
|
// Data
|
||||||
|
series:
|
||||||
|
{
|
||||||
|
type: 'pie',
|
||||||
|
avoidLabelOverlap: false,
|
||||||
|
radius: ['40%', '60%'],
|
||||||
|
center: ['50%', '55%'],
|
||||||
|
label: GraphUtils.pieTextStyle(),
|
||||||
|
data: this.course.assignmentTypes.map((t, i) => {return {
|
||||||
|
value: t.weight,
|
||||||
|
name: `${t.name}\n${t.weight}%`,
|
||||||
|
itemStyle:
|
||||||
|
{
|
||||||
|
color: Constants.THEME.colors[i],
|
||||||
|
opacity: 0.8,
|
||||||
|
shadowColor: 'rgba(0,0,0,0.22)',
|
||||||
|
shadowBlur: 10
|
||||||
|
}
|
||||||
|
}}).sort((a, b) => a.value - b.value)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return settings;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<template>
|
||||||
|
<div id="type-pie">
|
||||||
|
<ve-pie height="420px" class="graph" :extend="{a: this.course.name}" :after-config="afterConfig"></ve-pie>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script src="./type-pie.ts" lang="ts"></script>
|
||||||
|
<style lang="scss" scoped></style>
|
||||||
+9
-17
@@ -25,11 +25,13 @@ export default class TypeRadar extends Vue
|
|||||||
*/
|
*/
|
||||||
get chartSettings()
|
get chartSettings()
|
||||||
{
|
{
|
||||||
|
let min = this.course.assignmentTypes.reduce((min, t) => Math.min(min, t.percent), 100);
|
||||||
|
|
||||||
// Create settings
|
// Create settings
|
||||||
let settings =
|
let settings =
|
||||||
{
|
{
|
||||||
...GraphUtils.getBaseSettings('Type Radar',
|
...GraphUtils.getBaseSettings('Assignment Type Radar',
|
||||||
'Assignment type grades for ' + this.course.name),
|
'How are you doing for different types of assignment'),
|
||||||
|
|
||||||
// Radar settings
|
// Radar settings
|
||||||
radar:
|
radar:
|
||||||
@@ -37,18 +39,7 @@ export default class TypeRadar extends Vue
|
|||||||
// shape: 'circle',
|
// shape: 'circle',
|
||||||
name:
|
name:
|
||||||
{
|
{
|
||||||
textStyle:
|
textStyle: GraphUtils.pieTextStyle()
|
||||||
{
|
|
||||||
fontSize: 14,
|
|
||||||
textShadowColor: '#cfcfcf',
|
|
||||||
textShadowBlur: 2,
|
|
||||||
textShadowOffsetX: 1,
|
|
||||||
textShadowOffsetY: 1,
|
|
||||||
color: '#fff',
|
|
||||||
backgroundColor: '#f6f6f6',
|
|
||||||
borderRadius: 3,
|
|
||||||
padding: [3, 5]
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
splitArea:
|
splitArea:
|
||||||
{
|
{
|
||||||
@@ -68,13 +59,14 @@ export default class TypeRadar extends Vue
|
|||||||
indicator: this.course.assignmentTypes.map((t, i) => {return {
|
indicator: this.course.assignmentTypes.map((t, i) => {return {
|
||||||
name: `${t.name}\n${t.percent}%`,
|
name: `${t.name}\n${t.percent}%`,
|
||||||
max: 100,
|
max: 100,
|
||||||
|
min: min - 30,
|
||||||
color: Constants.THEME.colors[i]
|
color: Constants.THEME.colors[i]
|
||||||
}}),
|
}}),
|
||||||
radius: '60%',
|
radius: '60%',
|
||||||
center: ['50%', '60%']
|
center: ['50%', '55%']
|
||||||
},
|
},
|
||||||
|
|
||||||
tooltip: {},
|
tooltip: GraphUtils.tooltipCssShadow(),
|
||||||
|
|
||||||
// Data
|
// Data
|
||||||
series:
|
series:
|
||||||
@@ -90,7 +82,7 @@ export default class TypeRadar extends Vue
|
|||||||
color:
|
color:
|
||||||
{
|
{
|
||||||
type: 'radial',
|
type: 'radial',
|
||||||
x: 0.5, y: 0.6, r: 0.5,
|
x: 0.5, y: 0.55, r: 0.5,
|
||||||
colorStops:
|
colorStops:
|
||||||
[
|
[
|
||||||
{offset: 0, color: '#ffa0a0'},
|
{offset: 0, color: '#ffa0a0'},
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<template>
|
||||||
|
<div id="type-radar">
|
||||||
|
<ve-radar height="420px" class="graph" :extend="{a: this.course.name}" :after-config="afterConfig"></ve-radar>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script src="./type-radar.ts" lang="ts"></script>
|
||||||
|
<style lang="scss" scoped></style>
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div id="course-head" class="course-card-content main vertical-center">
|
<div id="course-head" class="course-card-content main vertical-center" @click="redirect">
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="12" class="course-col-name">
|
<el-col :span="12" class="course-col-name">
|
||||||
<div v-if="clickable" class="course-name clickable" @click="redirect">{{course.name}}</div>
|
<div v-if="clickable" class="course-name clickable" @click="redirect">{{course.name}}</div>
|
||||||
|
|||||||
@@ -44,6 +44,8 @@ export default class OverallLine extends Vue
|
|||||||
// Tooltip
|
// Tooltip
|
||||||
tooltip:
|
tooltip:
|
||||||
{
|
{
|
||||||
|
... GraphUtils.tooltipCssShadow(),
|
||||||
|
|
||||||
trigger: 'axis'
|
trigger: 'axis'
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div id="overall">
|
<div id="overall">
|
||||||
<el-row v-if="getGPA().gpa !== -1">
|
<el-row v-if="getGPA().gpa !== -1">
|
||||||
<el-col :span="4">
|
<el-col :span="4" class="overall-span">
|
||||||
<el-card class="large gpa-card vertical-center">
|
<el-card class="large gpa-card vertical-center" body-style="padding: 0">
|
||||||
<div style="padding: 14px;">
|
<div style="padding: 14px;">
|
||||||
<span class="gpa header">GPA:</span>
|
<span class="gpa header">GPA:</span>
|
||||||
<span class="gpa text">{{getGPA().gpa}}</span>
|
<span class="gpa text">{{getGPA().gpa}}</span>
|
||||||
@@ -13,13 +13,13 @@
|
|||||||
</div>
|
</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="14">
|
<el-col :span="14" class="overall-span">
|
||||||
<el-card class="large overall-line-card vertical-center">
|
<el-card class="large overall-line-card vertical-center" body-style="padding: 0 10px">
|
||||||
<overall-line :courses="courses"></overall-line>
|
<overall-line :courses="courses"></overall-line>
|
||||||
</el-card>
|
</el-card>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="6">
|
<el-col :span="6" class="overall-span">
|
||||||
<el-card class="large overall-bar-card vertical-center">
|
<el-card class="large overall-bar-card vertical-center" body-style="padding: 0 10px">
|
||||||
<overall-bar :courses="courses"></overall-bar>
|
<overall-bar :courses="courses"></overall-bar>
|
||||||
</el-card>
|
</el-card>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
|||||||
Reference in New Issue
Block a user