Files
firka-extension/dashboard/dashboard.js
Zan1456 107e20f5c1 .
2025-06-13 13:26:21 +02:00

450 lines
15 KiB
JavaScript

const DashboardUtils = {
formatGradeValue(value) {
const trimmedValue = value?.trim() || '';
if (trimmedValue.toLowerCase() === 'szöveges') {
return 'Sz';
}
return trimmedValue;
},
parseDate(dateStr) {
return dateStr?.trim() || '';
},
formatHungarianDate(dateStr) {
if (!dateStr) return '';
const dateParts = dateStr.trim().split('.');
if (dateParts.length < 3) return dateStr;
const month = parseInt(dateParts[1], 10);
const day = parseInt(dateParts[2], 10);
if (isNaN(month) || month < 1 || month > 12) return dateStr;
if (typeof window.LanguageManager !== 'undefined') {
const monthKeys = [
'months.january', 'months.february', 'months.march', 'months.april',
'months.may', 'months.june', 'months.july', 'months.august',
'months.september', 'months.october', 'months.november', 'months.december'
];
const monthName = window.LanguageManager.t(monthKeys[month - 1]);
return `${monthName} ${day}.`;
}
const monthKeys = [
'months.january', 'months.february', 'months.march', 'months.april', 'months.may', 'months.june',
'months.july', 'months.august', 'months.september', 'months.october', 'months.november', 'months.december'
];
return `${LanguageManager.t(monthKeys[month - 1])} ${day}.`;
}
};
class DashboardDataManager {
constructor() {
this.dashboardData = {
grades: [],
absences: [],
notes: [],
upcomingExams: [],
news: []
};
}
extractGradeData() {
const gradeRows = document.querySelectorAll('#legutobbiErtekelesek tr:not(:first-child)');
this.dashboardData.grades = Array.from(gradeRows).map(row => {
const gradeValue = row.querySelector('span[style*="font-size: 200%"]')?.textContent;
const gradeInfo = row.querySelector('span[style*="float: right"]')?.textContent;
if (!gradeValue || !gradeInfo) return null;
const [fullSubject, date] = gradeInfo.split('\n').map(str => str.trim());
const { subject, type, dateInSubject } = this.parseSubjectInformation(fullSubject);
return {
value: DashboardUtils.formatGradeValue(gradeValue),
subject,
date: DashboardUtils.parseDate(date),
type: type || LanguageManager.t('dashboard.evaluation'),
dateInSubject: dateInSubject || null
};
}).filter(Boolean);
}
parseSubjectInformation(fullSubject) {
const hungarianMonths = ['január', 'február', 'március', 'április', 'május', 'június',
'július', 'augusztus', 'szeptember', 'október', 'november', 'december'];
const monthPattern = hungarianMonths.join('|');
const datePattern = new RegExp(`(${monthPattern})\\s+(\\d{1,2})\\.?$`, 'i');
const dateMatch = fullSubject.match(datePattern);
if (dateMatch) {
const subjectPart = fullSubject.substring(0, dateMatch.index).trim();
const datePart = dateMatch[0].trim();
return {
subject: subjectPart,
type: '',
dateInSubject: datePart
};
}
const months = [
LanguageManager.t('months.january'), LanguageManager.t('months.february'), LanguageManager.t('months.march'),
LanguageManager.t('months.april'), LanguageManager.t('months.may'), LanguageManager.t('months.june'),
LanguageManager.t('months.july'), LanguageManager.t('months.august'), LanguageManager.t('months.september'),
LanguageManager.t('months.october'), LanguageManager.t('months.november'), LanguageManager.t('months.december')
];
const fallbackMonthPattern = new RegExp(months.join('|'), 'i');
const monthMatch = fullSubject.match(fallbackMonthPattern);
if (monthMatch) {
const monthIndex = fullSubject.lastIndexOf(monthMatch[0]);
return {
subject: fullSubject.substring(0, monthIndex).trim(),
type: fullSubject.substring(monthIndex).trim()
};
}
return { subject: fullSubject, type: '' };
}
extractAbsenceData() {
const absenceRows = document.querySelectorAll('#legutobbiMulasztasok tr:not(:first-child)');
this.dashboardData.absences = Array.from(absenceRows).map(row => {
const spans = row.querySelectorAll('span');
if (spans.length < 4) return null;
return {
date: spans[0]?.textContent?.trim() || '',
day: spans[2]?.textContent?.trim() || '',
type: spans[1]?.textContent?.trim() || '',
count: spans[3]?.textContent?.trim() || ''
};
}).filter(Boolean);
}
extractNoteData() {
const noteRows = document.querySelectorAll('#legutobbiFeljegyzesek tr:not(:first-child)');
this.dashboardData.notes = Array.from(noteRows).map(row => {
const spans = row.querySelectorAll('span');
if (spans.length < 3) return null;
return {
title: spans[0]?.textContent?.trim() || '',
author: spans[1]?.textContent?.trim() || '',
date: spans[2]?.textContent?.trim() || ''
};
}).filter(Boolean);
}
extractExamData() {
const examRows = document.querySelectorAll('#legutobbiBejelentettSzamonkeres tr:not(:first-child)');
this.dashboardData.upcomingExams = Array.from(examRows).map(row => {
const spans = row.querySelectorAll('span');
if (spans.length < 4) return null;
return {
date: spans[0]?.textContent?.trim() || '',
subject: spans[1]?.textContent?.trim() || '',
day: spans[2]?.textContent?.trim() || '',
type: spans[3]?.textContent?.trim() || ''
};
}).filter(Boolean);
}
async extractNewsData() {
try {
const timestamp = Date.now();
const apiUrl = `https://${window.location.hostname}/Intezmeny/Faliujsag/GetMoreEntries?startindex=0&range=10&_=${timestamp}`;
const response = await fetch(apiUrl, {
method: 'GET',
credentials: 'include',
headers: {
'Accept': 'application/json, text/javascript, */*; q=0.01',
'X-Requested-With': 'XMLHttpRequest'
}
});
if (!response.ok) {
throw new Error(`API request failed with status: ${response.status}`);
}
const data = await response.json();
if (!data.FaliujsagElemek || !Array.isArray(data.FaliujsagElemek)) {
return;
}
data.FaliujsagElemek.forEach((item, index) => {
let formattedDate = '';
if (item.DatumNap && item.DatumHonap && item.DatumEv) {
formattedDate = `${item.DatumEv}. ${item.DatumHonap} ${item.DatumNap}.`;
} else if (item.Idopont) {
const match = item.Idopont.match(/\/Date\((\d+)\)\//);
if (match) {
const timestamp = parseInt(match[1]);
const date = new Date(timestamp);
formattedDate = date.toLocaleDateString('hu-HU');
}
}
if (!formattedDate) {
formattedDate = new Date().toLocaleDateString('hu-HU');
}
let cleanContent = item.EsemenySzovege || '';
cleanContent = cleanContent.replace(/<[^>]*>/g, '');
cleanContent = cleanContent.replace(/\r\n/g, ' ');
cleanContent = cleanContent.replace(/\s+/g, ' ').trim();
const newsItem = {
title: item.EsemenyCime || `Hír ${index + 1}`,
content: cleanContent || 'Nincs elérhető tartalom',
date: formattedDate,
author: `${item.Nev || 'Ismeretlen'} (${item.Munkakor || 'Ismeretlen'})`
};
this.dashboardData.news.push(newsItem);
});
} catch (error) {
console.error('❌ Error fetching news from API:', error);
}
}
async extractAllData() {
this.extractGradeData();
this.extractAbsenceData();
this.extractNoteData();
this.extractExamData();
await this.extractNewsData();
return this.dashboardData;
}
}
class DashboardRenderer {
constructor(data) {
this.data = {
...data,
schoolInfo: {
name: cookieManager.get(COOKIE_KEYS.SCHOOL_NAME) || DEFAULT_VALUES.SCHOOL,
id: cookieManager.get(COOKIE_KEYS.SCHOOL_CODE) || ''
},
userData: {
name: cookieManager.get(COOKIE_KEYS.USER_NAME) || DEFAULT_VALUES.USER,
time: document.querySelector('.usermenu_timer')?.textContent?.trim() || DEFAULT_VALUES.TIMER
}
};
this.schoolNameFull = `${this.data.schoolInfo.id} - ${this.data.schoolInfo.name}`;
this.shortenedSchoolName = helper.shortenSchoolName(this.schoolNameFull);
}
generateMainContent() {
return `
<main class="kreta-main">
<div class="grid-container">
${this.createGradeCard()}
${this.createAbsenceCard()}
${this.createNoteCard()}
${this.createExamCard()}
${this.createNewsCard()}
</div>
</main>
`;
}
createNewsCard() {
const newsItems = this.data.news.map(news => `
<div class="widget-item news-item">
<div class="widget-row">
<div class="widget-details news-details">
<div class="widget-title news-title">${news.title}</div>
<div class="widget-content news-content">${news.content}</div>
</div>
<div class="widget-meta">
${news.date ? `<div class="widget-date news-date">${news.date}</div>` : ''}
${news.author ? `<div class="widget-author news-author">${news.author}</div>` : ''}
</div>
</div>
</div>
`).join('');
return this.createCard(LanguageManager.t('dashboard.news'), newsItems || LanguageManager.t('dashboard.not_supported'), '/Intezmeny/Faliujsag', LanguageManager.t('dashboard.all_news'));
}
createGradeCard() {
const gradeItems = this.data.grades.map(grade => `
<div class="widget-item grade-item">
<div class="widget-row grade-row">
<div class="grade grade-${grade.value}">${grade.value}</div>
<div class="widget-details grade-details">
<div class="widget-title subject-name">${grade.subject}</div>
<div class="grade-type-with-date">
<div class="widget-subtitle grade-type">${grade.type}</div>
${grade.dateInSubject || grade.date ? `<div class="widget-subtitle grade-date">${grade.dateInSubject || grade.date}</div>` : ''}
</div>
</div>
</div>
</div>
`).join('');
return this.createCard(LanguageManager.t('dashboard.grades'), gradeItems, '/TanuloErtekeles/Osztalyzatok', LanguageManager.t('dashboard.all_grades'));
}
createAbsenceCard() {
const absenceItems = this.data.absences.map(absence => `
<div class="widget-item absence-item">
<div class="widget-row">
<div class="widget-details absence-details">
<div class="widget-title absence-type">${absence.type}</div>
<div class="widget-subtitle absence-date">${absence.date}</div>
</div>
${absence.day ? `<div class="widget-date">${absence.day}</div>` : ''}
</div>
</div>
`).join('');
return this.createCard(LanguageManager.t('dashboard.absences'), absenceItems, '/Hianyzas/Hianyzasok', LanguageManager.t('dashboard.all_absences'));
}
createNoteCard() {
const noteItems = this.data.notes.map(note => `
<div class="widget-item note-item">
<div class="widget-row">
<div class="widget-details note-details">
<div class="widget-title note-title">${note.title}</div>
<div class="widget-subtitle note-date">${note.date}</div>
</div>
${note.author ? `<div class="widget-author note-author">${note.author}</div>` : ''}
</div>
</div>
`).join('');
return this.createCard(LanguageManager.t('dashboard.notes'), noteItems, '/TanuloErtekeles/InformaciokFeljegyzesek', LanguageManager.t('dashboard.all_messages'));
}
createExamCard() {
const examItems = this.data.upcomingExams.map(exam => `
<div class="widget-item exam-item">
<div class="widget-row">
<div class="widget-details exam-details">
<div class="widget-title exam-subject">${exam.subject}</div>
<div class="widget-subtitle exam-type">${exam.type || ''}</div>
</div>
<div class="widget-date exam-date">${DashboardUtils.formatHungarianDate(exam.date)}</div>
</div>
</div>
`).join('');
return this.createCard(LanguageManager.t('dashboard.exams'), examItems, '/Tanulo/TanuloBejelentettSzamonkeresek', LanguageManager.t('dashboard.all_exams'));
}
createCard(title, content, linkHref, linkText) {
return `
<div class="widget-card card">
<div class="widget-header">
<h2 class="widget-card-title">${title}</h2>
</div>
<div class="widget-content card-content">
${content || `<div class="widget-empty">${LanguageManager.t('dashboard.not_supported')}</div>`}
</div>
<div class="widget-footer">
<a href="${linkHref}" class="widget-link more-link">
${linkText}
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="17" viewBox="0 0 16 17" fill="none">
<path d="M11.2997 5.19947L5.64282 5.19947M11.2997 5.19947L11.2997 10.8563M11.2997 5.19947L4.70001 11.7991" stroke="var(--accent-accent)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</a>
</div>
</div>
`;
}
render() {
document.body.innerHTML = `
<div class="kreta-container">
${createTemplate.header()}
${this.generateMainContent()}
</div>
`;
setupUserDropdown();
}
}
class DashboardApplication {
constructor() {
this.init();
}
async init() {
if (!window.location.href.includes('/Intezmeny/Faliujsag')) {
return;
}
while (typeof window.LanguageManager === 'undefined' ||
!window.LanguageManager.t('dashboard.grades') ||
window.LanguageManager.t('dashboard.grades') === 'dashboard.grades') {
await new Promise(resolve => setTimeout(resolve, 50));
}
while (!document.querySelector('.faliujsag-lista, #faliujsagLista')) {
await new Promise(resolve => setTimeout(resolve, 100));
}
let newsItemsFound = false;
let attempts = 0;
const maxAttempts = 50;
while (!newsItemsFound && attempts < maxAttempts) {
const newsContainer = document.querySelector('.faliujsag-lista, #faliujsagLista');
if (newsContainer) {
const possibleSelectors = [
'.nb-item',
'.news-item',
'.faliujsag-item',
'.list-group-item',
'li',
'div[class*="item"]',
'div[class*="news"]'
];
for (const selector of possibleSelectors) {
const items = newsContainer.querySelectorAll(selector);
if (items.length > 0) {
newsItemsFound = true;
break;
}
}
if (!newsItemsFound) {
if (newsContainer.children.length > 0 || newsContainer.textContent.trim().length > 0) {
newsItemsFound = true;
}
}
}
if (!newsItemsFound) {
attempts++;
await new Promise(resolve => setTimeout(resolve, 100));
}
}
try {
const dataManager = new DashboardDataManager();
const dashboardData = await dataManager.extractAllData();
createTemplate.importFonts();
const renderer = new DashboardRenderer(dashboardData);
renderer.render();
} catch (error) {
console.error('Error initializing dashboard:', error);
}
}
}
new DashboardApplication();