Compare commits

...

3 Commits

6 changed files with 180 additions and 12 deletions

13
config.js Normal file
View File

@ -0,0 +1,13 @@
module.exports = {
excelFilename: "DashboardResults.xlsx",
//Selectors for the dashboard page
tableBodySelector: "#QQ_RPT_OIS_TEMP\\$scroll\\$0 tbody",
iframeSelector: 'iframe[title="Hoofdinhoud"]',
//Selectors for the AA-page
uitvouwenSelector: 'input[id="DERIVED_SAA_DPR_SSS_EXPAND_ALL"]',
collapsArrowSelector:'a.PSHYPERLINK.PTCOLLAPSE_ARROW',
excludeFromCollapsingSelector: 'a[title="Sectie samenvouwen AFSTUDEERVEREISTEN BACHELOR GESCHIEDENIS"]',
excludedTitle: 'Sectie samenvouwen AFSTUDEERVEREISTEN BACHELOR GESCHIEDENIS',
}

108
coursesEnrolled.js Normal file
View File

@ -0,0 +1,108 @@
const puppeteer = require('puppeteer');
const IFRAME_SELECTOR = 'iframe[title="Hoofdinhoud"]';
const wait = require("./wait");
const config = require("./config.js");
//Er zijn een aantal helperfuncties die nog verwijderd moeten worden
//zo is de functie van de contentFrame te verwijderen want staat dubbel in evaluatestartpakket.js
//de iframeselector is eveneens van belang om te verwijderen want staat ook dubbel in evaluatestartpakket.js
async function coursesEnrolled(page) {
/*connection to local host
const browser = await puppeteer.connect({
browserURL: "http://localhost:9222", // Connect to the browser's debugging address
});
// Get all open pages (tabs)
const pages = await browser.pages();
console.log(`Found ${pages.length} open pages on the browser.`);
// Interact with the last tab (or any tab of choice)
let page = pages[pages.length - 1]; // Choose the last opened tab
console.log("Current URL:", page.url()); */
let contentFrame= await getContentFrame(page);
const uitvouwenButton = await contentFrame.$(config.uitvouwenSelector);
if (uitvouwenButton) {
await uitvouwenButton.click();
console.log("uitvouwen button clicked");
await wait(2000);
contentFrame= await getContentFrame(page)
}
//logic to collapse all sections except the one with the excluded title
const collapseArrows = await contentFrame.$$(config.collapsArrowSelector);
const excludedArrow = await contentFrame.$(config.excludeFromCollapsingSelector);
const excludedTbody = await excludedArrow.evaluate(el => el.closest('tbody'));
for (const arrow of collapseArrows) {
const isExcluded = await arrow.evaluate((el, excludedTbody) => {
const title = el.getAttribute('title');
const tbody = el.closest('tbody');
return title === 'Sectie samenvouwen AFSTUDEERVEREISTEN BACHELOR GESCHIEDENIS' || tbody === excludedTbody;
}, excludedTbody);
if (!isExcluded) {
const isStillInDOM = await arrow.evaluate(el => document.body.contains(el));
if (isStillInDOM) {
await arrow.click();
await wait(500); // Adjust the wait time as needed
}
}
}
contentFrame= await getContentFrame(page)
const rowData = await contentFrame.$$eval(
'span',
(spans) => {
const uniqueEntries = new Set();
return spans
.filter((span) => span.innerText.trim().includes('Academiejaar'))
.map((span) => {
const tr = span.closest('tr');
if (!tr) return null;
const tds = tr.querySelectorAll('td');
const getInnerHtml = (element) => {
const aElement = element.querySelector('a');
return aElement ? aElement.innerHTML.trim() : element.innerHTML.trim();
};
const studiegidsNummer = tds[0] ? getInnerHtml(tds[0].querySelector('span')) : '';
const opleidingsOnderdeel = tds[1] ? getInnerHtml(tds[1].querySelector('span')) : '';
const studiepunten = tds[2] ? getInnerHtml(tds[2].querySelector('span')) : '';
if (uniqueEntries.has(studiegidsNummer)) return null;
uniqueEntries.add(studiegidsNummer);
return {
studiegidsNummer,
opleidingsOnderdeel,
studiepunten,
};
})
.filter((entry) => entry);
}
);
const totalStudiepunten = sumStudiepunten(rowData);
return {rowData, totalStudiepunten};
}
function sumStudiepunten(rowData) {
return rowData.reduce((total, row) => {
const studiepunten = parseFloat(row.studiepunten) || 0;
return total + studiepunten;
}, 0);
}
async function getContentFrame(page) {
await page.waitForSelector(IFRAME_SELECTOR);
const iframe = await page.$(IFRAME_SELECTOR);
if (!iframe) {
throw new Error("Could not find iframe on the AA-page");
}
console.log("iframe found on AA-page");
return await iframe.contentFrame();
}
module.exports = coursesEnrolled;

View File

