7 Commits

Author SHA1 Message Date
Zan
ec99a3b5c8 Merge pull request #20 from QwIT-Development/firefox
Firefox
2025-08-06 14:12:35 +02:00
Zan
02ffa23e1a Merge branch 'main' into firefox 2025-08-06 14:12:24 +02:00
Zan1456
d7ea449a1b Minimal fixes 2025-08-06 14:06:00 +02:00
Zan1456
e7ec225e18 Updated chart.js 2025-06-14 09:42:33 +02:00
Zan1456
5a9837e655 . 2025-06-14 09:05:07 +02:00
Zan1456
1a340a1950 fixed week select 2025-06-13 14:50:49 +02:00
Zan1456
6a52c51ece . 2025-06-13 13:59:17 +02:00
15 changed files with 1010 additions and 342 deletions

View File

@@ -1,7 +1,4 @@
async function collectAbsencesData() {
await helper.waitForElement('#HianyzasGrid');
await new Promise(resolve => setTimeout(resolve, 1000));
const basicData = {
schoolInfo: {
name: cookieManager.get('schoolName') || 'Iskola',
@@ -13,35 +10,63 @@ async function collectAbsencesData() {
}
};
const absences = [];
const rows = document.querySelectorAll('#HianyzasGrid .k-grid-content tr');
rows.forEach(row => {
const cells = row.querySelectorAll('td');
if (cells.length >= 9) {
absences.push({
date: cells[1]?.textContent?.trim() || '',
lesson: cells[2]?.textContent?.trim() || '',
subject: cells[3]?.textContent?.trim() || '',
topic: cells[4]?.textContent?.trim() || '',
type: cells[5]?.textContent?.trim() || '',
justified: cells[6]?.textContent?.trim() === 'Igen',
justificationStatus: cells[6]?.textContent?.trim() === 'Igen' ? 'justified' :
cells[6]?.textContent?.trim() === 'Nem' ? 'unjustified' : 'pending',
purposeful: cells[7]?.textContent?.trim() || '',
justificationType: cells[8]?.textContent?.trim() || ''
try {
const currentDomain = window.location.hostname;
const response = await fetch(`https://${currentDomain}/api/HianyzasokApi/GetHianyzasGrid?sort=MulasztasDatum-desc&page=1&pageSize=100&group=&filter=&data=%7B%7D&_=${Date.now()}`, {
method: 'GET',
credentials: 'include',
headers: {
'Accept': 'application/json, text/javascript, */*; q=0.01',
'X-Requested-With': 'XMLHttpRequest'
}
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const apiData = await response.json();
const absences = [];
if (apiData.Data && Array.isArray(apiData.Data)) {
apiData.Data.forEach(item => {
const date = new Date(item.MulasztasDatum);
const formattedDate = `${date.getFullYear()}.${(date.getMonth() + 1).toString().padStart(2, '0')}.${date.getDate().toString().padStart(2, '0')}.`;
let justificationStatus = 'pending';
if (item.Igazolt_BOOL === true) {
justificationStatus = 'justified';
} else if (item.Igazolt_BOOL === false && item.IgazolasTipus !== null) {
justificationStatus = 'unjustified';
}
absences.push({
date: formattedDate,
lesson: item.Oraszam?.toString() || '',
subject: item.Targy || '',
topic: item.Tema || '',
type: item.MulasztasTipus_DNAME || '',
justified: item.Igazolt_BOOL === true,
justificationStatus: justificationStatus,
purposeful: item.TanoraiCeluMulasztas_BNAME || '',
justificationType: item.IgazolasTipus_DNAME || ''
});
});
}
});
const groupedAbsences = {};
absences.forEach(absence => {
if (!groupedAbsences[absence.date]) {
groupedAbsences[absence.date] = [];
}
groupedAbsences[absence.date].push(absence);
});
const groupedAbsences = {};
absences.forEach(absence => {
if (!groupedAbsences[absence.date]) {
groupedAbsences[absence.date] = [];
}
groupedAbsences[absence.date].push(absence);
});
return { basicData, absences, groupedAbsences };
return { basicData, absences, groupedAbsences };
} catch (error) {
console.error('Hiba az API hívás során:', error);
return { basicData, absences: [], groupedAbsences: {} };
}
}
async function transformAbsencesPage() {
@@ -62,7 +87,7 @@ async function transformAbsencesPage() {
<span class="material-icons-round">date_range</span>
${LanguageManager.t('absences.date')}
</label>
<input type="date" id="dateFilter" class="filter-input" disabled>
<input type="date" id="dateFilter" class="filter-input">
</div>
<div class="filter-group">
<label>
@@ -156,47 +181,43 @@ function setupFilters() {
return;
}
if (filters.dateFilter) {
filters.dateFilter.disabled = true;
}
const filterAbsences = () => {
try {
const dateFilterValue = filters.dateFilter.value;
const subject = filters.subject.value;
const justified = filters.justified.value;
const selectedDate = dateFilterValue ? new Date(dateFilterValue) : null;
document.querySelectorAll('.absence-group').forEach(group => {
const dateStr = group.dataset.date;
const dateParts = dateStr.split('.');
if (dateParts.length < 3) {
console.error(`Invalid date format: ${dateStr}`);
return;
}
const parsedDay = parseInt(dateParts[0].trim(), 10);
const parsedYear = parseInt(dateParts[0].trim(), 10);
const parsedMonth = parseInt(dateParts[1].trim(), 10) - 1;
const parsedYear = parseInt(dateParts[2].trim(), 10);
const parsedDay = parseInt(dateParts[2].trim(), 10);
if (isNaN(parsedDay) || isNaN(parsedMonth) || isNaN(parsedYear)) {
console.error(`Invalid date components: ${dateStr}`);
return;
}
const groupDate = new Date(parsedYear, parsedMonth, parsedDay);
let showGroup = true;
if (selectedDate) {
if (groupDate.getFullYear() !== selectedDate.getFullYear() ||
groupDate.getMonth() !== selectedDate.getMonth() ||
groupDate.getDate() !== selectedDate.getDate()) {
showGroup = false;
}
}
const absenceItems = group.querySelectorAll('.absence-item');
let visibleItems = 0;
@@ -225,7 +246,7 @@ function setupFilters() {
Object.values(filters).forEach(filter => {
try {
if (filter && filter !== filters.dateFilter) {
if (filter) {
filter.addEventListener('change', filterAbsences);
}
} catch (err) {

View File

@@ -101,7 +101,6 @@ h2 {
transition: transform 0.2s ease, box-shadow 0.2s ease;
border: none;
background: var(--card-card);
box-shadow: 0px 1px var(--shadow-blur, 2px) 0px var(--accent-shadow);
display: flex;
flex-direction: column;
padding: 8px;
@@ -109,11 +108,6 @@ h2 {
min-height: 80px;
}
.widget-item:hover {
transform: translateY(-2px);
box-shadow: 0px 2px calc(var(--shadow-blur, 2px) * 2) 0px var(--accent-shadow);
}
.widget-row {
display: flex;
align-items: flex-start;

View File

@@ -375,6 +375,7 @@ class DashboardRenderer {
</div>
`;
setupUserDropdown();
setupMobileNavigation();
}
}

View File

@@ -7,9 +7,9 @@
body {
margin: 0;
padding: 0;
color: var(--primary);
background-color: var(--bg) !important;
font-family: "Montserrat", serif !important;
color: var(--text-primary);
background-color: var(--background) !important;
font-family: "Montserrat", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif !important;
min-height: 100vh;
font-size: 16px;
display: flex;
@@ -18,12 +18,64 @@ body {
}
.forgot-container {
width: 100%;
width: 90%;
max-width: 500px;
padding: 20px;
margin: 0 auto;
}
.forgot-card {
background: var(--card-card);
padding: 24px;
margin-bottom: 16px;
border-radius: 24px;
box-shadow: 0px 1px var(--shadow-blur) 0px var(--accent-shadow);
}
.forgot-header {
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
margin: 16px 0;
background: var(--card-card) !important;
border-bottom: 1px solid rgba(0, 0, 0, 0) !important;
}
.logo-text {
color: var(--text-primary);
text-align: center;
font-family: Montserrat;
font-size: 20px;
font-style: normal;
font-weight: 700;
line-height: normal;
display: flex;
align-items: center;
justify-content: center;
gap: 12px;
}
.logo {
width: 48px;
height: 48px;
border-radius: 12px;
}
.forgot-title {
color: var(--text-primary);
text-align: center;
font-family: Montserrat;
font-size: 24px;
font-style: normal;
font-weight: 700;
line-height: normal;
margin-bottom: 24px;
}
.forgot-form {
width: 100%;
=======
.forgot-header {
text-align: center;
margin-bottom: 24px;
@@ -66,74 +118,45 @@ body {
.form-label {
display: block;
color: var(--secondary);
font-size: 14px;
margin-bottom: 8px;
color: var(--text-primary);
font-family: Montserrat;
font-size: 14px;
font-weight: 600;
}
.form-control {
width: 100%;
padding: 12px 16px;
border: 2px solid transparent;
display: flex;
height: 48px;
padding: 0px 14px;
align-items: center;
gap: 10px;
align-self: stretch;
border-radius: 12px;
background: var(--accent-15) !important;
border: 0px solid var(--accent-15) !important;
color: var(--text-primary) !important;
width: 100%;
font-size: 16px;
font-family: "Montserrat", serif;
background: var(--cardsec);
color: var(--primary);
transition: all 0.2s ease;
transition: border-color 0.2s ease;
}
.form-control:focus {
outline: none;
border-color: var(--accent);
border-color: var(--accent-accent) !important;
}
.form-control::placeholder {
color: var(--secondary);
color: var(--text-secondary) !important;
}
.form-actions {
margin-top: 24px;
display: flex;
justify-content: space-between;
align-items: center;
}
.help-link {
color: var(--accent);
text-decoration: none;
font-size: 14px;
transition: color 0.2s ease;
}
.help-link:hover {
color: var(--tertiary);
}
.btn-submit {
padding: 12px 24px;
background: var(--accent);
color: white;
border: none;
border-radius: 12px;
font-size: 16px;
font-weight: 600;
font-family: "Montserrat", serif;
cursor: pointer;
transition: background 0.2s ease;
}
.btn-submit:hover {
background: var(--tertiary);
}
.btn-submit:disabled {
opacity: 0.7;
cursor: not-allowed;
.form-control.error {
border-color: var(--error-accent) !important;
background: var(--error-card) !important;
}
.error-message {
color: var(--error);
color: var(--error-text);
font-size: 14px;
margin-top: 4px;
display: none;
@@ -142,12 +165,73 @@ body {
.error-message.show {
display: block;
animation: fadeIn 0.2s ease;
border-color: var(--accent);
}
.g-recaptcha {
.form-actions {
margin-top: 24px;
display: flex;
justify-content: center;
flex-direction: column;
gap: 16px;
}
.help-link {
color: var(--text-primary);
font-size: 14px;
font-weight: 500;
text-decoration: none;
transition: color 0.2s ease;
text-align: center;
}
.help-link:hover {
color: var(--text-teritary);
}
.btn-submit {
width: 100%;
padding: 12px;
background: var(--accent-accent);
color: white;
border: none;
border-radius: 12px;
font-size: 16px;
font-weight: 600;
font-family: "Montserrat", serif;
cursor: pointer;
transition: background 0.2s ease;
position: relative;
}
.btn-submit:hover {
background: var(--text-teritary);
}
.btn-submit:disabled {
opacity: 0.7;
cursor: not-allowed;
}
.message {
padding: 12px 16px;
border-radius: 12px;
margin-bottom: 16px;
font-size: 14px;
font-weight: 500;
animation: fadeIn 0.3s ease;
text-align: center;
}
.message.success {
background: var(--success-card);
color: var(--success-text);
border: 1px solid var(--success-accent);
}
.message.error {
background: var(--error-card);
color: var(--error-text);
border: 1px solid var(--error-accent);
}
@keyframes fadeIn {
@@ -155,6 +239,42 @@ body {
to { opacity: 1; transform: translateY(0); }
}
@media (max-width: 480px) {
.forgot-container {
padding: 16px;
}
.forgot-card {
padding: 20px;
}
.forgot-header {
margin-bottom: 20px;
}
.logo-text {
font-size: 18px;
}
.forgot-title {
font-size: 20px;
}
.form-control {
height: 44px;
font-size: 14px;
}
.btn-submit {
padding: 10px;
font-size: 14px;
}
.help-link {
font-size: 12px;
}
}
@media (max-width: 600px) {
.forgot-container {
padding: 16px;
@@ -169,8 +289,4 @@ body {
gap: 16px;
align-items: stretch;
}
.btn-submit {
width: 100%;
}
}

View File

@@ -1,64 +1,169 @@
(() => {
const transformForgotPasswordPage = () => {
const isDarkMode = localStorage.getItem('darkMode') === 'true';
document.documentElement.setAttribute('data-theme', isDarkMode ? 'dark' : 'light');
const renderRecaptcha = () => {
const container = document.getElementById('recaptcha-container');
if (container && typeof grecaptcha !== 'undefined' && grecaptcha.render) {
try {
grecaptcha.render('recaptcha-container', {
'sitekey': '6LfKURIqAAAAAD5bF2evQ-_Sf6MRrOkUEBwb_mMy',
'theme': 'light'
});
} catch (error) {
console.error('Error rendering reCAPTCHA:', error);
}
}
};
const loadDependencies = async () => {
if (typeof cookieManager === 'undefined') {
const cookieScript = document.createElement('script');
cookieScript.src = chrome.runtime.getURL('tools/cookieManager.js');
document.head.appendChild(cookieScript);
chrome.runtime.onMessage.addListener((message) => {
if (message.action === 'toggleTheme') {
document.documentElement.setAttribute('data-theme', message.darkMode ? 'dark' : 'light');
localStorage.setItem('darkMode', message.darkMode);
}
await new Promise(resolve => {
cookieScript.onload = resolve;
});
}
if (typeof LanguageManager === 'undefined') {
const langScript = document.createElement('script');
langScript.src = chrome.runtime.getURL('global/language.js');
document.head.appendChild(langScript);
document.body.innerHTML = `
<div class="forgot-container">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons+Round" rel="stylesheet">
await new Promise(resolve => {
langScript.onload = resolve;
});
await new Promise(resolve => setTimeout(resolve, 100));
}
if (!document.querySelector('script[src*="recaptcha"]')) {
await new Promise((resolve) => {
window.onRecaptchaLoad = resolve;
const script = document.createElement('script');
script.src = 'https://www.google.com/recaptcha/api.js?hl=hu&onload=onRecaptchaLoad&render=explicit';
document.head.appendChild(script);
});
}
};
const createPageStructure = () => {
document.body.innerHTML = `
<div class="forgot-container">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons+Round" rel="stylesheet">
<style>
.g-recaptcha {
margin-top: 5px;
display: flex;
justify-content: center;
}
</style>
<div class="forgot-card">
<header class="forgot-header">
<p class="logo-text">
<img src="${chrome.runtime.getURL('images/firka_logo.png')}" alt="Firka" class="logo">
Firka
</p>
</header>
<div class="forgot-card">
<h1 class="forgot-title">${LanguageManager.t('forgotpassword.title')}</h1>
<form id="forgotForm" novalidate>
<div class="form-group">
<label class="form-label" for="username">${LanguageManager.t('forgotpassword.om_id_label')}</label>
<input type="text" id="username" name="username" class="form-control"
placeholder="${LanguageManager.t('forgotpassword.om_id_placeholder')}" required>
<div class="error-message">${LanguageManager.t('forgotpassword.om_id_required')}</div>
</div>
<div class="form-group">
<label class="form-label" for="email">${LanguageManager.t('forgotpassword.email_label')}</label>
<input type="email" id="email" name="email" class="form-control"
placeholder="${LanguageManager.t('forgotpassword.email_placeholder')}" required>
<div class="error-message">${LanguageManager.t('forgotpassword.email_required')}</div>
</div>
<div class="g-recaptcha" data-sitekey="6LcmPB8dAAAAACJPQBj7WfpBoBsEfyibZeIG5Vbl"></div>
<div class="form-actions">
<a href="/Adminisztracio/Login" class="help-link">
${LanguageManager.t('forgotpassword.back_to_login')}
</a>
<button type="submit" class="btn-submit">
${LanguageManager.t('forgotpassword.reset_button')}
</button>
</div>
</form>
</div>
<h1 class="forgot-title" data-i18n="forgotpassword.title">Elfelejtett jelszó</h1>
<form id="forgotForm" novalidate>
<div class="form-group">
<label class="form-label" for="BejelentkezesiNev" data-i18n="forgotpassword.om_id_label">OM azonosító</label>
<input type="text" id="BejelentkezesiNev" name="BejelentkezesiNev" class="form-control"
data-i18n-attr="placeholder" data-i18n="forgotpassword.om_id_placeholder"
placeholder="Adja meg az OM azonosítóját" required>
<div class="error-message" data-i18n="forgotpassword.om_id_required">Az OM azonosító megadása kötelező</div>
</div>
<div class="form-group">
<label class="form-label" for="EmailCim" data-i18n="forgotpassword.email_label">E-mail cím</label>
<input type="email" id="EmailCim" name="EmailCim" class="form-control"
data-i18n-attr="placeholder" data-i18n="forgotpassword.email_placeholder"
placeholder="Adja meg az e-mail címét" required>
<div class="error-message" data-i18n="forgotpassword.email_required">Az e-mail cím megadása kötelező</div>
</div>
<div id="recaptcha-container"></div>
<div class="form-actions">
<a href="/Adminisztracio/Login" class="help-link" data-i18n="forgotpassword.back_to_login">
Vissza a bejelentkezéshez
</a>
<button type="submit" class="btn-submit" data-i18n="forgotpassword.reset_button">
Jelszó visszaállítása
</button>
</div>
</form>
</div>
`;
setupFormValidation();
</div>
`;
};
const transformForgotPasswordPage = async () => {
await loadDependencies();
const isDarkMode = localStorage.getItem('darkMode') === 'true';
document.documentElement.setAttribute('data-theme', isDarkMode ? 'dark' : 'light');
chrome.runtime.onMessage.addListener((message) => {
if (message.action === 'toggleTheme') {
document.documentElement.setAttribute('data-theme', message.darkMode ? 'dark' : 'light');
localStorage.setItem('darkMode', message.darkMode);
}
});
createPageStructure();
let attempts = 0;
const maxAttempts = 50;
const waitForLanguageManager = () => {
return new Promise((resolve) => {
const checkLanguageManager = () => {
attempts++;
if (typeof LanguageManager !== 'undefined' && LanguageManager.t) {
setTimeout(resolve, 200);
} else if (attempts < maxAttempts) {
setTimeout(checkLanguageManager, 100);
} else {
console.warn('LanguageManager not available, using fallback texts');
resolve();
}
};
checkLanguageManager();
});
};
await waitForLanguageManager();
if (typeof LanguageManager !== 'undefined' && LanguageManager.t) {
const elements = document.querySelectorAll('[data-i18n]');
elements.forEach(element => {
const key = element.getAttribute('data-i18n');
const translation = LanguageManager.t(key);
if (translation && translation !== key) {
const attr = element.getAttribute('data-i18n-attr');
if (attr) {
element.setAttribute(attr, translation);
} else {
element.textContent = translation;
}
}
});
}
setTimeout(() => {
renderRecaptcha();
}, 500);
setupFormValidation();
};
const setupFormValidation = () => {
const form = document.getElementById('forgotForm');
@@ -94,6 +199,31 @@
return isValid;
};
const showMessage = (message, isError = false) => {
const existingMessage = document.querySelector('.message');
if (existingMessage) {
existingMessage.remove();
}
const messageDiv = document.createElement('div');
messageDiv.className = `message ${isError ? 'error' : 'success'}`;
messageDiv.textContent = message;
const form = document.getElementById('forgotForm');
form.insertBefore(messageDiv, form.firstChild);
setTimeout(() => {
if (messageDiv.parentNode) {
messageDiv.remove();
}
}, 5000);
};
const validateEmail = (email) => {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
};
const handleSubmit = async (event) => {
event.preventDefault();
@@ -106,16 +236,46 @@
isValid = false;
}
});
const emailInput = form.querySelector('#EmailCim');
if (emailInput.value && !validateEmail(emailInput.value)) {
emailInput.classList.add('error');
const errorElement = emailInput.nextElementSibling;
if (errorElement) {
errorElement.textContent = LanguageManager.t('forgotpassword.invalid_email');
errorElement.classList.add('show');
}
isValid = false;
}
let recaptchaResponse = '';
if (typeof grecaptcha !== 'undefined') {
recaptchaResponse = grecaptcha.getResponse();
if (!recaptchaResponse) {
showMessage(LanguageManager.t('forgotpassword.recaptcha_required'), true);
isValid = false;
}
} else {
showMessage('reCAPTCHA nem töltődött be. Kérjük, frissítse az oldalt!', true);
isValid = false;
}
if (!isValid) {
return;
}
const submitButton = form.querySelector('.btn-submit');
const originalText = submitButton.textContent;
submitButton.disabled = true;
submitButton.textContent = LanguageManager.t('loading.text') || 'Küldés...';
try {
const formData = new FormData(form);
if (typeof grecaptcha !== 'undefined') {
formData.append('ReCaptcha', grecaptcha.getResponse());
}
const response = await fetch('/Adminisztracio/ElfelejtettJelszo/LinkKuldes', {
method: 'POST',
body: formData,
@@ -123,25 +283,46 @@
'X-Requested-With': 'XMLHttpRequest'
}
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const result = await response.json();
if (result.Success) {
window.location.href = '/Adminisztracio/Login';
showMessage(LanguageManager.t('forgotpassword.success_message'));
form.reset();
if (typeof grecaptcha !== 'undefined') {
grecaptcha.reset();
}
setTimeout(() => {
window.location.href = '/Adminisztracio/Login';
}, 3000);
} else {
alert(result.Message || LanguageManager.t('forgotpassword.error_message'));
grecaptcha.reset();
showMessage(result.Message || LanguageManager.t('forgotpassword.error_message'), true);
if (typeof grecaptcha !== 'undefined') {
grecaptcha.reset();
}
}
} catch (error) {
//alert('Hiba történt a jelszó visszaállítása során.');
grecaptcha.reset();
console.error('Password reset error:', error);
showMessage(LanguageManager.t('forgotpassword.error_message'), true);
if (typeof grecaptcha !== 'undefined') {
grecaptcha.reset();
}
} finally {
submitButton.disabled = false;
submitButton.textContent = originalText;
}
};
if (window.location.href.includes('/Adminisztracio/ElfelejtettJelszo')) {
transformForgotPasswordPage();
transformForgotPasswordPage().catch(console.error);
}
})();

File diff suppressed because one or more lines are too long

View File

@@ -20,7 +20,7 @@ body {
}
.grades-chart {
width: 100%;
height: 250px;
height: 320px;
margin-bottom: 1.5rem;
padding: 1rem;
display: flex;
@@ -33,7 +33,6 @@ body {
border-radius: 24px;
box-shadow: 0px 1px var(--shadow-blur) 0px var(--accent-shadow);
width: 100%;
max-width: calc(995px + 50px);
}
.average-details {
display: flex;
@@ -531,7 +530,6 @@ body {
.grades-overview {
display: grid;
grid-template-columns: 1fr auto;
gap: 1.5rem;
margin-bottom: 2rem;
align-items: stretch;
overflow-y: auto;
@@ -618,6 +616,109 @@ body {
color: var(--grades-5);
}
.year-end-grades {
width: 300px;
height: 400px;
padding: 1.5rem;
background: var(--card-card);
border-radius: 24px;
box-shadow: 0px 1px var(--shadow-blur) 0px var(--accent-shadow);
display: flex;
flex-direction: column;
}
.year-end-grades h3 {
padding: 1rem;
margin-bottom: 0px !important;
margin-top: 0px !important;
color: var(--text-primary);
font-family: Montserrat;
font-size: 16px;
font-style: normal;
font-weight: 600;
line-height: normal;
}
.year-end-grade-item {
display: grid;
grid-template-columns: auto 1fr auto;
gap: 1rem;
padding: 1rem;
border-radius: 12px;
align-items: center;
}
.year-end-grade-item:hover {
background: var(--button-secondaryFill);
}
.year-end-grades-list {
display: flex;
flex-direction: column;
gap: 1rem;
overflow-y: auto;
padding-right: 0.5rem;
flex: 1;
margin: -0.5rem 0;
}
.year-end-grade-subject {
overflow: hidden;
color: var(--text-primary);
text-overflow: ellipsis;
font-family: Figtree;
font-size: 16px;
font-style: normal;
font-weight: 600;
line-height: 130%;
}
.year-end-grade-value {
width: 32px;
height: 32px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 16px;
font-weight: 700;
font-size: 22px;
}
.year-end-grade-item.grade-1 .year-end-grade-value {
background-color: var(--grades-background-1);
color: var(--grades-1);
}
.year-end-grade-item.grade-2 .year-end-grade-value {
background-color: var(--grades-background-2);
color: var(--grades-2);
}
.year-end-grade-item.grade-3 .year-end-grade-value {
background-color: var(--grades-background-3);
color: var(--grades-3);
}
.year-end-grade-item.grade-4 .year-end-grade-value {
background-color: var(--grades-background-4);
color: var(--grades-4);
}
.year-end-grade-item.grade-5 .year-end-grade-value {
background-color: var(--grades-background-5);
color: var(--grades-5);
}
.year-end-grade {
border: 2px solid var(--accent-primary) !important;
box-shadow: 0 0 0 2px rgba(var(--accent-primary-rgb), 0.2) !important;
}
.year-end-grade::before {
content: "É";
position: absolute;
top: -8px;
right: -8px;
background: var(--accent-primary);
color: white;
border-radius: 50%;
width: 16px;
height: 16px;
font-size: 10px;
font-weight: bold;
display: flex;
align-items: center;
justify-content: center;
}
@media (max-width: 1200px) {
.chart-header {
flex-direction: column;
@@ -650,6 +751,12 @@ body {
height: auto;
max-height: 400px;
}
.year-end-grades {
width: 100%;
height: auto;
max-height: 400px;
}
.overall-averages {
width: 100%;
@@ -658,7 +765,7 @@ body {
@media (max-width: 768px) {
.grades-chart {
height: 200px;
height: 250px;
padding: 0.75rem;
margin-bottom: 1rem;
}
@@ -727,6 +834,32 @@ body {
font-size: 14px;
}
.year-end-grades {
padding: 1rem;
width: 100%;
min-width: 0;
}
.year-end-grades h3 {
padding: 0.5rem;
font-size: 14px;
}
.year-end-grade-item {
padding: 0.75rem;
gap: 0.75rem;
}
.year-end-grade-value {
width: 28px;
height: 28px;
font-size: 18px;
}
.year-end-grade-subject {
font-size: 14px;
}
.overall-averages {
padding: 1rem;
overflow-x: auto;
@@ -746,7 +879,6 @@ body {
}
.chart-averages {
align-self: center;
gap: 0.25rem;
}
@@ -769,6 +901,10 @@ body {
padding: 0.75rem;
}
.year-end-grades {
padding: 0.75rem;
}
.overall-averages {
padding: 0.75rem;
}

View File

@@ -1,13 +1,15 @@
(() => {
async function transformGradesPage() {
try {
await helper.waitForElement('#Osztalyzatok_7895TanuloErtekelesByTanuloGrid');
await new Promise(resolve => setTimeout(resolve, 1000));
const gradesData = extractGradesData();
const tanuloIdElement = document.querySelector('#TanuloId');
const tanuloId = tanuloIdElement ? tanuloIdElement.value : '772481';
const gradesData = await fetchGradesFromAPI(tanuloId);
const studentAverage = calculateOverallAverage(gradesData.subjects);
const classAverage = calculateOverallClassAverage(gradesData.subjects);
window.currentGradesData = gradesData;
document.body.innerHTML = generatePageHTML(gradesData, studentAverage, classAverage);
createTemplate.importFonts();
@@ -27,11 +29,137 @@
loadingScreen.hide();
} catch (error) {
console.error('Error loading grades:', error);
loadingScreen.hide();
}
}
function extractGradesData() {
async function fetchGradesFromAPI(tanuloId) {
try {
const currentDomain = window.location.origin;
const apiUrl = `${currentDomain}/api/TanuloErtekelesByTanuloApi/GetTanuloErtekelesByTanuloGridTanuloView?sort=&group=&filter=&data=%7B%22tanuloId%22%3A%22${tanuloId}%22%2C%22oktatasiNevelesiFeladatId%22%3A%227895%22%2C%22isOsztalyAtlagMegjelenik%22%3A%22True%22%7D&_=${Date.now()}`;
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(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
return processAPIGradesData(data);
} catch (error) {
console.error('Error fetching grades from API:', error);
return extractGradesDataFromDOM();
}
}
function processAPIGradesData(apiData) {
const subjects = [];
if (!apiData.Data || !Array.isArray(apiData.Data)) {
return {
schoolInfo: {
id: cookieManager.get('schoolCode') || '',
name: cookieManager.get('schoolName') || 'Iskola'
},
userData: {
name: cookieManager.get('userName') || 'Felhasználó',
time: document.querySelector('.usermenu_timer')?.textContent?.trim() || '45:00'
},
subjects: []
};
}
apiData.Data.forEach(subject => {
if (subject.TantargyNev && subject.TantargyNev !== 'Magatartás/Szorgalom') {
const grades = [];
const monthFields = [
'Szeptember', 'Oktober', 'November', 'December',
'JanuarI', 'I', 'JanuarII', 'Februar', 'Marcius',
'Aprilis', 'Majus', 'Junius', 'Julius', 'Augusztus', 'II'
];
monthFields.forEach(month => {
const monthData = subject[month];
if (monthData && monthData.trim() !== '') {
const gradeMatches = monthData.match(/<span[^>]*data-tanuloertekelesid[^>]*>([^<]+)<\/span>/g);
if (gradeMatches) {
gradeMatches.forEach(gradeHtml => {
const gradeValue = gradeHtml.match(/>([^<]+)<\/span>/)?.[1]?.trim();
if (gradeValue && gradeValue !== '-' && !gradeValue.includes('%')) {
const dateMatch = gradeHtml.match(/data-datum='([^']*)'/);
const typeMatch = gradeHtml.match(/data-tipusmod='([^']*)'/);
const themeMatch = gradeHtml.match(/data-ertekelestema='([^']*)'/);
const weightMatch = gradeHtml.match(/data-suly='([^']*)'/);
const teacherMatch = gradeHtml.match(/data-ertekelonyomtatasinev='([^']*)'/);
const theme = themeMatch ? themeMatch[1].replace('Téma: ', '').replace(/&#\d+;/g, (match) => {
const code = match.match(/\d+/)[0];
return String.fromCharCode(code);
}) : '';
const teacher = teacherMatch ? teacherMatch[1].replace(/&#\d+;/g, (match) => {
const code = match.match(/\d+/)[0];
return String.fromCharCode(code);
}) : '';
const type = typeMatch ? typeMatch[1].replace(/&#\d+;/g, (match) => {
const code = match.match(/\d+/)[0];
return String.fromCharCode(code);
}) : '';
grades.push({
value: gradeValue,
date: dateMatch ? dateMatch[1] : '',
type: type,
theme: theme,
weight: weightMatch ? weightMatch[1] : '',
teacher: teacher,
isSemesterGrade: type.toLowerCase().includes('félévi') ||
theme.toLowerCase().includes('félévi'),
isYearEndGrade: type.toLowerCase().includes('évvégi') ||
theme.toLowerCase().includes('évvégi') ||
type.toLowerCase().includes('év végi') ||
theme.toLowerCase().includes('év végi')
});
}
});
}
}
});
if (grades.length > 0) {
subjects.push({
name: subject.TantargyNev,
grades: grades,
average: subject.Atlag || 0,
classAverage: subject.OsztalyAtlag || 0
});
}
}
});
return {
schoolInfo: {
id: cookieManager.get('schoolCode') || '',
name: cookieManager.get('schoolName') || 'Iskola'
},
userData: {
name: cookieManager.get('userName') || 'Felhasználó',
time: document.querySelector('.usermenu_timer')?.textContent?.trim() || '45:00'
},
subjects: subjects
};
}
function extractGradesDataFromDOM() {
const subjects = [];
const rows = document.querySelectorAll('#Osztalyzatok_7895TanuloErtekelesByTanuloGrid tbody tr');
@@ -60,23 +188,32 @@
const gradeElements = cells[index + 3].querySelectorAll('span[data-tanuloertekelesid]');
gradeElements.forEach(element => {
const gradeText = element.textContent.trim();
if (gradeText && gradeText !== '-') {
if (gradeText && gradeText !== '-' && !gradeText.includes('%')) {
const type = element.getAttribute('data-tipusmod') || '';
const theme = element.getAttribute('data-ertekelestema') || '';
const dataType = element.getAttribute('data-tipus') || '';
grades.push({
value: gradeText,
date: element.getAttribute('data-datum'),
type: element.getAttribute('data-tipusmod'),
theme: element.getAttribute('data-ertekelestema').replace('Téma: ', ''),
type: type,
theme: theme.replace('Téma: ', ''),
weight: element.getAttribute('data-suly'),
teacher: element.getAttribute('data-ertekelonyomtatasinev'),
isSemesterGrade: (element.getAttribute('data-tipusmod') || '').toLowerCase().includes('félévi') ||
(element.getAttribute('data-ertekelestema') || '').toLowerCase().includes('félévi') ||
(element.getAttribute('data-tipus') || '').toLowerCase().includes('félévi')
isSemesterGrade: type.toLowerCase().includes('félévi') ||
theme.toLowerCase().includes('félévi') ||
dataType.toLowerCase().includes('félévi'),
isYearEndGrade: type.toLowerCase().includes('évvégi') ||
theme.toLowerCase().includes('évvégi') ||
type.toLowerCase().includes('év végi') ||
theme.toLowerCase().includes('év végi') ||
dataType.toLowerCase().includes('évvégi') ||
dataType.toLowerCase().includes('év végi')
});
}
});
});
const avgText = cells[16].textContent.trim();
const classAvgText = cells[17].textContent.trim();
@@ -84,7 +221,6 @@
const classAvg = classAvgText !== '-' ? parseFloat(classAvgText.replace(',', '.')) : 0;
if (grades.length > 0) {
subjects.push({
name: subjectName,
grades: grades,
@@ -113,24 +249,7 @@
const validSubjects = subjects.filter(s => s.average > 0);
if (validSubjects.length === 0) return 0;
const weightedSum = validSubjects.reduce((sum, subject) => {
const validGrades = subject.grades.filter(grade => !isNaN(parseInt(grade.value)));
const subjectWeightedSum = validGrades.reduce((gradeSum, grade) => {
const value = parseInt(grade.value);
const weight = parseInt(grade.weight?.match(/\d+/)?.[0] || '100') / 100;
return gradeSum + (value * weight);
}, 0);
const totalWeight = validGrades.reduce((weightSum, grade) => {
const weight = parseInt(grade.weight?.match(/\d+/)?.[0] || '100') / 100;
return weightSum + weight;
}, 0);
return sum + (subjectWeightedSum / totalWeight);
}, 0);
return weightedSum / validSubjects.length;
return validSubjects.reduce((sum, s) => sum + s.average, 0) / validSubjects.length;
}
function calculateOverallClassAverage(subjects) {
@@ -147,6 +266,7 @@
function generateGradeItem(grade) {
const semesterClass = grade.isSemesterGrade ? 'semester-grade' : '';
const yearEndClass = grade.isYearEndGrade ? 'year-end-grade' : '';
const dateObj = new Date(grade.date);
const monthNames = [
LanguageManager.t('months.january'),
@@ -165,7 +285,7 @@
const formattedDate = `${monthNames[dateObj.getMonth()]} ${dateObj.getDate()}`;
const shortenedTheme = shortenEvaluationName(grade.theme);
return `
<div class="grade-item grade-${grade.value} ${semesterClass}">
<div class="grade-item grade-${grade.value} ${semesterClass} ${yearEndClass}">
<div class="grade-value">${grade.value}</div>
<div class="grade-details">
<div class="grade-theme" title="${grade.theme}">${shortenedTheme}</div>
@@ -181,7 +301,7 @@
subjects.forEach(subject => {
subject.grades.forEach(grade => {
const value = parseInt(grade.value);
if (value >= 1 && value <= 5) {
if (value >= 1 && value <= 5 && !grade.value.includes('%')) {
distribution[value]++;
}
});
@@ -193,6 +313,7 @@
const totalGrades = data.subjects.reduce((sum, subject) => sum + subject.grades.length, 0);
const gradeDistribution = calculateGradeDistribution(data.subjects);
const semesterGrades = extractSemesterGrades(data.subjects);
const yearEndGrades = extractYearEndGrades(data.subjects);
const studentGradeLevel = Math.floor(studentAverage) || 0;
const classGradeLevel = Math.floor(classAverage) || 0;
@@ -233,14 +354,19 @@
`).join('')}
</div>
</div>
${semesterGrades.length > 0 ? `
<div class="semester-grades card">
<h3>${LanguageManager.t('grades.semester_evaluations')}</h3>
<div class="semester-grades-list">
${semesterGrades.map(grade => `
<div class="semester-grade-item grade-${grade.value}">
<div class="semester-grade-value">${grade.value}</div>
<div class="semester-grade-subject">${grade.subject}</div>
${yearEndGrades.length > 0 ? `
<div class="year-end-grades card">
<div class="grades-summary-header">
<h3>${LanguageManager.t('grades.year_end_evaluations')}</h3>
<button class="view-details-btn" onclick="showGradesModal('yearEnd')">
${LanguageManager.t('grades.view_details')}
</button>
</div>
<div class="year-end-grades-list">
${yearEndGrades.map(grade => `
<div class="year-end-grade-item grade-${grade.value}">
<div class="year-end-grade-value">${grade.value}</div>
<div class="year-end-grade-subject">${grade.subject}</div>
</div>
`).join('')}
</div>
@@ -270,6 +396,21 @@
return semesterGrades;
}
function extractYearEndGrades(subjects) {
const yearEndGrades = [];
subjects.forEach(subject => {
const yearEndGrade = subject.grades.find(grade => grade.isYearEndGrade);
if (yearEndGrade) {
yearEndGrades.push({
subject: subject.name,
value: yearEndGrade.value,
date: yearEndGrade.date
});
}
});
return yearEndGrades;
}
function calculateGradePoints(subjects) {
const allGrades = [];
@@ -278,7 +419,7 @@
const date = new Date(grade.date);
const value = parseInt(grade.value);
const weight = parseInt(grade.weight?.match(/\d+/)?.[0] || '100') / 100;
if (date && value && weight) {
if (date && value && weight && !grade.value.includes('%')) {
allGrades.push({
date,
value,
@@ -487,7 +628,7 @@
checkScrollable();
});
}
if (window.location.href.includes('/TanuloErtekeles/Osztalyzatok')) {
transformGradesPage();
}

View File

@@ -184,13 +184,13 @@ body {
.filter-card {
background: var(--card-card);
border-radius: 24px;
padding: 1.5rem;
margin-bottom: 1.5rem;
box-shadow: 0px 1px 3px 0px var(--accent-shadow);
padding: 20px;
margin-bottom: 24px;
box-shadow: 0px 1px var(--shadow-blur) 0px var(--accent-shadow);
}
.filter-header {
margin-bottom: 1rem;
margin-bottom: 16px;
}
.filter-header h2 {
@@ -202,43 +202,40 @@ body {
.filter-content {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
gap: 1rem;
width: 100%;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 16px;
}
.filter-group {
display: flex;
flex-direction: column;
gap: 0.5rem;
gap: 8px;
}
.filter-group label {
display: flex;
align-items: center;
gap: 0.5rem;
font-size: 14px;
gap: 8px;
color: var(--text-secondary);
font-size: 14px;
}
.filter-group select,
.filter-group input {
padding: 0.75rem;
border-radius: 12px;
border: 1px solid var(--accent-15);
background-color: var(--background);
padding: 10px;
border: none;
border-radius: 8px;
background: var(--button-secondaryFill);
color: var(--text-primary);
font-family: inherit;
font-size: 14px;
width: 100%;
transition: border-color 0.2s ease, box-shadow 0.2s ease;
transition: all 0.2s ease;
}
.filter-group select:focus,
.filter-group input:focus {
outline: none;
border-color: var(--accent-accent);
box-shadow: 0 0 0 2px var(--accent-15);
box-shadow: 0 0 0 2px var(--accent-accent);
}
.filter-actions {
@@ -274,93 +271,116 @@ body {
.homework-list {
display: grid;
grid-template-columns: 1fr;
gap: 1rem;
display: flex;
flex-direction: column;
gap: 16px;
}
.homework-date-group {
margin-bottom: 2rem;
background: var(--card-card);
border-radius: 24px;
overflow: hidden;
animation: fadeIn 0.3s ease;
box-shadow: 0px 1px var(--shadow-blur) 0px var(--accent-shadow);
}
.date-header {
padding: 16px;
color: var(--text-primary);
font-weight: 600;
display: flex;
align-items: center;
gap: 0.5rem;
margin-bottom: 0.5rem;
padding-bottom: 0.5rem;
border-bottom: 1px solid var(--accent-15);
gap: 8px;
}
.homework-count {
margin-left: auto;
background: var(--accent-accent);
color: var(--button-secondaryFill);
padding: 4px 8px;
border-radius: 12px;
font-size: 14px;
}
.homework-list-items {
padding: 16px;
display: flex;
flex-direction: column;
gap: 12px;
}
.date-header h3 {
font-size: 16px;
font-weight: 600;
color: var(--text-primary);
margin: 0;
}
.homework-item {
background: var(--card-card);
display: flex;
flex-direction: column;
gap: 8px;
padding: 12px;
margin: 0 16px 12px 16px;
background: var(--accent-15);
border-radius: 12px;
padding: 1rem;
margin-bottom: 0.5rem;
box-shadow: 0px 1px 2px 0px var(--accent-shadow);
transition: transform 0.2s ease;
}
.homework-item:hover {
transform: translateY(-2px);
transform: translateX(4px);
}
.homework-item.due-tomorrow {
border-left: 4px solid var(--accent-accent);
background-color: var(--accent-5);
background: var(--accent-accent);
color: white;
}
.homework-header {
.homework-item.due-tomorrow .homework-subject,
.homework-item.due-tomorrow .homework-content,
.homework-item.due-tomorrow .homework-teacher {
color: white;
}
.homework-details {
display: flex;
justify-content: space-between;
margin-bottom: 0.5rem;
flex-direction: column;
gap: 4px;
}
.homework-subject {
font-weight: 600;
font-size: 16px;
color: var(--text-primary);
}
.homework-deadline {
font-size: 14px;
color: var(--text-secondary);
}
.homework-deadline.urgent {
color: var(--accent-accent);
font-weight: 500;
margin-bottom: 4px;
}
.homework-content {
margin-bottom: 0.5rem;
color: var(--text-primary);
font-size: 14px;
}
.homework-footer {
display: flex;
justify-content: space-between;
align-items: center;
font-size: 12px;
color: var(--text-secondary);
margin-bottom: 8px;
line-height: 1.4;
word-wrap: break-word;
overflow-wrap: break-word;
white-space: pre-wrap;
}
.homework-teacher {
color: var(--text-secondary);
font-size: 12px;
font-style: italic;
}
.empty-state {
text-align: center;
padding: 2rem;
color: var(--text-secondary);
display: none;
background: var(--card-card);
border-radius: 24px;
box-shadow: 0px 1px var(--shadow-blur) 0px var(--accent-shadow);
}
.empty-state p {
@@ -380,6 +400,17 @@ body {
}
}
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(-10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes dropdownShow {
from {
opacity: 0;
@@ -389,4 +420,26 @@ body {
opacity: 1;
transform: translateY(0);
}
}
@keyframes spin {
to { transform: rotate(360deg); }
}
::-webkit-scrollbar {
width: clamp(4px, 1vw, 8px);
height: clamp(4px, 1vw, 8px);
}
::-webkit-scrollbar-track {
background: var(--background);
}
::-webkit-scrollbar-thumb {
background: var(--text-secondary);
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
background: var(--text-primary);
}

View File

@@ -221,24 +221,24 @@ function renderHomeworkList(groupedHomework) {
<div class="homework-date-group" data-date="${date}">
<div class="date-header">
<h3>${formatDateHeader(date)}</h3>
<span class="homework-count">${homeworkItems.length} ${LanguageManager.t('homework.items') || 'feladat'}</span>
</div>
${homeworkItems.map(homework => {
const isTomorrowClass = isTomorrow(homework.deadline) ? 'due-tomorrow' : '';
const urgentClass = isTomorrow(homework.deadline) ? 'urgent' : '';
return `
<div class="homework-item ${isTomorrowClass}" data-subject="${homework.subject}" data-teacher="${homework.teacher}">
<div class="homework-header">
<div class="homework-subject">${homework.subject}</div>
<div class="homework-deadline ${urgentClass}">${homework.deadline}</div>
<div class="homework-list-items">
${homeworkItems.map(homework => {
const isTomorrowClass = isTomorrow(homework.deadline) ? 'due-tomorrow' : '';
const urgentClass = isTomorrow(homework.deadline) ? 'urgent' : '';
return `
<div class="homework-item ${isTomorrowClass}" data-subject="${homework.subject}" data-teacher="${homework.teacher}">
<div class="homework-details">
<div class="homework-subject">${homework.subject}</div>
<div class="homework-content">${homework.description}</div>
<div class="homework-teacher">${homework.teacher}</div>
</div>
</div>
<div class="homework-content">${formatHomeworkDescription(homework.description)}</div>
<div class="homework-footer">
<div class="homework-teacher">${homework.teacher}</div>
</div>
</div>
`;
}).join('')}
`;
}).join('')}
</div>
</div>
`;
}).join('');
@@ -285,14 +285,6 @@ function formatDate(dateStr) {
return dateStr;
}
function formatHomeworkDescription(description) {
if (!description) return '';
description = description.replace(/\n/g, '<br>');
return description;
}
function setupFilters(homeworkItems, groupedHomework) {
const subjectFilter = document.getElementById('subjectFilter');
const teacherFilter = document.getElementById('teacherFilter');

View File

@@ -43,6 +43,7 @@
"homework": "Homework",
"absences": "Absences",
"other": "Other",
"messages": "Messages",
"profile": "Profile",
"settings": "Settings",
"logout": "Logout",
@@ -130,7 +131,8 @@
"no_homework": "No homework to display.",
"no_filtered_homework": "No homework matching the filter criteria.",
"teacher": "Teacher",
"no_matching_homework": "No homework matching the filter criteria."
"no_matching_homework": "No homework matching the filter criteria.",
"items": "items"
},
"absences": {
"title": "Absences",
@@ -146,7 +148,13 @@
"subject": "Subject",
"justification": "Justification",
"hours": "hours",
"page_transform_error": "An error occurred while transforming the page"
"page_transform_error": "An error occurred while transforming the page",
"time_period": "Time period",
"all_periods": "All periods",
"current_month": "Current month",
"last_month": "Last month",
"current_semester": "Current semester",
"last_30_days": "Last 30 days"
},
"profile": {
"title": "Profile",
@@ -315,5 +323,21 @@
"app": {
"title": "Firka - KRÉTA",
"settings_title": "Firka - Settings"
},
"forgotpassword": {
"title": "Forgot Password",
"om_id_label": "OM ID",
"om_id_placeholder": "Enter your OM ID",
"om_id_required": "OM ID is required",
"email_label": "Email address",
"email_placeholder": "Enter your email address",
"email_required": "Email address is required",
"back_to_login": "Back to login",
"reset_button": "Reset password",
"error_message": "An error occurred during password reset",
"success_message": "Password reset link sent to your email address",
"invalid_data": "Invalid data",
"invalid_email": "Invalid email address format",
"recaptcha_required": "Please complete the reCAPTCHA"
}
}

View File

@@ -43,6 +43,7 @@
"homework": "Házi feladatok",
"absences": "Mulasztások",
"other": "Egyéb",
"messages": "Üzenetek",
"profile": "Profil",
"settings": "Beállítások",
"logout": "Kijelentkezés",
@@ -130,7 +131,8 @@
"no_homework": "Nincs megjeleníthető házi feladat.",
"no_filtered_homework": "Nincs a szűrési feltételeknek megfelelő házi feladat.",
"teacher": "Tanár",
"no_matching_homework": "Nincs a szűrési feltételeknek megfelelő házi feladat."
"no_matching_homework": "Nincs a szűrési feltételeknek megfelelő házi feladat.",
"items": "feladat"
},
"absences": {
"title": "Hiányzások",
@@ -146,7 +148,13 @@
"subject": "Tantárgy",
"justification": "Igazolás",
"hours": "óra",
"page_transform_error": "Hiba történt az oldal átalakítása során"
"page_transform_error": "Hiba történt az oldal átalakítása során",
"time_period": "Időszak",
"all_periods": "Összes időszak",
"current_month": "Aktuális hónap",
"last_month": "Előző hónap",
"current_semester": "Aktuális félév",
"last_30_days": "Utolsó 30 nap"
},
"profile": {
"title": "Profil",
@@ -315,5 +323,21 @@
"app": {
"title": "Firka - KRÉTA",
"settings_title": "Firxa - Beállítások"
},
"forgotpassword": {
"title": "Elfelejtett jelszó",
"om_id_label": "OM azonosító",
"om_id_placeholder": "Adja meg az OM azonosítóját",
"om_id_required": "Az OM azonosító megadása kötelező",
"email_label": "E-mail cím",
"email_placeholder": "Adja meg az e-mail címét",
"email_required": "Az e-mail cím megadása kötelező",
"back_to_login": "Vissza a bejelentkezéshez",
"reset_button": "Jelszó visszaállítása",
"error_message": "Hiba történt a jelszó visszaállítása során",
"success_message": "A jelszó visszaállítási link elküldve az e-mail címére",
"invalid_data": "Hibás adatok",
"invalid_email": "Érvénytelen e-mail cím formátum",
"recaptcha_required": "Kérjük, töltse ki a reCAPTCHA-t"
}
}

1
icons/messages.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><g fill="none"><path fill-rule="evenodd" clip-rule="evenodd" d="M6 21a3 3 0 0 1-3-3v-3h5a2 2 0 0 0 2 2h4a2 2 0 0 0 2-2h5v3a3 3 0 0 1-3 3H6zm15-8h-5a2 2 0 0 0-2 2h-4a2 2 0 0 0-2-2H3V6a3 3 0 0 1 3-3h12a3 3 0 0 1 3 3v7z" fill="#A7DC22"/></g></svg>

After

Width:  |  Height:  |  Size: 327 B

View File

@@ -1,7 +1,7 @@
{
"manifest_version": 3,
"name": "Firxa",
"version": "1.2.2",
"version": "1.2.3",
"description": "KRÉTA webes verziójának újraírása",
"icons": {
"128": "images/firka_logo_128.png"
@@ -12,6 +12,12 @@
"128": "images/firka_logo_128.png"
}
},
"browser_specific_settings": {
"gecko": {
"id": "firxa@zan1456.hu",
"strict_min_version": "58.0"
}
},
"web_accessible_resources": [{
"resources": [
"settings/*",
@@ -23,25 +29,16 @@
"i18n/*.json",
"tools/cookieManager.js"
],
"matches": ["https://*.e-kreta.hu/*", "https://idp.e-kreta.hu/*"]
"matches": ["<all_urls>"]
}],
"content_scripts": [
{
"matches": [
"https://*.e-kreta.hu/*"
],
"js": ["tools/cookieManager.js", "tools/helper.js", "tools/loadingScreen.js", "tools/createTemplate.js",
"matches": ["https://*.e-kreta.hu/*"],
"js": ["tools/loadingScreen.js, tools/cookieManager.js", "tools/helper.js", "tools/createTemplate.js",
"global/language.js", "global/maintenance.js", "global/theme.js", "global/navigation.js"],
"css": ["tools/loadingScreen.css", "global/theme.css", "global/navigation.css"],
"css": ["tools/loadingScreen.css", "global/theme.css", "global/navigation.css", "global/maintenance.css"],
"run_at": "document_start"
},
{
"matches": [
"https://*.e-kreta.hu/*"
],
"css": ["global/maintenance.css"],
"run_at": "document_end"
},
{
"matches": ["https://idp.e-kreta.hu/Account/Login*"],
"js": ["login/login.js"],
@@ -53,48 +50,37 @@
"css": ["login/twofactor.css"]
},
{
"matches": [
"https://*.e-kreta.hu/Hianyzas/Hianyzasok*"
],
"matches": ["https://*.e-kreta.hu/Hianyzas/Hianyzasok*"],
"js": ["absences/absences.js"],
"css": ["absences/absences.css"],
"run_at": "document_end"
},
{
"matches": [
"https://idp.e-kreta.hu/Account/Logout*"
],
"matches": ["https://idp.e-kreta.hu/Account/Logout*"],
"js": ["logout/logout.js"],
"css": ["logout/logout.css"],
"run_at": "document_end"
},
{
"matches": [
"https://*.e-kreta.hu/Adminisztracio/BelepesKezelo*"
],
"matches": ["https://*.e-kreta.hu/Adminisztracio/BelepesKezelo*"],
"js": ["roleselect/roleselect.js"],
"css": ["roleselect/roleselect.css"],
"run_at": "document_end"
},
{
"matches": [
"https://*.e-kreta.hu/Adminisztracio/ElfelejtettJelszo*"
],
"matches": ["https://*.e-kreta.hu/Adminisztracio/ElfelejtettJelszo*"],
"js": ["forgotpassword/forgotpassword.js"],
"css": ["forgotpassword/forgotpassword.css"],
"run_at": "document_end"
},
{
"matches": [
"https://*.e-kreta.hu/Intezmeny/Faliujsag*"
],
"matches": ["https://*.e-kreta.hu/Intezmeny/Faliujsag*"],
"js": ["dashboard/dashboard.js"],
"css": ["dashboard/dashboard.css"],
"run_at": "document_end"
},
{
"matches": [
"https://*.e-kreta.hu/TanuloErtekeles/Osztalyzatok*"
"matches": [ "https://*.e-kreta.hu/TanuloErtekeles/Osztalyzatok*"
],
"js": ["grades/grades.js", "grades/chart.js"],
"css": ["grades/grades.css"],

View File

@@ -67,6 +67,10 @@ const createTemplate = {
</div>
</button>
<div class="user-dropdown">
<a href="https://bmszc-puskas.e-kreta.hu/Home/Uzenetek" data-page="messages" class="dropdown-item">
<img src="${chrome.runtime.getURL('icons/messages.svg')}" alt="${LanguageManager.t('navigation.messages')}">
${LanguageManager.t('navigation.messages')}
</a>
<a href="/Adminisztracio/Profil" data-page="profile" class="dropdown-item">
<img src="${chrome.runtime.getURL('icons/profile.svg')}" alt="${LanguageManager.t('navigation.profile')}">
${LanguageManager.t('navigation.profile')}