mirror of
https://github.com/QwIT-Development/firka-extension.git
synced 2026-06-12 03:41:39 +02:00
543 lines
20 KiB
JavaScript
543 lines
20 KiB
JavaScript
(() => {
|
|
// Segédfüggvények
|
|
function convertTimeToMinutes(timeStr) {
|
|
const [hours, minutes] = timeStr.split(':').map(Number);
|
|
return hours * 60 + minutes;
|
|
}
|
|
function getCookie(name) {
|
|
const cookieName = `${name}=`;
|
|
const decodedCookie = decodeURIComponent(document.cookie);
|
|
const cookieArray = decodedCookie.split(';');
|
|
|
|
for(let i = 0; i < cookieArray.length; i++) {
|
|
let cookie = cookieArray[i];
|
|
while (cookie.charAt(0) === ' ') {
|
|
cookie = cookie.substring(1);
|
|
}
|
|
if (cookie.indexOf(cookieName) === 0) {
|
|
return cookie.substring(cookieName.length, cookie.length);
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
function shortenSchoolName(name, maxLength = 50) {
|
|
if (!name) return '';
|
|
if (name.length <= maxLength) return name;
|
|
|
|
const parts = name.split(' - ');
|
|
if (parts.length === 2) {
|
|
const [code, fullName] = parts;
|
|
if (fullName.length > maxLength - code.length - 3) {
|
|
return `${code} - ${fullName.substring(0, maxLength - code.length - 6)}...`;
|
|
}
|
|
}
|
|
return name.substring(0, maxLength - 3) + '...';
|
|
}
|
|
|
|
function showLoadingScreen() {
|
|
const loadingScreen = document.createElement('div');
|
|
loadingScreen.className = 'loading-screen';
|
|
loadingScreen.innerHTML = `
|
|
<img src="https://i.imgur.com/JE3LzRc.gif" alt="Firka" class="loading-logo">
|
|
<div class="loading-text">Betöltés alatt...</div>
|
|
<p class="loading-text2">Kis türelmet!</p>
|
|
`;
|
|
document.body.appendChild(loadingScreen);
|
|
}
|
|
|
|
function hideLoadingScreen() {
|
|
const loadingScreen = document.querySelector('.loading-screen');
|
|
if (loadingScreen) {
|
|
loadingScreen.style.opacity = '0';
|
|
loadingScreen.style.transition = 'opacity 0.3s ease';
|
|
setTimeout(() => loadingScreen.remove(), 300);
|
|
}
|
|
}
|
|
|
|
// DOM elemek várása
|
|
function waitForElement(selector) {
|
|
return new Promise(resolve => {
|
|
if (document.querySelector(selector)) {
|
|
return resolve(document.querySelector(selector));
|
|
}
|
|
|
|
const observer = new MutationObserver(mutations => {
|
|
if (document.querySelector(selector)) {
|
|
observer.disconnect();
|
|
resolve(document.querySelector(selector));
|
|
}
|
|
});
|
|
|
|
observer.observe(document.body, {
|
|
childList: true,
|
|
subtree: true
|
|
});
|
|
});
|
|
}
|
|
|
|
// Órarendi adatok gyűjtése
|
|
async function collectTimetableData() {
|
|
await waitForElement('#Calendar');
|
|
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
|
|
const calendar = document.querySelector('#Calendar');
|
|
const dates = Array.from(document.querySelectorAll('.fc-day-header')).map(header => {
|
|
const fullText = header.textContent.trim();
|
|
// Remove the day name from the beginning and clean up the format
|
|
const dateText = fullText.replace(/^(hétfő|kedd|szerda|csütörtök|péntek)/, '').trim();
|
|
return {
|
|
date: fullText,
|
|
formattedDate: dateText
|
|
};
|
|
});
|
|
// Fix the Thursday issue by ensuring we have all 5 days
|
|
if (dates.length === 4) {
|
|
// Get Wednesday's date parts
|
|
const wedDate = dates[2].formattedDate;
|
|
const [month, day] = wedDate.split(' ');
|
|
const dayNum = parseInt(day.replace('.', ''));
|
|
|
|
// Create Thursday's date
|
|
const thursdayDate = `${month} ${dayNum + 1}.`;
|
|
|
|
dates.splice(3, 0, {
|
|
date: `csütörtök${thursdayDate}`,
|
|
formattedDate: thursdayDate
|
|
});
|
|
}
|
|
// Set week selector based on the current date
|
|
const weekOptions = Array.from(document.querySelectorAll('#Calendar_tanevHetek_listbox li'));
|
|
const currentDate = dates[0]?.formattedDate; // Using Monday's date
|
|
const matchingWeek = weekOptions.find(opt => opt.textContent.includes(currentDate));
|
|
|
|
if (matchingWeek) {
|
|
const kendoCombo = document.querySelector('#Calendar_tanevHetek')?.__kendoWidget;
|
|
if (kendoCombo) {
|
|
const weekIndex = weekOptions.indexOf(matchingWeek);
|
|
kendoCombo.value(weekIndex.toString());
|
|
kendoCombo.trigger('change');
|
|
}
|
|
}
|
|
const timetableData = {
|
|
schoolInfo: {
|
|
name: getCookie('schoolName') || 'Iskola',
|
|
id: getCookie('schoolCode') || ''
|
|
},
|
|
userData: {
|
|
name: getCookie('userName') || 'Felhasználó',
|
|
time: document.querySelector('.usermenu_timer')?.textContent?.trim() || '45:00'
|
|
},
|
|
weekInfo: {
|
|
title: document.querySelector('.fc-center h2')?.textContent?.trim() || 'Hét',
|
|
options: Array.from(document.querySelectorAll('#Calendar_tanevHetek_listbox li'))
|
|
.map((li, i) => ({
|
|
text: li.textContent.trim(),
|
|
value: i.toString(),
|
|
selected: li.classList.contains('k-state-selected')
|
|
}))
|
|
},
|
|
weekDates: dates, // Add the dates to the data object
|
|
lessons: []
|
|
};
|
|
|
|
// Órák adatainak gyűjtése
|
|
document.querySelectorAll('.fc-event').forEach(event => {
|
|
const timeEl = event.querySelector('.fc-time');
|
|
const titleEl = event.querySelector('.fc-title');
|
|
|
|
if (timeEl && titleEl) {
|
|
const [startTime, endTime] = (timeEl.getAttribute('data-full') || timeEl.textContent || '').split(' - ');
|
|
const [fullSubject, teacher, room] = titleEl.innerHTML.split('<br>').map(str => str.trim());
|
|
const subject = fullSubject.split('-')[0].trim();
|
|
|
|
timetableData.lessons.push({
|
|
startTime,
|
|
endTime,
|
|
subject: subject || '',
|
|
teacher: teacher || '',
|
|
room: (room || '').replace(/[()]/g, ''),
|
|
day: event.closest('td').cellIndex - 1,
|
|
isSubstituted: event.querySelector('.fc-bg2') !== null,
|
|
isCancelled: event.classList.contains('fc-textline-through'),
|
|
hasHomework: titleEl.querySelector('.hasCalendarIcon') !== null,
|
|
testInfo: event.getAttribute('data-tooltiptext') || '',
|
|
homeworkDetails: event.getAttribute('data-homework') || ''
|
|
});
|
|
}
|
|
});
|
|
|
|
return timetableData;
|
|
}
|
|
|
|
// Grid generálása
|
|
function generateTimeGrid(lessons, weekDates) {
|
|
const times = [...new Set(lessons.map(l => l.startTime))].sort((a, b) => {
|
|
const timeA = convertTimeToMinutes(a);
|
|
const timeB = convertTimeToMinutes(b);
|
|
return timeA - timeB;
|
|
});
|
|
const days = ['Hétfő', 'Kedd', 'Szerda', 'Csütörtök', 'Péntek'];
|
|
|
|
return `
|
|
<div class="grid-header"></div>
|
|
${days.map((day, index) => `
|
|
<div class="grid-header">
|
|
<span class="day-name">${day}</span>
|
|
<span class="day-date">${weekDates[index]?.formattedDate || ''}</span>
|
|
</div>
|
|
`).join('')}
|
|
${times.map(time => `
|
|
<div class="time-slot">${time}</div>
|
|
${Array(5).fill().map((_, dayIndex) => {
|
|
const dayLessons = lessons.filter(l => l.startTime === time && l.day === dayIndex);
|
|
return `
|
|
<div class="lesson-slot">
|
|
${dayLessons.map(lesson => `
|
|
<div class="lesson-card ${lesson.isSubstituted ? 'substituted' : ''}
|
|
${lesson.isCancelled ? 'cancelled' : ''}
|
|
${lesson.hasHomework ? 'has-homework' : ''}"
|
|
data-lesson='${JSON.stringify(lesson)}'>
|
|
<div class="lesson-subject">${lesson.subject}</div>
|
|
<div class="lesson-teacher">${lesson.teacher}</div>
|
|
<div class="lesson-bottom">
|
|
<div class="lesson-room">${lesson.room}</div>
|
|
<div class="lesson-time">${lesson.isCancelled ? 'Elmarad' : lesson.startTime}</div>
|
|
</div>
|
|
${lesson.hasHomework || lesson.testInfo ? `
|
|
<div class="lesson-indicators">
|
|
${lesson.hasHomework ? `
|
|
<span class="lesson-indicator homework-indicator" title="Házi feladat">
|
|
<span class="material-icons-round">assignment</span>
|
|
</span>
|
|
` : ''}
|
|
${lesson.testInfo ? `
|
|
<span class="lesson-indicator test-indicator" title="Számonkérés">
|
|
<span class="material-icons-round">quiz</span>
|
|
</span>
|
|
` : ''}
|
|
</div>
|
|
` : ''}
|
|
</div>
|
|
`).join('')}
|
|
</div>
|
|
`;
|
|
}).join('')}
|
|
`).join('')}
|
|
`;
|
|
}
|
|
// Óra részletek modal
|
|
function showLessonModal(lesson) {
|
|
const modal = document.createElement('div');
|
|
modal.className = 'lesson-modal';
|
|
modal.innerHTML = `
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h3 class="modal-title">${lesson.subject}</h3>
|
|
<button class="modal-close">
|
|
<span class="material-icons-round">close</span>
|
|
</button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="lesson-details">
|
|
<div class="detail-item">
|
|
<span class="detail-label">Tanár:</span>
|
|
<span class="detail-value">${lesson.teacher}</span>
|
|
</div>
|
|
<div class="detail-item">
|
|
<span class="detail-label">Terem:</span>
|
|
<span class="detail-value">${lesson.room}</span>
|
|
</div>
|
|
<div class="detail-item">
|
|
<span class="detail-label">Időpont:</span>
|
|
<span class="detail-value">${lesson.startTime} - ${lesson.endTime}</span>
|
|
</div>
|
|
${lesson.isSubstituted ? `
|
|
<div class="detail-item">
|
|
<span class="detail-label">Állapot:</span>
|
|
<span class="detail-value"><span class="material-icons-round">sync_alt</span> Helyettesítés</span>
|
|
</div>
|
|
` : ''}
|
|
${lesson.isCancelled ? `
|
|
<div class="detail-item">
|
|
<span class="detail-label">Állapot:</span>
|
|
<span class="detail-value"><span class="material-icons-round">cancel</span> Elmarad</span>
|
|
</div>
|
|
` : ''}
|
|
</div>
|
|
|
|
${lesson.hasHomework ? `
|
|
<div class="modal-section homework-section">
|
|
<h4>
|
|
<span class="material-icons-round">assignment</span>
|
|
Házi feladat
|
|
</h4>
|
|
<div class="homework-content">
|
|
${lesson.homeworkDetails ? `<p>${lesson.homeworkDetails}</p>` : '<p>Van házi feladat</p>'}
|
|
</div>
|
|
</div>
|
|
` : ''}
|
|
${lesson.testInfo ? `
|
|
<div class="modal-section test-section">
|
|
<h4>
|
|
<span class="material-icons-round">quiz</span>
|
|
Számonkérés
|
|
</h4>
|
|
<div class="test-content">
|
|
<p>${lesson.testInfo}</p>
|
|
</div>
|
|
</div>
|
|
` : ''}
|
|
</div>
|
|
</div>
|
|
`;
|
|
|
|
document.body.appendChild(modal);
|
|
|
|
// Modal bezárás
|
|
const closeModal = () => {
|
|
modal.classList.remove('show');
|
|
setTimeout(() => modal.remove(), 300);
|
|
};
|
|
|
|
modal.querySelector('.modal-close').addEventListener('click', closeModal);
|
|
modal.addEventListener('click', (e) => {
|
|
if (e.target === modal) closeModal();
|
|
});
|
|
|
|
// ESC gomb kezelése
|
|
const handleEscape = (e) => {
|
|
if (e.key === 'Escape') {
|
|
closeModal();
|
|
document.removeEventListener('keydown', handleEscape);
|
|
}
|
|
};
|
|
document.addEventListener('keydown', handleEscape);
|
|
|
|
// Animáció
|
|
requestAnimationFrame(() => {
|
|
modal.classList.add('show');
|
|
});
|
|
}
|
|
|
|
// Eseménykezelők beállítása
|
|
function setupEventListeners(data) {
|
|
// Órakártyák
|
|
document.querySelectorAll('.lesson-card').forEach(card => {
|
|
card.addEventListener('click', () => {
|
|
const lessonData = JSON.parse(card.dataset.lesson);
|
|
showLessonModal(lessonData);
|
|
});
|
|
});
|
|
|
|
// Felhasználói menü
|
|
const userBtn = document.querySelector('.user-dropdown-btn');
|
|
const userDropdown = document.querySelector('.user-dropdown');
|
|
|
|
userBtn?.addEventListener('click', (e) => {
|
|
e.stopPropagation();
|
|
userDropdown?.classList.toggle('show');
|
|
});
|
|
|
|
document.addEventListener('click', () => {
|
|
userDropdown?.classList.remove('show');
|
|
});
|
|
|
|
// Hét navigáció
|
|
const prevBtn = document.querySelector('.prev-week');
|
|
const nextBtn = document.querySelector('.next-week');
|
|
const weekSelect = document.querySelector('.week-select');
|
|
|
|
prevBtn?.addEventListener('click', async () => {
|
|
showLoadingScreen();
|
|
const kendoCalendar = document.querySelector('#Calendar')?.__kendoWidget;
|
|
if (kendoCalendar) {
|
|
kendoCalendar.prev();
|
|
await new Promise(resolve => setTimeout(resolve, 500));
|
|
await transformTimetablePage();
|
|
}
|
|
});
|
|
|
|
nextBtn?.addEventListener('click', async () => {
|
|
showLoadingScreen();
|
|
const kendoCalendar = document.querySelector('#Calendar')?.__kendoWidget;
|
|
if (kendoCalendar) {
|
|
kendoCalendar.next();
|
|
await new Promise(resolve => setTimeout(resolve, 500));
|
|
await transformTimetablePage();
|
|
}
|
|
});
|
|
|
|
weekSelect?.addEventListener('change', async function() {
|
|
showLoadingScreen();
|
|
const kendoCombo = document.querySelector('#Calendar_tanevHetek')?.__kendoWidget;
|
|
if (kendoCombo) {
|
|
kendoCombo.value(this.value);
|
|
kendoCombo.trigger('change');
|
|
await new Promise(resolve => setTimeout(resolve, 500));
|
|
await transformTimetablePage();
|
|
}
|
|
});
|
|
|
|
// Kijelentkezés időzítő
|
|
const startTime = parseInt(data.userData.time?.match(/\d+/)?.[0] || "45");
|
|
let timeLeft = startTime * 60;
|
|
|
|
const updateTimer = () => {
|
|
const minutes = Math.floor(timeLeft / 60);
|
|
const seconds = timeLeft % 60;
|
|
const timerEl = document.getElementById('logoutTimer');
|
|
if (timerEl) {
|
|
timerEl.textContent = `${minutes}:${seconds.toString().padStart(2, '0')}`;
|
|
}
|
|
|
|
if (timeLeft <= 0) {
|
|
window.location.href = '/Home/Logout';
|
|
} else {
|
|
timeLeft--;
|
|
}
|
|
};
|
|
|
|
updateTimer();
|
|
setInterval(updateTimer, 1000);
|
|
}
|
|
|
|
// Oldal transzformáció
|
|
async function transformTimetablePage() {
|
|
try {
|
|
showLoadingScreen();
|
|
|
|
const data = await collectTimetableData();
|
|
if (!data) {
|
|
hideLoadingScreen();
|
|
return;
|
|
}
|
|
|
|
const schoolNameFull = `${data.schoolInfo.id} - ${data.schoolInfo.name}`;
|
|
const shortenedSchoolName = shortenSchoolName(schoolNameFull);
|
|
|
|
document.body.innerHTML = `
|
|
<div class="kreta-container">
|
|
<header class="kreta-header">
|
|
<div class="school-info">
|
|
<p class="logo-text">
|
|
<img src="${chrome.runtime.getURL('images/firka_logo.png')}" alt="Firka" class="logo">
|
|
Firka
|
|
</p>
|
|
<div class="school-details" title="${schoolNameFull}">
|
|
${shortenedSchoolName}
|
|
</div>
|
|
</div>
|
|
|
|
<nav class="kreta-nav">
|
|
<div class="nav-links">
|
|
<a href="/Intezmeny/Faliujsag" data-page="dashboard" class="nav-item">
|
|
<img src="${chrome.runtime.getURL('icons/dashboard-inactive.svg')}" alt="Kezdőlap">
|
|
Kezdőlap
|
|
</a>
|
|
<a href="/TanuloErtekeles/Osztalyzatok" data-page="grades" class="nav-item">
|
|
<img src="${chrome.runtime.getURL('icons/grades-inactive.svg')}" alt="Jegyek">
|
|
Jegyek
|
|
</a>
|
|
<a href="/Orarend/InformaciokOrarend" data-page="timetable" class="nav-item active">
|
|
<img src="${chrome.runtime.getURL('icons/timetable-active.svg')}" alt="Órarend">
|
|
Órarend
|
|
</a>
|
|
<a href="/Hianyzas/Hianyzasok" data-page="absences" class="nav-item">
|
|
<img src="${chrome.runtime.getURL('icons/absences-inactive.svg')}" alt="Mulasztások">
|
|
Mulasztások
|
|
</a>
|
|
<a href="/Tanulo/TanuloHaziFeladat" data-page="other" class="nav-item">
|
|
<img src="${chrome.runtime.getURL('icons/others.svg')}" alt="Egyéb">
|
|
Egyéb
|
|
</a>
|
|
</div>
|
|
</nav>
|
|
|
|
<div class="user-profile">
|
|
<button class="user-dropdown-btn">
|
|
<div class="user-info">
|
|
<span class="user-name">${data.userData.name}</span>
|
|
<span class="nav-logout-timer" id="logoutTimer">${data.userData.time}</span>
|
|
</div>
|
|
</button>
|
|
<div class="user-dropdown">
|
|
<a href="/Adminisztracio/Profil" data-page="profile" class="dropdown-item">
|
|
<img src="${chrome.runtime.getURL('icons/profile.svg')}" alt="Profil">
|
|
Profil
|
|
</a>
|
|
<a href="#" class="dropdown-item" id="settingsBtn">
|
|
<img src="${chrome.runtime.getURL('icons/settings.svg')}" alt="Beállítások">
|
|
Beállítások
|
|
</a>
|
|
<a href="/Home/Logout" data-page="logout" class="dropdown-item">
|
|
<img src="${chrome.runtime.getURL('icons/logout.svg')}" alt="Kijelentkezés">
|
|
Kijelentkezés
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</header>
|
|
|
|
<main class="kreta-main">
|
|
<div class="week-controls">
|
|
<button class="week-nav-btn prev-week">
|
|
<span class="material-icons-round">chevron_left</span>
|
|
</button>
|
|
<select class="week-select">
|
|
${data.weekInfo.options.map(opt => `
|
|
<option value="${opt.value}" ${opt.selected ? 'selected' : ''}>
|
|
${opt.text}
|
|
</option>
|
|
`).join('')}
|
|
</select>
|
|
<button class="week-nav-btn next-week">
|
|
<span class="material-icons-round">chevron_right</span>
|
|
</button>
|
|
</div>
|
|
|
|
<div class="timetable-container">
|
|
<div class="timetable-grid">
|
|
${generateTimeGrid(data.lessons, data.weekDates)}
|
|
</div>
|
|
</div>
|
|
</main>
|
|
</div>
|
|
`;
|
|
|
|
// Szükséges fontok hozzáadása
|
|
const links = [
|
|
{ rel: 'preconnect', href: 'https://fonts.googleapis.com' },
|
|
{ rel: 'preconnect', href: 'https://fonts.gstatic.com', crossorigin: true },
|
|
{ rel: 'stylesheet', href: 'https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap' },
|
|
{ rel: 'stylesheet', href: 'https://fonts.googleapis.com/icon?family=Material+Icons+Round' }
|
|
];
|
|
|
|
links.forEach(link => {
|
|
const linkElement = document.createElement('link');
|
|
Object.entries(link).forEach(([key, value]) => {
|
|
linkElement[key] = value;
|
|
});
|
|
document.head.appendChild(linkElement);
|
|
});
|
|
|
|
setupEventListeners(data);
|
|
hideLoadingScreen();
|
|
|
|
} catch (error) {
|
|
console.error('Hiba az oldal átalakítása során:', error);
|
|
hideLoadingScreen();
|
|
}
|
|
}
|
|
|
|
// Beállítások gomb kezelése
|
|
document.getElementById('settingsBtn')?.addEventListener('click', (e) => {
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
const url = chrome.runtime.getURL('settings/index.html');
|
|
window.open(url, '_blank', 'width=400,height=600');
|
|
});
|
|
|
|
if (window.location.href.includes('/Orarend/')) {
|
|
transformTimetablePage();
|
|
}
|
|
})(); |