Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Selma styling updates #153

Open
wants to merge 22 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
248 changes: 191 additions & 57 deletions src/contentScripts/other/selma/layout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ const currentView = document.location.pathname
// Regex for extracting Programm name and arguments from a popup Script
// This is used to get the URL which would be opened in a popup
const popupScriptsRegex =
/dl_popUp\("\/scripts\/mgrqispi\.dll\?APPNAME=CampusNet&PRGNAME=(\w+)&ARGUMENTS=([^"]+)"/
/dl_popUp\("\/scripts\/mgrqispi\.dll\?APPNAME=CampusNet&PRGNAME=(\w+)&ARGUMENTS=([^"]+)"/

function scriptToURL (script: string): string {
const matches = script.match(popupScriptsRegex)!
Expand Down Expand Up @@ -85,6 +85,7 @@ namespace Graphing {
export function createSVGGradeDistributionGraph (
values: GradeStat[],
url: string,
ownGrade: number,
width = 200,
height = 100
): string {
Expand All @@ -104,7 +105,22 @@ namespace Graphing {

// Allows styling the failed sections differently
let className = 'passed'
if (grade >= 5.0) className = 'failed'
if (grade >= 5.0) {
if (ownGrade === grade) {
className = 'failedgrade'
} else {
className = 'failed'
}
} else if (grade === ownGrade) {
className = 'grade'
}
if (ownGrade === -1) {
className = 'nograde'
} else if (ownGrade === -10) {
className = 'animate-loading'
}
// 99 are any unhandled grade variants
// add handling as needed

barsSvg += `
<rect
Expand Down Expand Up @@ -209,9 +225,9 @@ Actual logic

// Create a small banner that indicates the user that the site was modified
// It also adds a small toggle to disable the table
async function createCreditsBanner() {
async function createCreditsBanner () {
const { improveSelma: settingEnabled } = await chrome.storage.local.get(['improveSelma'])

const imgUrl = chrome.runtime.getURL('/assets/images/tufast48.png')
const credits = document.createElement('p')

Expand All @@ -222,7 +238,7 @@ async function createCreditsBanner() {
credits.innerHTML = `Table ${settingEnabled ? 'powered by' : 'disabled'}
<img src="${imgUrl}" style="position:relative; right: 2px; height: 0.7lh; top: 0.15lh; padding-left: 0.1lh;">
<a href="https://www.tu-fast.de" target="_blank">TUfast</a>
by <a href="https://github.com/A-K-O-R-A" target="_blank">AKORA</a>
by <a href="https://github.com/A-K-O-R-A" target="_blank">AKORA</a>, <a href="https://github.com/t0mbrn" target="_blank">Tom</a>
`

const disableButton = document.createElement('button')
Expand Down Expand Up @@ -261,11 +277,12 @@ async function createCreditsBanner() {
// Add Credit banner with toggle button
const creditElm = await createCreditsBanner()
document.querySelector('.semesterChoice')!.appendChild(creditElm)

if (!improveSelma) return
eventListener();

eventListener()
})
document.addEventListener('DOMContentLoaded', eventListener, false)
})()

async function eventListener () {
Expand All @@ -286,18 +303,66 @@ async function eventListener () {
applyChanges()
}

// default values for Notenübersicht, when table is null
const NULL_TABLE = [
{
grade: 1,
count: 1
},
{
grade: 1.3,
count: 1
},
{
grade: 1.7,
count: 1
},
{
grade: 2,
count: 1
},
{
grade: 2.3,
count: 1
},
{
grade: 2.7,
count: 1
},
{
grade: 3,
count: 1
},
{
grade: 3.3,
count: 1
},
{
grade: 3.7,
count: 1
},
{
grade: 4,
count: 1
},
{
grade: 5,
count: 1
}
]

function applyChanges () {
if (currentView.startsWith('/APP/EXAMRESULTS/')) {
// Prüfungen > Ergebnisse

// Remove the "gut/befriedigend" section
const headRow = document.querySelector('thead>tr')!
headRow.removeChild(headRow.children.item(3)!)
headRow.children.item(3)!.textContent = 'Notenverteilung'
headRow.removeChild(headRow.children.item(4)!)

const body = document.querySelector('tbody')!
const promises: Promise<{ doc: Document; elm: Element; url: string }>[] =
[]
const promises: Promise<{ doc: Document; elm: Element; url: string; ownGrade: number}>[] =
[]
for (const row of body.children) {
// Remove useless inline styles which set the vertical alignment
for (const col of row.children) col.removeAttribute('style')
Expand All @@ -313,38 +378,70 @@ function applyChanges () {

const url = scriptToURL(scriptContent)

// loading animation
lastCol.innerHTML = Graphing.createSVGGradeDistributionGraph(NULL_TABLE, url, -10)

let ownGradeNum = 0
const gradeElm = row.children.item(2)?.innerHTML.trim()
if (gradeElm?.includes(',')) {
let ownGrade: string
const grade = (gradeElm + '').split(',')
let first = Number(grade[0])
const second = Number(grade[1])
if (second > 70) {
ownGrade = (first++).toString() + '.0'
} else if (second > 30) {
ownGrade = first.toString() + '.7'
} else if (second > 0) {
ownGrade = first.toString() + '.3'
} else {
ownGrade = first.toString() + '.0'
}
ownGradeNum = Number(ownGrade)
} else if (gradeElm?.includes('be')) {
ownGradeNum = 1
} else {
// default exception case, maybe expand as needed
ownGradeNum = -99
}

promises.push(
fetch(url).then(async (s) => {
const parser = new DOMParser()
const doc = parser.parseFromString(await s.text(), 'text/html')

return { doc, elm: lastCol, url }
return { doc, elm: lastCol, url, ownGrade: ownGradeNum }
})
)
}

promises.forEach((p) =>
p.then(({ doc, elm, url }) => {
p.then(({ doc, elm, url, ownGrade }) => {
const tableBody = doc.querySelector('tbody')!
const values = [...tableBody.children].map((tr) => {
const gradeText = tr.children.item(0)!.textContent!.replace(',', '.')
const grade = parseFloat(gradeText)

const countText = tr.children.item(1)!.textContent!
let count: number
if (countText === '---') count = 0
else count = parseInt(countText)

return {
grade,
count
}
})
// .slice(0, -2); // Remove the 5.0 from all lists

// Present the bar chart
const graphSVG = Graphing.createSVGGradeDistributionGraph(values, url)
let graphSVG
if (tableBody === null) {
// No grades available
graphSVG = Graphing.createSVGGradeDistributionGraph(NULL_TABLE, url, -1)
} else {
const values = [...tableBody.children].map((tr) => {
const gradeText = tr.children.item(0)!.textContent!.replace(',', '.')
const grade = parseFloat(gradeText)

const countText = tr.children.item(1)!.textContent!
let count: number
if (countText === '---') count = 0
else count = parseInt(countText)

return {
grade,
count
}
})
graphSVG = Graphing.createSVGGradeDistributionGraph(values, url, ownGrade)
}
elm.innerHTML = graphSVG
}).catch(({ elm, url }) => {
elm.innerHTML = Graphing.createSVGGradeDistributionGraph(NULL_TABLE, url, -1)
})
)

Expand All @@ -360,6 +457,7 @@ function applyChanges () {
// Remove the "bestanden" section
const headRow = document.querySelector('thead>tr')!
headRow.removeChild(headRow.children.item(3)!)
headRow.children.item(3)!.textContent = 'Versuche'

// Add "Notenverteilung" header
{
Expand All @@ -371,8 +469,9 @@ function applyChanges () {

// Create the grade distribution graph
const body = document.querySelector('tbody')!
const promises: Promise<{ doc: Document; elm: Element; url: string }>[] =
[]
const promises: Promise<{ doc: Document; elm: Element; url: string, ownGrade:number }>[] =
[]

for (const row of body.children) {
// Remove useless inline styles which set the vertical alignment
for (const col of row.children) col.removeAttribute('style')
Expand All @@ -392,43 +491,77 @@ function applyChanges () {
// Skip courses wihtout grades
if (scriptElm === null) continue

let ownGradeNum = 0
const gradeElm = row.children.item(2)?.innerHTML.trim()
if (gradeElm?.includes(',')) {
let ownGrade: string
const grade = (gradeElm + '').split(',')
let first = Number(grade[0])
const second = Number(grade[1])
if (second > 7) {
ownGrade = (first++).toString() + '.0'
} else if (second > 3) {
ownGrade = first.toString() + '.7'
} else if (second > 0) {
ownGrade = first.toString() + '.3'
} else {
ownGrade = first.toString() + '.0'
}
ownGradeNum = Number(ownGrade)
} else if (gradeElm?.includes('be')) {
ownGradeNum = 1
} else {
// default exception case, maybe expand as needed
ownGradeNum = -99
}

const scriptContent = scriptElm!.innerHTML

const url = scriptToURL(scriptContent)
// loading animation
lastCol.innerHTML = Graphing.createSVGGradeDistributionGraph(NULL_TABLE, url, -10)

promises.push(
fetch(url).then(async (s) => {
const parser = new DOMParser()
const doc = parser.parseFromString(await s.text(), 'text/html')

return { doc, elm: lastCol, url }
return { doc, elm: lastCol, url, ownGrade: ownGradeNum }
})
)
}

promises.forEach((p) =>
p.then(({ doc, elm, url }) => {
p.then(({ doc, elm, url, ownGrade }) => {
// Parse the grade distributions
const tableBody = doc.querySelector('tbody')!
const values = [...tableBody.children].map((tr) => {
const gradeText = tr.children.item(0)!.textContent!.replace(',', '.')
const grade = parseFloat(gradeText)

const countText = tr.children.item(1)!.textContent!
let count: number
if (countText === '---') count = 0
else count = parseInt(countText)

return {
grade,
count
}
})
let graphSVG
if (tableBody === null) {
// No grades available
graphSVG = Graphing.createSVGGradeDistributionGraph(NULL_TABLE, url, -1)
} else {
const values = [...tableBody.children].map((tr) => {
const gradeText = tr.children.item(0)!.textContent!.replace(',', '.')
const grade = parseFloat(gradeText)

const countText = tr.children.item(1)!.textContent!
let count: number
if (countText === '---') count = 0
else count = parseInt(countText)

return {
grade,
count
}
})
graphSVG = Graphing.createSVGGradeDistributionGraph(values, url, ownGrade)
}
// .slice(0, -2); // Remove the 5.0 from all lists

// Present the bar chart
const graphSVG = Graphing.createSVGGradeDistributionGraph(values, url)
elm.innerHTML = graphSVG
}).catch(({ elm, url }) => {
elm.innerHTML = Graphing.createSVGGradeDistributionGraph(NULL_TABLE, url, -1)
})
)

Expand Down Expand Up @@ -479,7 +612,6 @@ function applyChanges () {
tries.push({ date, grade })

i += 2
continue
}
}

Expand Down Expand Up @@ -539,12 +671,14 @@ function applyChanges () {
''
)
}

// Table head "Prüfungsleistung"
document.querySelector('thead > tr > th#Name')!.textContent = ''
// Table head "Termin"
document.querySelector('thead > tr > th#Date')!.textContent =
'Prüfungsleistung/Termin'
}
// Table head "Prüfungsleistung"
document.querySelector('thead > tr > th#Name')!.textContent = ''
// Table head "Termin"
document.querySelector('thead > tr > th#Date')!.textContent =
'Prüfungsleistung/Termin'
// Append extra bar to head
const headRow = document.querySelector('thead>tr')!
headRow.removeChild(headRow.children.item(3)!)
}
}
Loading