Changed: DB Params
9
assets/css/colors.css
Normal file
@@ -0,0 +1,9 @@
|
||||
:root {
|
||||
--text-color: #E0E1DD;
|
||||
--text-color-inverted: #1f1e22;
|
||||
--background-color: #0d1b2a;
|
||||
--focused: #f4a260;
|
||||
--unfocused: #2ec4b6;
|
||||
--menu-bg: #1b3857;
|
||||
--menu-border: #668580;
|
||||
}
|
36
assets/css/grid_layout.css
Normal file
@@ -0,0 +1,36 @@
|
||||
.two-split {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 4fr;
|
||||
grid-auto-rows: 75px;
|
||||
}
|
||||
|
||||
.three-split {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 4fr 1fr;
|
||||
grid-auto-rows: 75px;
|
||||
}
|
||||
|
||||
.grid-item-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-left: 10%;
|
||||
justify-content: left;
|
||||
}
|
||||
|
||||
.grid-item-center {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.one-row {
|
||||
grid-template-rows: 1fr;
|
||||
}
|
||||
|
||||
.two-row {
|
||||
grid-template-rows: 1fr 1fr;
|
||||
}
|
||||
|
||||
.three-row {
|
||||
grid-template-rows: 1fr 1fr 1fr;
|
||||
}
|
319
assets/css/style.css
Normal file
@@ -0,0 +1,319 @@
|
||||
@font-face {
|
||||
font-family: "Lato";
|
||||
src:
|
||||
url("/assets/fonts/lato/Lato-BlackItalic.ttf") format("truetype"),
|
||||
url("/assets/fonts/lato/Lato-Black.ttf") format("truetype"),
|
||||
url("/assets/fonts/lato/Lato-BoldItalic.ttf") format("truetype"),
|
||||
url("/assets/fonts/lato/Lato-Bold.ttf") format("truetype"),
|
||||
url("/assets/fonts/lato/Lato-Italic.ttf") format("truetype"),
|
||||
url("/assets/fonts/lato/Lato-LightItalic.ttf") format("truetype"),
|
||||
url("/assets/fonts/lato/Lato-Regular.ttf") format("truetype"),
|
||||
url("/assets/fonts/lato/Lato-ThinItalic.ttf") format("truetype"),
|
||||
url("/assets/fonts/lato/Lato-Thin.ttf") format("truetype");
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
.lato-thin {
|
||||
font-family: "Lato", sans-serif;
|
||||
font-weight: 100;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
.lato-light {
|
||||
font-family: "Lato", sans-serif;
|
||||
font-weight: 300;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
.lato-regular {
|
||||
font-family: "Lato", sans-serif;
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
.lato-bold {
|
||||
font-family: "Lato", sans-serif;
|
||||
font-weight: 700;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
.lato-black {
|
||||
font-family: "Lato", sans-serif;
|
||||
font-weight: 900;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
.lato-thin-italic {
|
||||
font-family: "Lato", sans-serif;
|
||||
font-weight: 100;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.lato-light-italic {
|
||||
font-family: "Lato", sans-serif;
|
||||
font-weight: 300;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.lato-regular-italic {
|
||||
font-family: "Lato", sans-serif;
|
||||
font-weight: 400;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.lato-bold-italic {
|
||||
font-family: "Lato", sans-serif;
|
||||
font-weight: 700;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.lato-black-italic {
|
||||
font-family: "Lato", sans-serif;
|
||||
font-weight: 900;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
* {
|
||||
color: var(--text-color);
|
||||
font-family: lato-regular, sans-serif;
|
||||
box-sizing: inherit;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: var(--background-color);
|
||||
}
|
||||
|
||||
main {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
transform: translate(-50%, 0%);
|
||||
min-height: 110vh;
|
||||
width: 90%;
|
||||
}
|
||||
|
||||
footer {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
background-color: var(--menu-bg);
|
||||
width: 100vw;
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--unfocused);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: var(--focused);
|
||||
}
|
||||
|
||||
button {
|
||||
color: var(--text-color-inverted);
|
||||
background-color: var(--unfocused);
|
||||
text-decoration: none;
|
||||
border: none;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
color: var(--text-color);
|
||||
background-color: var(--focused);
|
||||
}
|
||||
|
||||
.content_container {
|
||||
}
|
||||
|
||||
|
||||
.login {
|
||||
zoom: 150%;
|
||||
position: absolute;
|
||||
top: 35%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 40%;
|
||||
}
|
||||
|
||||
.login h1 {
|
||||
font-size: 30px;
|
||||
text-align: center;
|
||||
margin-top: -20px;
|
||||
margin-bottom: 1%;
|
||||
}
|
||||
|
||||
.login img {
|
||||
position: relative;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
|
||||
.login form {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.login input {
|
||||
text-align: left;
|
||||
font-size: 15px;
|
||||
background-color: var(--background-color);
|
||||
border: none;
|
||||
border-bottom: 2px solid var(--unfocused);
|
||||
transition: border-bottom 0.2s ease-out;
|
||||
}
|
||||
|
||||
.login input:focus {
|
||||
outline: none;
|
||||
border-bottom: 2px solid var(--focused);
|
||||
}
|
||||
|
||||
.login input:required {
|
||||
border-bottom: 2px solid var(--focused);
|
||||
}
|
||||
|
||||
.login input[required]:invalid {
|
||||
border-bottom: 2px solid var(--unfocused);
|
||||
}
|
||||
|
||||
.login input[type=text] {
|
||||
background-image: url("/assets/img/id-card-negated.png");
|
||||
background-position: 5% center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 15px 15px;
|
||||
text-indent: 15%;
|
||||
}
|
||||
|
||||
.login input[type=password] {
|
||||
background-image: url("/assets/img/key-negated.png");
|
||||
background-position: 5% center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 15px 15px;
|
||||
text-indent: 15%;
|
||||
}
|
||||
|
||||
.login input[type=submit] {
|
||||
text-align: center;
|
||||
width: 30%;
|
||||
background-color: var(--background-color);
|
||||
transition: border-bottom 0.2s ease-out;
|
||||
}
|
||||
|
||||
.login input[type=submit]:hover {
|
||||
border-bottom: 2px solid var(--focused);
|
||||
}
|
||||
|
||||
.side_by_side {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.error {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.error h1 {
|
||||
font-size: 300%;
|
||||
}
|
||||
|
||||
.error h2 {
|
||||
font-size: 200%;
|
||||
}
|
||||
|
||||
.error p {
|
||||
font-size: 150%;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.navbar {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.navbar ul {
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
background-color: var(--menu-bg);
|
||||
}
|
||||
|
||||
.navbar li {
|
||||
float: left;
|
||||
border-right: 1px solid var(--menu-border);
|
||||
}
|
||||
|
||||
.navbar li:first-child {
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
.navbar li:last-child {
|
||||
float: right;
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
.navbar img {
|
||||
object-fit: contain;
|
||||
width: 80px;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.navbar a {
|
||||
display: block;
|
||||
padding: 8px;
|
||||
font-size: 130%;
|
||||
text-align: center;
|
||||
color: var(--text-color-inverted);
|
||||
background-color: var(--unfocused);
|
||||
}
|
||||
|
||||
.navbar a:hover {
|
||||
color: var(--text-color);
|
||||
background-color: var(--focused);
|
||||
}
|
||||
|
||||
.usercard {
|
||||
border-radius: 10px;
|
||||
border: 3px solid var(--unfocused);
|
||||
}
|
||||
|
||||
.usercard img {
|
||||
display: block;
|
||||
margin-top: 2%;
|
||||
margin-bottom: 2%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
border-radius: 50%;
|
||||
max-width: 70%;
|
||||
}
|
||||
|
||||
.usercard h1 {
|
||||
margin-top: 0%;
|
||||
text-align: center;
|
||||
font-size: 150%;
|
||||
background-color: var(--unfocused);
|
||||
color: var(--text-color-inverted);
|
||||
}
|
||||
|
||||
.usercard p {
|
||||
font-size: 90%;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.chart {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.button_row {
|
||||
text-align: left;
|
||||
padding-top: 1%;
|
||||
padding-bottom: 1%;
|
||||
}
|
||||
|
||||
.button_row button {
|
||||
font-size: 100%;
|
||||
margin-left: 5%;
|
||||
width: 15%;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
0
assets/fonts/.gitignore
vendored
Normal file
BIN
assets/fonts/lato/Lato-Black.ttf
Normal file
BIN
assets/fonts/lato/Lato-BlackItalic.ttf
Normal file
BIN
assets/fonts/lato/Lato-Bold.ttf
Normal file
BIN
assets/fonts/lato/Lato-BoldItalic.ttf
Normal file
BIN
assets/fonts/lato/Lato-Italic.ttf
Normal file
BIN
assets/fonts/lato/Lato-Light.ttf
Normal file
BIN
assets/fonts/lato/Lato-LightItalic.ttf
Normal file
BIN
assets/fonts/lato/Lato-Regular.ttf
Normal file
BIN
assets/fonts/lato/Lato-Thin.ttf
Normal file
BIN
assets/fonts/lato/Lato-ThinItalic.ttf
Normal file
BIN
assets/fonts/lato/MPLUSRounded1c-Black.ttf
Normal file
BIN
assets/fonts/lato/MPLUSRounded1c-Bold.ttf
Normal file
BIN
assets/fonts/lato/MPLUSRounded1c-ExtraBold.ttf
Normal file
BIN
assets/fonts/lato/MPLUSRounded1c-Light.ttf
Normal file
BIN
assets/fonts/lato/MPLUSRounded1c-Medium.ttf
Normal file
BIN
assets/fonts/lato/MPLUSRounded1c-Regular.ttf
Normal file
BIN
assets/fonts/lato/MPLUSRounded1c-Thin.ttf
Normal file
18
assets/img/failed-exam.svg
Normal file
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg fill="#E0E1DD" version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
width="128px" height="128px" viewBox="0 0 893.4 893.4" xml:space="preserve"
|
||||
>
|
||||
<g>
|
||||
<path d="M747.3,0H146.101c-13.8,0-25,11.2-25,25v700.5H234c30.3,0,55,24.7,55,55v112.9H747.3c13.801,0,25-11.2,25-25V25
|
||||
C772.3,11.2,761.101,0,747.3,0z M636.901,655.6H256.5c-13.8,0-25-11.199-25-25c0-13.8,11.2-25,25-25h380.401
|
||||
c13.799,0,25,11.2,25,25C661.901,644.4,650.7,655.6,636.901,655.6z M636.901,543.5H256.5c-13.8,0-25-11.2-25-25s11.2-25,25-25
|
||||
h380.401c13.799,0,25,11.2,25,25S650.7,543.5,636.901,543.5z M661.901,406.4c0,13.8-11.201,25-25,25H256.5c-13.8,0-25-11.2-25-25
|
||||
l0,0c0-13.801,11.2-25,25-25h380.401C650.7,381.4,661.901,392.6,661.901,406.4L661.901,406.4z M661.901,98.3
|
||||
c0,12.5-10.102,22.6-22.602,22.6l-97.6,1v55.7l81.201-1c12.5,0,22.6,10.1,22.6,22.6l0,0c0,12.5-10.1,22.6-22.6,22.6l-81.201,1v82
|
||||
c0,12.5-10.1,22.6-22.6,22.6h-8.1c-12.5,0-22.6-10.1-22.6-22.6V98.3c0-12.5,10.1-22.6,22.6-22.6H639.3
|
||||
C651.8,75.7,661.901,85.8,661.901,98.3L661.901,98.3z"/>
|
||||
<path d="M234,755.5h-110.9h-2L259,893.4v-0.7V780.5C259,766.7,247.801,755.5,234,755.5z"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.4 KiB |
BIN
assets/img/icon/android-chrome-192x192.png
Normal file
After Width: | Height: | Size: 4.7 KiB |
BIN
assets/img/icon/android-chrome-512x512.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
assets/img/icon/apple-touch-icon.png
Normal file
After Width: | Height: | Size: 4.3 KiB |
BIN
assets/img/icon/favicon-16x16.png
Normal file
After Width: | Height: | Size: 354 B |
BIN
assets/img/icon/favicon-32x32.png
Normal file
After Width: | Height: | Size: 676 B |
BIN
assets/img/icon/favicon.ico
Normal file
After Width: | Height: | Size: 15 KiB |
1
assets/img/icon/site.webmanifest
Normal file
@@ -0,0 +1 @@
|
||||
{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
|
BIN
assets/img/id-card-negated.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
assets/img/id-card.png
Normal file
After Width: | Height: | Size: 2.0 KiB |
BIN
assets/img/key-negated.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
assets/img/key.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
assets/img/learnlytics.png
Normal file
After Width: | Height: | Size: 7.3 KiB |
28
assets/img/learnlytics.svg
Normal file
@@ -0,0 +1,28 @@
|
||||
<svg
|
||||
width="300" height="150" viewBox="0 0 300 150"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none" stroke-linecap="round" stroke-linejoin="round"
|
||||
>
|
||||
<!-- Centering Group -->
|
||||
<g transform="translate(25, 0)">
|
||||
<!-- Bar Chart -->
|
||||
<rect x="0" y="90" width="30" height="30" fill="#2EC4B6" />
|
||||
<rect x="45" y="60" width="30" height="60" fill="#2EC4B6" />
|
||||
<rect x="90" y="80" width="30" height="40" fill="#2EC4B6" />
|
||||
<rect x="135" y="40" width="30" height="80" fill="#2EC4B6" />
|
||||
<rect x="180" y="70" width="30" height="50" fill="#2EC4B6" />
|
||||
<rect x="225" y="30" width="30" height="90" fill="#2EC4B6" />
|
||||
|
||||
<!-- Analytics Chart - Dynamic Graph Lines -->
|
||||
<polyline points="15,90 60,60 105,80 150,40 195,70 240,30" stroke="#F4A261" stroke-width="3" stroke-dasharray="8 4" />
|
||||
<circle cx="15" cy="90" r="5" fill="#F4A261" />
|
||||
<circle cx="60" cy="60" r="5" fill="#F4A261" />
|
||||
<circle cx="105" cy="80" r="5" fill="#F4A261" />
|
||||
<circle cx="150" cy="40" r="5" fill="#F4A261" />
|
||||
<circle cx="195" cy="70" r="5" fill="#F4A261" />
|
||||
<circle cx="240" cy="30" r="5" fill="#F4A261" />
|
||||
|
||||
<!-- Centered Text -->
|
||||
<!-- text x="75" y="140" fill="#E0E1DD" font="lato-regular" font-size="20" font-weight="bold">Learnlytics</text-->
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.3 KiB |
4
assets/img/smiley-x.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
<svg fill="#E0E1DD" width="128px" height="128px" viewBox="0 0 256 256" id="Flat" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M128,28A100,100,0,1,0,228,128,100.11332,100.11332,0,0,0,128,28Zm0,192a92,92,0,1,1,92-92A92.10416,92.10416,0,0,1,128,220ZM186.82812,98.82812,173.65674,112l13.17138,13.17188a3.99957,3.99957,0,1,1-5.65624,5.65624L168,117.65674l-13.17188,13.17138a3.99957,3.99957,0,0,1-5.65624-5.65624L162.34326,112,149.17188,98.82812a3.99957,3.99957,0,0,1,5.65624-5.65624L168,106.34326l13.17188-13.17138a3.99957,3.99957,0,1,1,5.65624,5.65624Zm-80,0L93.65674,112l13.17138,13.17188a3.99957,3.99957,0,1,1-5.65624,5.65624L88,117.65674,74.82812,130.82812a3.99957,3.99957,0,0,1-5.65624-5.65624L82.34326,112,69.17188,98.82812a3.99957,3.99957,0,0,1,5.65624-5.65624L88,106.34326l13.17188-13.17138a3.99957,3.99957,0,0,1,5.65624,5.65624ZM136,180a8,8,0,1,1-8-8A8.00917,8.00917,0,0,1,136,180Z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1017 B |
BIN
assets/img/user.jpeg
Normal file
After Width: | Height: | Size: 352 KiB |
20
assets/js/chart.js
Normal file
293
assets/js/chartUtils.js
Normal file
@@ -0,0 +1,293 @@
|
||||
function barChart(id, data, labels, tooltip, title, scale_label_x, scale_label_y) {
|
||||
const canvas = document.getElementById('bar_chart'+id)
|
||||
const ctx = canvas.getContext("2d");
|
||||
|
||||
data = data.map((item) => DecimalPrecision.round(item, 2));
|
||||
|
||||
// Gradient
|
||||
var gradient = ctx.createLinearGradient(0, 0, 0, 500);
|
||||
gradient.addColorStop(0, '#f4a260');
|
||||
gradient.addColorStop(1, '#2ec4b6');
|
||||
|
||||
// Data
|
||||
var displayData = {
|
||||
labels: labels,
|
||||
datasets: [
|
||||
{
|
||||
label: tooltip,
|
||||
data: data,
|
||||
backgroundColor: gradient,
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
// Options
|
||||
var options = {
|
||||
responsive: true,
|
||||
|
||||
scales: {
|
||||
x: {
|
||||
display: true,
|
||||
text: scale_label_x,
|
||||
},
|
||||
y: {
|
||||
display: true,
|
||||
text: scale_label_y,
|
||||
beginAtZero: true
|
||||
}
|
||||
},
|
||||
|
||||
plugins: {
|
||||
title: {
|
||||
display: true,
|
||||
text: title,
|
||||
font: {
|
||||
size: 20,
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
var config = {
|
||||
type: 'bar',
|
||||
data: displayData,
|
||||
options: options
|
||||
};
|
||||
|
||||
new Chart(ctx, config);
|
||||
}
|
||||
|
||||
function barLineChart(id, data, labels, tooltip, title, scale_label_x, scale_label_y) {
|
||||
const canvas = document.getElementById('bar_line_chart'+id)
|
||||
const ctx = canvas.getContext("2d");
|
||||
|
||||
// Gradient
|
||||
const gradient = ctx.createLinearGradient(0, 0, 0, 500);
|
||||
gradient.addColorStop(0, '#f4a260');
|
||||
gradient.addColorStop(1, '#2ec4b6');
|
||||
|
||||
const sum = data.reduce((partialSum, a) => partialSum + a, 0);
|
||||
const percentage = data.map((item) => DecimalPrecision.round(item/sum*100, 2));
|
||||
var percentageTick = 100;
|
||||
var percentageTickSize = 20;
|
||||
|
||||
// Data
|
||||
const displayData = {
|
||||
labels: labels,
|
||||
datasets: [
|
||||
{
|
||||
label: "Percentage",
|
||||
data: percentage,
|
||||
borderColor: '#E0E1DD',
|
||||
backgroundColor: '#2ec4b6',
|
||||
yAxisID: 'y1',
|
||||
type: 'line',
|
||||
},
|
||||
{
|
||||
label: tooltip,
|
||||
data: data,
|
||||
backgroundColor: gradient,
|
||||
yAxisID: 'y',
|
||||
},
|
||||
|
||||
]
|
||||
};
|
||||
|
||||
// Options
|
||||
const options = {
|
||||
responsive: true,
|
||||
|
||||
scales: {
|
||||
x: {
|
||||
display: true,
|
||||
text: scale_label_x,
|
||||
},
|
||||
y: {
|
||||
display: true,
|
||||
text: scale_label_y,
|
||||
beginAtZero: true,
|
||||
max: Math.max.apply(null, data) + 1,
|
||||
},
|
||||
|
||||
y1: {
|
||||
display: true,
|
||||
position: 'right',
|
||||
beginAtZero: true,
|
||||
max: percentageTick,
|
||||
ticks: {
|
||||
stepSize: percentageTickSize,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
plugins: {
|
||||
title: {
|
||||
display: true,
|
||||
text: title,
|
||||
font: {
|
||||
size: 20,
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
const config = {
|
||||
type: 'bar',
|
||||
data: displayData,
|
||||
options: options
|
||||
};
|
||||
|
||||
let barlinechart = new Chart(ctx, config);
|
||||
|
||||
// Actions
|
||||
const actions = [
|
||||
{
|
||||
name: "Toggle Tick",
|
||||
handler(chart) {
|
||||
if (percentageTick == 100 ) {
|
||||
percentageTick = Math.trunc(Math.max.apply(null, percentage) + 1);
|
||||
percentageTickSize = Math.trunc(percentageTick / 5);
|
||||
}
|
||||
else {
|
||||
percentageTick = 100;
|
||||
percentageTickSize = 20;
|
||||
}
|
||||
barlinechart.options.scales.y1.max = percentageTick;
|
||||
barlinechart.options.scales.y1.ticks.stepSize = percentageTickSize;
|
||||
chart.update();
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
actions.forEach((a, i) => {
|
||||
let button = document.createElement("button");
|
||||
button.id = "button"+i;
|
||||
button.innerText = a.name;
|
||||
button.onclick = () => a.handler(barlinechart);
|
||||
document.querySelector(".button_row").appendChild(button);
|
||||
});
|
||||
}
|
||||
|
||||
function pieChart(id, data, labels, tooltip, title, scale_label_x, scale_label_y) {
|
||||
const canvas = document.getElementById('pie_chart'+id)
|
||||
const ctx = canvas.getContext("2d");
|
||||
|
||||
// Data
|
||||
var displayData = {
|
||||
labels: labels,
|
||||
datasets: [
|
||||
{
|
||||
label: tooltip,
|
||||
data: data,
|
||||
backgroundColor: [
|
||||
'#f4a260',
|
||||
'#e77f7a',
|
||||
'#be6d8e',
|
||||
'#856490',
|
||||
'#4f597b',
|
||||
'#2f4858',
|
||||
],
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
// Options
|
||||
var options = {
|
||||
responsive: true,
|
||||
};
|
||||
|
||||
var config = {
|
||||
type: 'pie',
|
||||
data: displayData,
|
||||
options: options
|
||||
};
|
||||
|
||||
new Chart(ctx, config);
|
||||
}
|
||||
|
||||
function doughnutChart(id, data, labels, tooltip, title, scale_label_x, scale_label_y) {
|
||||
const canvas = document.getElementById('doughnut_chart'+id)
|
||||
const ctx = canvas.getContext("2d");
|
||||
|
||||
// Data
|
||||
var displayData = {
|
||||
labels: labels,
|
||||
datasets: [
|
||||
{
|
||||
label: tooltip,
|
||||
data: data,
|
||||
backgroundColor: [
|
||||
'#f4a260',
|
||||
'#e77f7a',
|
||||
'#be6d8e',
|
||||
'#856490',
|
||||
'#4f597b',
|
||||
'#2f4858',
|
||||
],
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
// Options
|
||||
var options = {
|
||||
responsive: true,
|
||||
};
|
||||
|
||||
var config = {
|
||||
type: 'doughnut',
|
||||
data: displayData,
|
||||
options: options
|
||||
};
|
||||
|
||||
new Chart(ctx, config);
|
||||
}
|
||||
|
||||
function polarChart(id, data, labels, tooltip, title, scale_label_x, scale_label_y) {
|
||||
const canvas = document.getElementById('polar_chart'+id)
|
||||
const ctx = canvas.getContext("2d");
|
||||
|
||||
// Data
|
||||
var displayData = {
|
||||
labels: labels,
|
||||
datasets: [
|
||||
{
|
||||
label: tooltip,
|
||||
data: data,
|
||||
backgroundColor: [
|
||||
'#f4a260',
|
||||
'#e77f7a',
|
||||
'#be6d8e',
|
||||
'#856490',
|
||||
'#4f597b',
|
||||
'#2f4858',
|
||||
],
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
// Options
|
||||
var options = {
|
||||
responsive: true,
|
||||
|
||||
scales: {
|
||||
x: {
|
||||
border: { display: true },
|
||||
grid: {
|
||||
display: false,
|
||||
drawOnChartArea: true,
|
||||
drawTicks: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
var config = {
|
||||
type: 'polarArea',
|
||||
data: displayData,
|
||||
options: config,
|
||||
};
|
||||
|
||||
new Chart(ctx, config);
|
||||
}
|
1
assets/js/htmx.min.js
vendored
Normal file
39
assets/js/utils.js
Normal file
@@ -0,0 +1,39 @@
|
||||
var DecimalPrecision = (function() {
|
||||
if (Math.trunc === undefined) {
|
||||
Math.trunc = function(v) {
|
||||
return v < 0 ? Math.ceil(v) : Math.floor(v);
|
||||
};
|
||||
}
|
||||
var decimalAdjust = function myself(type, num, decimalPlaces) {
|
||||
if (type === 'round' && num < 0)
|
||||
return -myself(type, -num, decimalPlaces);
|
||||
var shift = function(value, exponent) {
|
||||
value = (value + 'e').split('e');
|
||||
return +(value[0] + 'e' + (+value[1] + (exponent || 0)));
|
||||
};
|
||||
var n = shift(num, +decimalPlaces);
|
||||
return shift(Math[type](n), -decimalPlaces);
|
||||
};
|
||||
return {
|
||||
// Decimal round (half away from zero)
|
||||
round: function(num, decimalPlaces) {
|
||||
return decimalAdjust('round', num, decimalPlaces);
|
||||
},
|
||||
// Decimal ceil
|
||||
ceil: function(num, decimalPlaces) {
|
||||
return decimalAdjust('ceil', num, decimalPlaces);
|
||||
},
|
||||
// Decimal floor
|
||||
floor: function(num, decimalPlaces) {
|
||||
return decimalAdjust('floor', num, decimalPlaces);
|
||||
},
|
||||
// Decimal trunc
|
||||
trunc: function(num, decimalPlaces) {
|
||||
return decimalAdjust('trunc', num, decimalPlaces);
|
||||
},
|
||||
// Format using fixed-point notation
|
||||
toFixed: function(num, decimalPlaces) {
|
||||
return decimalAdjust('round', num, decimalPlaces).toFixed(decimalPlaces);
|
||||
}
|
||||
};
|
||||
})();
|
BIN
assets/learnlytics.png
Normal file
After Width: | Height: | Size: 7.9 KiB |