@ -2,6 +2,7 @@
open chrome in debug modus
start chrome --remote-debugging-port=9222 --user-data-dir="C:\ChromeDebug"
navigeer naar het dashboard en roep de lijst met startpakket studenten op die relevant zijn voor de test
wees er zeker van dat de tab waarin je moet werken de meest rechtse tab is in de tabbladenbalk
start dan het script
*/
const puppeteer = require("puppeteer");
@ -10,11 +11,14 @@ const fs = require("fs");
const saveResultsToExcel = require("./saveResultsToExcel");
const appendToExcel = require("./appendResultsToExcel");
const wait = require("./wait");
const courseEnrolled = require("./coursesEnrolled");
const parseCourseResults = require('./utils/parseCourseResults');
const config = require("./config.js");
async function iterateOverDashboardTable() {
/*connection to local host */
const browser = await puppeteer.connect({
browserURL: "http://localhost:9222", // Connect to the browser's debugging address
browserURL: "http://localhost:9222"
});
//array to store results for Excel export
@ -31,7 +35,7 @@ async function iterateOverDashboardTable() {
// Select the table body by ID
const iframeElement = await page.waitForSelector(
'iframe[title="Hoofdinhoud"]'
config.iframeSelector
);
const iframe = await iframeElement.contentFrame();
@ -40,11 +44,8 @@ async function iterateOverDashboardTable() {
return;
}
// Select the table body within the iframe
const tableBodySelector = "#QQ_RPT_OIS_TEMP\\$scroll\\$0 tbody";
// Check if the table exists inside the iframe
const tableExists = await iframe.$(tableBodySelector);
const tableExists = await iframe.$(config.tableBodySelector);
if (!tableExists) {
console.log("Table not found inside iframe!");
return;
@ -53,7 +54,7 @@ async function iterateOverDashboardTable() {
// Get all rows within the table body
const links = await iframe.$$(
`${tableBodySelector} tr span[title="AA-rapport"] a`
`${config.tableBodySelector} tr span[title="AA-rapport"] a`
);
console.log(`Found ${links.length} AA-links to process.`);
@ -68,12 +69,12 @@ async function iterateOverDashboardTable() {
console.log(`Processing link ${i + 1}`);
const iframeElement = await page.waitForSelector(
'iframe[title="Hoofdinhoud"]'
config.iframeSelector
);
const iframe = await iframeElement.contentFrame();
const links = await iframe.$$(
`${tableBodySelector} tr span[title="AA-rapport"] a`
`${config.tableBodySelector} tr span[title="AA-rapport"] a`
);
// Get the parent row of the current link
const parentRow = await links[i].evaluateHandle((link) =>
@ -109,6 +110,7 @@ async function iterateOverDashboardTable() {
try {
const evaluationResult = await isStartPakketAvailable(newPage);
const coursesResult = await courseEnrolled(newPage)
//Save results for Excel
result = {
@ -119,8 +121,11 @@ async function iterateOverDashboardTable() {
IsCollapsedKeuze: evaluationResult.isCollapsed_keuze ? "Yes" : "No",
IsCollapsedMain: evaluationResult.isCollapsed_main ? "Yes" : "No",
ContainsVZP: evaluationResult.containsVZP ? "Yes" : "No",
ContainsVZPKeuze: evaluationResult.containsVZP_keuze ? "Yes" : "No"
ContainsVZPKeuze: evaluationResult.containsVZP_keuze ? "Yes" : "No",
coursesResult: parseCourseResults(coursesResult.rowData),
totalStudiepunten: coursesResult.totalStudiepunten
};
console.log("Courses enrolled: ", coursesResult.rowData);
console.log(`Link ${i + 1} processed successfully.`);
} catch (error) {
console.error(`Error processing link ${i + 1}:`, error.message);
@ -143,8 +148,9 @@ async function iterateOverDashboardTable() {
appendToExcel(result, filename);
}
console.log("All links processed.");
saveResultsToExcel(results, "DashboardResults.xlsx");
saveResultsToExcel(results, config.excelFilename);
console.log("Results saved successfully to DashboardResults.xlsx");
}

View File

@ -1,7 +1,28 @@
const xlsx = require("xlsx");
function saveResultsToExcel(data, filename) {
const workbook = xlsx.utils.book_new(); // Create a new workbook
const worksheet = xlsx.utils.json_to_sheet(data); // Convert data to worksheet
const worksheetData = [];
data.forEach(item => {
const courses = item.coursesResult.split('. ').filter(course => course.trim() !== '');
courses.forEach(course => {
worksheetData.push({
LinkNumber: item.LinkNumber,
StudentName: item.StudentName,
StudentID: item.StudentID,
IsCollapsed: item.IsCollapsed,
IsCollapsedKeuze: item.IsCollapsedKeuze,
IsCollapsedMain: item.IsCollapsedMain,
ContainsVZP: item.ContainsVZP,
ContainsVZPKeuze: item.ContainsVZPKeuze,
Course: course.trim(),
TotalStudiepunten: item.totalStudiepunten
});
});
});
const worksheet = xlsx.utils.json_to_sheet(worksheetData); // Convert data to worksheet
xlsx.utils.book_append_sheet(workbook, worksheet, "Results"); // Add worksheet to workbook
// Write workbook to file

7
todo.md Normal file
View File

@ -0,0 +1,7 @@
# TODO
## High Priority
- [ ] adviesrapport geeft geen buizen weer voor het huidige aj. Vakken verschijnen dan ook niet in de functie
coursesenrolled. Hoe oplossen? Rapport deliberatie?
- dit is eig geen probleem voor het begin van het aj wanneer nog geen examenperiode heeft
plaatsgevonden.

View File

@ -0,0 +1,13 @@
const parseCourseResults = (listOfObj) => {
result = listOfObj.map(obj => {
const studiegidsNummer = obj.studiegidsNummer.slice(-10);
return `${studiegidsNummer} ${obj.opleidingsOnderdeel} - ${obj.studiepunten}SP, `;
});
return result.join("\n");
}
module.exports = parseCourseResults;