From b4a270a8d2df720cc34cd38bcf65c026514dbeb5 Mon Sep 17 00:00:00 2001 From: Zan <62830223+Zan1456@users.noreply.github.com> Date: Mon, 8 Sep 2025 21:51:55 +0200 Subject: [PATCH] Firefox addons fix --- absences/absences.js | 425 ++++++++++++------ dashboard/dashboard.js | 29 +- forgotpassword/forgotpassword.js | 101 +---- grades/grades.js | 11 +- homework/homework.js | 307 +++++++++---- login/login.js | 11 +- login/twofactor.css | 2 - login/twofactor.js | 19 +- logout/logout.js | 9 +- manifest.json | 2 +- profile/profile.js | 13 +- roleselect/roleselect.js | 11 +- search/search.css | 1 - search/search.js | 36 +- timetable/timetable.css | 18 + timetable/timetable.js | 727 ++++++++++++++++++++++--------- tools/loadingScreen.js | 30 +- 17 files changed, 1186 insertions(+), 566 deletions(-) diff --git a/absences/absences.js b/absences/absences.js index a99215d..de4e023 100644 --- a/absences/absences.js +++ b/absences/absences.js @@ -74,95 +74,230 @@ async function collectAbsencesData() { } } +function createFilterCard(absences) { + const filterCard = document.createElement('div'); + filterCard.className = 'filter-card'; + + const filterHeader = document.createElement('div'); + filterHeader.className = 'filter-header'; + const h2 = document.createElement('h2'); + h2.textContent = LanguageManager.t('absences.filter_title'); + filterHeader.appendChild(h2); + + const filterContent = document.createElement('div'); + filterContent.className = 'filter-content'; + + const dateGroup = createFilterGroup( + 'Calendar.svg', + 'Dátum', + LanguageManager.t('absences.date'), + 'input', + { type: 'date', id: 'dateFilter', className: 'filter-input' } + ); + filterContent.appendChild(dateGroup); + + const subjectGroup = createSubjectFilterGroup(absences); + filterContent.appendChild(subjectGroup); + + const justificationGroup = createJustificationFilterGroup(); + filterContent.appendChild(justificationGroup); + + filterCard.appendChild(filterHeader); + filterCard.appendChild(filterContent); + + return filterCard; +} + +function createFilterGroup(iconName, altText, labelText, elementType, attributes) { + const group = document.createElement('div'); + group.className = 'filter-group'; + + const label = document.createElement('label'); + const img = document.createElement('img'); + img.src = chrome.runtime.getURL(`icons/${iconName}`); + img.alt = altText; + img.style.width = '24px'; + img.style.height = '24px'; + + label.appendChild(img); + label.appendChild(document.createTextNode(' ' + labelText)); + + const element = document.createElement(elementType); + Object.assign(element, attributes); + + group.appendChild(label); + group.appendChild(element); + + return group; +} + +function createSubjectFilterGroup(absences) { + const group = document.createElement('div'); + group.className = 'filter-group'; + + const label = document.createElement('label'); + const img = document.createElement('img'); + img.src = chrome.runtime.getURL('icons/Subject.svg'); + img.alt = 'Tantárgy'; + img.style.width = '24px'; + img.style.height = '24px'; + + label.appendChild(img); + label.appendChild(document.createTextNode(' ' + LanguageManager.t('absences.subject'))); + + const select = document.createElement('select'); + select.id = 'subjectFilter'; + select.className = 'filter-input'; + + const defaultOption = document.createElement('option'); + defaultOption.value = ''; + defaultOption.textContent = LanguageManager.t('absences.all_subjects'); + select.appendChild(defaultOption); + + const subjects = [...new Set(absences.map(a => a.subject))].sort(); + subjects.forEach(subject => { + const option = document.createElement('option'); + option.value = subject; + option.textContent = subject; + select.appendChild(option); + }); + + group.appendChild(label); + group.appendChild(select); + + return group; +} + +function createJustificationFilterGroup() { + const group = document.createElement('div'); + group.className = 'filter-group'; + + const label = document.createElement('label'); + const img = document.createElement('img'); + img.src = chrome.runtime.getURL('icons/BadgeCheck.svg'); + img.alt = 'Igazolás'; + img.style.width = '24px'; + img.style.height = '24px'; + + label.appendChild(img); + label.appendChild(document.createTextNode(' ' + LanguageManager.t('absences.justification'))); + + const select = document.createElement('select'); + select.id = 'justificationFilter'; + select.className = 'filter-input'; + + const options = [ + { value: '', text: LanguageManager.t('absences.all_types') }, + { value: 'justified', text: LanguageManager.t('absences.justified') }, + { value: 'unjustified', text: LanguageManager.t('absences.unjustified') }, + { value: 'pending', text: LanguageManager.t('absences.pending') } + ]; + + options.forEach(optionData => { + const option = document.createElement('option'); + option.value = optionData.value; + option.textContent = optionData.text; + select.appendChild(option); + }); + + group.appendChild(label); + group.appendChild(select); + + return group; +} + +function createStatsOverview(absences) { + const statsOverview = document.createElement('div'); + statsOverview.className = 'stats-overview'; + + const stats = [ + { number: absences.length, label: LanguageManager.t('absences.total_absences') }, + { number: absences.filter(a => a.justificationStatus === 'justified').length, label: LanguageManager.t('absences.justified') }, + { number: absences.filter(a => a.justificationStatus === 'unjustified').length, label: LanguageManager.t('absences.unjustified') }, + { number: absences.filter(a => a.justificationStatus === 'pending').length, label: LanguageManager.t('absences.pending') } + ]; + + stats.forEach(stat => { + const statCard = document.createElement('div'); + statCard.className = 'stat-card'; + + const statNumber = document.createElement('div'); + statNumber.className = 'stat-number'; + statNumber.textContent = stat.number; + + const statLabel = document.createElement('div'); + statLabel.className = 'stat-label'; + statLabel.textContent = stat.label; + + statCard.appendChild(statNumber); + statCard.appendChild(statLabel); + statsOverview.appendChild(statCard); + }); + + return statsOverview; +} + +function createAbsencesContainer(absences) { + const container = document.createElement('div'); + container.className = 'absences-container'; + + const table = document.createElement('table'); + table.className = 'absences-table'; + + const thead = document.createElement('thead'); + thead.className = 'table-header'; + + const headerRow = document.createElement('tr'); + const headers = [ + LanguageManager.t('absences.date'), + LanguageManager.t('absences.lesson'), + LanguageManager.t('absences.subject'), + LanguageManager.t('absences.topic'), + LanguageManager.t('absences.status') + ]; + + headers.forEach(headerText => { + const th = document.createElement('th'); + th.textContent = headerText; + headerRow.appendChild(th); + }); + + thead.appendChild(headerRow); + + const tbody = document.createElement('tbody'); + generateAbsencesRows(absences, tbody); + + table.appendChild(thead); + table.appendChild(tbody); + container.appendChild(table); + + return container; +} + async function transformAbsencesPage() { const { basicData, absences, groupedAbsences } = await collectAbsencesData(); - - document.body.innerHTML = ` -
- ${createTemplate.header()} - -
-
-
-

${LanguageManager.t("absences.filter_title")}

-
-
-
- - -
-
- - -
-
- - -
-
-
- -
-
-
${absences.length}
-
${LanguageManager.t("absences.total_absences")}
-
-
-
${absences.filter((a) => a.justificationStatus === "justified").length}
-
${LanguageManager.t("absences.justified")}
-
-
-
${absences.filter((a) => a.justificationStatus === "unjustified").length}
-
${LanguageManager.t("absences.unjustified")}
-
-
-
${absences.filter((a) => a.justificationStatus === "pending").length}
-
${LanguageManager.t("absences.pending")}
-
-
- -
- - - - - - - - - - - - ${generateAbsencesHTML(absences)} - -
${LanguageManager.t("absences.date")}${LanguageManager.t("absences.lesson")}${LanguageManager.t("absences.subject")}${LanguageManager.t("absences.topic")}${LanguageManager.t("absences.status")}
-
-
-
- `; + document.body.textContent = ''; + const container = document.createElement('div'); + container.className = 'kreta-container'; + const headerDiv = document.createElement('div'); + const parser = new DOMParser(); + const doc = parser.parseFromString(createTemplate.header(), 'text/html'); + const tempDiv = doc.body; + while (tempDiv.firstChild) { + headerDiv.appendChild(tempDiv.firstChild); + } + container.appendChild(headerDiv); + const main = document.createElement('main'); + main.className = 'kreta-main'; + const filterCard = createFilterCard(absences); + main.appendChild(filterCard); + const statsOverview = createStatsOverview(absences); + main.appendChild(statsOverview); + const absencesContainer = createAbsencesContainer(absences); + main.appendChild(absencesContainer); + + container.appendChild(main); + document.body.appendChild(container); setupUserDropdown(); @@ -174,7 +309,7 @@ async function transformAbsencesPage() { loadingScreen.hide(); } -function generateAbsencesHTML(absences) { +function generateAbsencesRows(absences, tbody) { const groupedByDate = absences.reduce((groups, absence) => { const date = absence.date; if (!groups[date]) { @@ -188,49 +323,81 @@ function generateAbsencesHTML(absences) { (a, b) => new Date(b) - new Date(a), ); - let html = ""; - sortedDates.forEach((date) => { const dateAbsences = groupedByDate[date]; - - html += ``; + const divider = document.createElement('tr'); + divider.className = 'date-group-divider'; + divider.style.display = 'none'; + tbody.appendChild(divider); dateAbsences.forEach((absence) => { - html += ` - - - ${absence.date} - - - ${absence.lesson}. - - - ${absence.subject} - - - ${absence.topic} - - - - ${ - absence.justificationStatus === "justified" - ? `Igazolt ${LanguageManager.t("absences.justified")}` - : absence.justificationStatus === "unjustified" - ? `cancel ${LanguageManager.t("absences.unjustified")}` - : `pending ${LanguageManager.t("absences.pending")}` - } - - - - `; + const row = document.createElement('tr'); + row.className = 'table-row'; + row.dataset.subject = absence.subject; + row.dataset.justified = absence.justified; + row.dataset.date = absence.date; + row.dataset.dateGroup = date; + + const dateCell = document.createElement('td'); + dateCell.className = 'table-cell date-cell'; + dateCell.dataset.label = LanguageManager.t('absences.date'); + dateCell.textContent = absence.date; + row.appendChild(dateCell); + + const lessonCell = document.createElement('td'); + lessonCell.className = 'table-cell lesson-cell'; + lessonCell.dataset.label = LanguageManager.t('absences.lesson'); + lessonCell.textContent = absence.lesson + '.'; + row.appendChild(lessonCell); + + const subjectCell = document.createElement('td'); + subjectCell.className = 'table-cell subject-cell'; + subjectCell.dataset.label = LanguageManager.t('absences.subject'); + subjectCell.textContent = absence.subject; + row.appendChild(subjectCell); + + const topicCell = document.createElement('td'); + topicCell.className = 'table-cell topic-cell'; + topicCell.dataset.label = LanguageManager.t('absences.topic'); + topicCell.title = absence.topic; + topicCell.textContent = absence.topic; + row.appendChild(topicCell); + + const statusCell = document.createElement('td'); + statusCell.className = 'table-cell status-cell'; + statusCell.dataset.label = LanguageManager.t('absences.status'); + + const statusBadge = document.createElement('span'); + statusBadge.className = `status-badge ${absence.justificationStatus}`; + + if (absence.justificationStatus === 'justified') { + const img = document.createElement('img'); + img.src = chrome.runtime.getURL('icons/BadgeCheck.svg'); + img.alt = 'Igazolt'; + img.style.width = '16px'; + img.style.height = '16px'; + statusBadge.appendChild(img); + statusBadge.appendChild(document.createTextNode(' ' + LanguageManager.t('absences.justified'))); + } else if (absence.justificationStatus === 'unjustified') { + const span = document.createElement('span'); + span.className = 'material-icons-round'; + span.textContent = 'cancel'; + statusBadge.appendChild(span); + statusBadge.appendChild(document.createTextNode(' ' + LanguageManager.t('absences.unjustified'))); + } else { + const span = document.createElement('span'); + span.className = 'material-icons-round'; + span.textContent = 'pending'; + statusBadge.appendChild(span); + statusBadge.appendChild(document.createTextNode(' ' + LanguageManager.t('absences.pending'))); + } + + statusCell.appendChild(statusBadge); + row.appendChild(statusCell); + + tbody.appendChild(row); }); }); - - return html; } function setupEventListeners() { @@ -268,7 +435,9 @@ function createMobileGroups() { (a, b) => new Date(b) - new Date(a), ); - tbody.innerHTML = ""; + while (tbody.firstChild) { + tbody.removeChild(tbody.firstChild); + } sortedDates.forEach((date) => { const dateRows = groupedRows[date]; @@ -306,7 +475,9 @@ function removeMobileGroups() { rows.forEach((row) => allRows.push(row)); }); - tbody.innerHTML = ""; + while (tbody.firstChild) { + tbody.removeChild(tbody.firstChild); + } allRows.forEach((row) => tbody.appendChild(row)); } diff --git a/dashboard/dashboard.js b/dashboard/dashboard.js index a72fc8d..2c74233 100644 --- a/dashboard/dashboard.js +++ b/dashboard/dashboard.js @@ -476,12 +476,29 @@ class DashboardRenderer { } render() { - document.body.innerHTML = ` -
- ${createTemplate.header()} - ${this.generateMainContent()} -
- `; + document.body.innerHTML = ''; + + const kretaContainer = document.createElement('div'); + kretaContainer.className = 'kreta-container'; + const headerDiv = document.createElement('div'); + const parser = new DOMParser(); + const headerDoc = parser.parseFromString(createTemplate.header(), 'text/html'); + const headerContent = headerDoc.body; + while (headerContent.firstChild) { + headerDiv.appendChild(headerContent.firstChild); + } + kretaContainer.appendChild(headerDiv); + const mainContentDiv = document.createElement('div'); + const parser2 = new DOMParser(); + const mainDoc = parser2.parseFromString(this.generateMainContent(), 'text/html'); + const mainContent = mainDoc.body; + while (mainContent.firstChild) { + mainContentDiv.appendChild(mainContent.firstChild); + } + kretaContainer.appendChild(mainContentDiv); + + document.body.appendChild(kretaContainer); + setupUserDropdown(); setupMobileNavigation(); } diff --git a/forgotpassword/forgotpassword.js b/forgotpassword/forgotpassword.js index 92d0b70..5ab9ab6 100644 --- a/forgotpassword/forgotpassword.js +++ b/forgotpassword/forgotpassword.js @@ -1,54 +1,17 @@ (() => { - 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); - } - } - }; + // reCAPTCHA functionality removed for security compliance const loadDependencies = async () => { - if (typeof cookieManager === "undefined") { - const cookieScript = document.createElement("script"); - cookieScript.src = chrome.runtime.getURL("tools/cookieManager.js"); - document.head.appendChild(cookieScript); - - 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); - - 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); - }); - } + // reCAPTCHA functionality removed for security compliance + // Extension now works without external script dependencies }; const createPageStructure = () => { - document.body.innerHTML = ` + // Biztonságos DOM létrehozás innerHTML helyett + document.body.innerHTML = ''; + // Biztonságos HTML parsing DOMParser használatával + const parser = new DOMParser(); + const doc = parser.parseFromString(`
@@ -89,7 +52,7 @@
Az e-mail cím megadása kötelező
-
+
@@ -102,7 +65,13 @@
- `; + `, 'text/html'); + const tempDiv = doc.body; + + // Biztonságos DOM hozzáadás + while (tempDiv.firstChild) { + document.body.appendChild(tempDiv.firstChild); + } }; const transformForgotPasswordPage = async () => { @@ -165,9 +134,7 @@ }); } - setTimeout(() => { - renderRecaptcha(); - }, 500); + // reCAPTCHA rendering removed for security compliance setupFormValidation(); }; @@ -255,23 +222,7 @@ 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; - } + // reCAPTCHA validation removed for security compliance if (!isValid) { return; @@ -285,9 +236,7 @@ try { const formData = new FormData(form); - if (typeof grecaptcha !== "undefined") { - formData.append("ReCaptcha", grecaptcha.getResponse()); - } + // reCAPTCHA data removed for security compliance const response = await fetch( "/Adminisztracio/ElfelejtettJelszo/LinkKuldes", @@ -311,9 +260,7 @@ form.reset(); - if (typeof grecaptcha !== "undefined") { - grecaptcha.reset(); - } + // reCAPTCHA reset removed setTimeout(() => { window.location.href = "/Adminisztracio/Login"; @@ -324,17 +271,13 @@ true, ); - if (typeof grecaptcha !== "undefined") { - grecaptcha.reset(); - } + // reCAPTCHA reset removed } } catch (error) { console.error("Password reset error:", error); showMessage(LanguageManager.t("forgotpassword.error_message"), true); - if (typeof grecaptcha !== "undefined") { - grecaptcha.reset(); - } + // reCAPTCHA reset removed } finally { submitButton.disabled = false; submitButton.textContent = originalText; diff --git a/grades/grades.js b/grades/grades.js index 2e6f3c0..3ff6b13 100644 --- a/grades/grades.js +++ b/grades/grades.js @@ -9,12 +9,17 @@ const classAverage = calculateOverallClassAverage(gradesData.subjects); window.currentGradesData = gradesData; - - document.body.innerHTML = generatePageHTML( + document.body.innerHTML = ''; + const parser = new DOMParser(); + const doc = parser.parseFromString(generatePageHTML( gradesData, studentAverage, classAverage, - ); + ), 'text/html'); + const tempDiv = doc.body; + while (tempDiv.firstChild) { + document.body.appendChild(tempDiv.firstChild); + } setupUserDropdown(); diff --git a/homework/homework.js b/homework/homework.js index 5c20ae2..989974d 100644 --- a/homework/homework.js +++ b/homework/homework.js @@ -120,101 +120,218 @@ async function transformHomeworkPage() { const { basicData, homeworkItems, groupedHomework } = await collectHomeworkData(); - document.body.innerHTML = ` -
- ${createTemplate.header()} - -
-
-
-

${LanguageManager.t("homework.filter_title")}

-
-
-
- - -
-
- - -
-
- - -
-
-
- -
-
-
0
-
${LanguageManager.t("homework.total_homework")}
-
-
-
0
-
${LanguageManager.t("homework.urgent_homework")}
-
-
-
0
-
${LanguageManager.t("homework.completed_homework")}
-
-
-
0
-
${LanguageManager.t("homework.pending_homework")}
-
-
- -
- - - - - - - - - - - - ${generateHomeworkHTML(homeworkItems)} - -
${LanguageManager.t("homework.due_date")}${LanguageManager.t("homework.subject")}${LanguageManager.t("homework.description")}${LanguageManager.t("homework.teacher")}${LanguageManager.t("homework.status")}
-
-
-
- `; + // Biztonságos DOM létrehozás innerHTML helyett + document.body.innerHTML = ''; + + // Fő konténer létrehozása + const kretaContainer = document.createElement('div'); + kretaContainer.className = 'kreta-container'; + + // Header hozzáadása + const headerDiv = document.createElement('div'); + // Biztonságos HTML parsing DOMParser használatával + const parser = new DOMParser(); + const headerDoc = parser.parseFromString(createTemplate.header(), 'text/html'); + const headerContent = headerDoc.body; + while (headerContent.firstChild) { + headerDiv.appendChild(headerContent.firstChild); + } + kretaContainer.appendChild(headerDiv); + + // Main elem létrehozása + const main = document.createElement('main'); + main.className = 'kreta-main'; + + // Filter card létrehozása + const filterCard = document.createElement('div'); + filterCard.className = 'filter-card'; + + const filterHeader = document.createElement('div'); + filterHeader.className = 'filter-header'; + const filterTitle = document.createElement('h2'); + filterTitle.textContent = LanguageManager.t('homework.filter_title'); + filterHeader.appendChild(filterTitle); + + const filterContent = document.createElement('div'); + filterContent.className = 'filter-content'; + + // Subject filter + const subjectGroup = document.createElement('div'); + subjectGroup.className = 'filter-group'; + const subjectLabel = document.createElement('label'); + subjectLabel.textContent = LanguageManager.t('homework.subject'); + const subjectSelect = document.createElement('select'); + subjectSelect.id = 'subjectFilter'; + + const allSubjectsOption = document.createElement('option'); + allSubjectsOption.value = ''; + allSubjectsOption.textContent = LanguageManager.t('homework.all_subjects'); + subjectSelect.appendChild(allSubjectsOption); + + [...new Set(homeworkItems.map((item) => item.subject))] + .sort() + .forEach((subject) => { + const option = document.createElement('option'); + option.value = subject; + option.textContent = subject; + subjectSelect.appendChild(option); + }); + + subjectGroup.appendChild(subjectLabel); + subjectGroup.appendChild(subjectSelect); + + // Teacher filter + const teacherGroup = document.createElement('div'); + teacherGroup.className = 'filter-group'; + const teacherLabel = document.createElement('label'); + teacherLabel.textContent = LanguageManager.t('homework.teacher'); + const teacherSelect = document.createElement('select'); + teacherSelect.id = 'teacherFilter'; + + const allTeachersOption = document.createElement('option'); + allTeachersOption.value = ''; + allTeachersOption.textContent = LanguageManager.t('homework.all_teachers'); + teacherSelect.appendChild(allTeachersOption); + + [...new Set(homeworkItems.map((item) => item.teacher))] + .sort() + .forEach((teacher) => { + const option = document.createElement('option'); + option.value = teacher; + option.textContent = teacher; + teacherSelect.appendChild(option); + }); + + teacherGroup.appendChild(teacherLabel); + teacherGroup.appendChild(teacherSelect); + + // Deadline filter + const deadlineGroup = document.createElement('div'); + deadlineGroup.className = 'filter-group'; + const deadlineLabel = document.createElement('label'); + deadlineLabel.textContent = LanguageManager.t('homework.due_date'); + const deadlineSelect = document.createElement('select'); + deadlineSelect.id = 'deadlineFilter'; + + const deadlineOptions = [ + { value: '', text: LanguageManager.t('homework.all_deadlines') }, + { value: 'tomorrow', text: LanguageManager.t('homework.tomorrow_deadline') }, + { value: 'thisWeek', text: LanguageManager.t('homework.this_week') }, + { value: 'nextWeek', text: LanguageManager.t('homework.next_week') } + ]; + + deadlineOptions.forEach(({ value, text }) => { + const option = document.createElement('option'); + option.value = value; + option.textContent = text; + deadlineSelect.appendChild(option); + }); + + deadlineGroup.appendChild(deadlineLabel); + deadlineGroup.appendChild(deadlineSelect); + + filterContent.appendChild(subjectGroup); + filterContent.appendChild(teacherGroup); + filterContent.appendChild(deadlineGroup); + + filterCard.appendChild(filterHeader); + filterCard.appendChild(filterContent); + + // Stats overview + const statsOverview = document.createElement('div'); + statsOverview.className = 'stats-overview'; + statsOverview.id = 'statsOverview'; + + const statCards = [ + { id: 'totalHomework', label: LanguageManager.t('homework.total_homework'), className: '' }, + { id: 'urgentHomework', label: LanguageManager.t('homework.urgent_homework'), className: 'urgent' }, + { id: 'completedHomework', label: LanguageManager.t('homework.completed_homework'), className: 'completed' }, + { id: 'pendingHomework', label: LanguageManager.t('homework.pending_homework'), className: '' } + ]; + + statCards.forEach(({ id, label, className }) => { + const statCard = document.createElement('div'); + statCard.className = `stat-card ${className}`.trim(); + + const statNumber = document.createElement('div'); + statNumber.className = 'stat-number'; + statNumber.id = id; + statNumber.textContent = '0'; + + const statLabel = document.createElement('div'); + statLabel.className = 'stat-label'; + statLabel.textContent = label; + + statCard.appendChild(statNumber); + statCard.appendChild(statLabel); + statsOverview.appendChild(statCard); + }); + + // Homework container + const homeworkContainer = document.createElement('div'); + homeworkContainer.className = 'homework-container'; + + const homeworkTable = document.createElement('table'); + homeworkTable.className = 'homework-table'; + homeworkTable.id = 'homeworkTable'; + + const thead = document.createElement('thead'); + thead.className = 'table-header'; + const headerRow = document.createElement('tr'); + + const headers = [ + LanguageManager.t('homework.due_date'), + LanguageManager.t('homework.subject'), + LanguageManager.t('homework.description'), + LanguageManager.t('homework.teacher'), + LanguageManager.t('homework.status') + ]; + + headers.forEach(headerText => { + const th = document.createElement('th'); + th.textContent = headerText; + headerRow.appendChild(th); + }); + + thead.appendChild(headerRow); + + const tbody = document.createElement('tbody'); + tbody.id = 'homeworkTableBody'; + + // Biztonságos HTML tartalom hozzáadása + const homeworkHTML = generateHomeworkHTML(homeworkItems); + + if (homeworkHTML.trim()) { + // Biztonságos HTML parsing DOMParser használatával - table kontextusban + const parser = new DOMParser(); + const doc = parser.parseFromString(`${homeworkHTML}
`, 'text/html'); + const tempTbody = doc.querySelector('tbody'); + while (tempTbody.firstChild) { + tbody.appendChild(tempTbody.firstChild); + } + } else { + // Ha nincs házi feladat, üres sor hozzáadása + const emptyRow = document.createElement('tr'); + const emptyCell = document.createElement('td'); + emptyCell.colSpan = 5; + emptyCell.textContent = LanguageManager.t('homework.no_homework') || 'Nincs házi feladat'; + emptyCell.style.textAlign = 'center'; + emptyCell.style.padding = '20px'; + emptyRow.appendChild(emptyCell); + tbody.appendChild(emptyRow); + } + + homeworkTable.appendChild(thead); + homeworkTable.appendChild(tbody); + homeworkContainer.appendChild(homeworkTable); + + // Összeállítás + main.appendChild(filterCard); + main.appendChild(statsOverview); + main.appendChild(homeworkContainer); + + kretaContainer.appendChild(main); + document.body.appendChild(kretaContainer); setupFilters(homeworkItems, groupedHomework); setupUserDropdown(); diff --git a/login/login.js b/login/login.js index 9ed64b3..93f6ad2 100644 --- a/login/login.js +++ b/login/login.js @@ -110,7 +110,15 @@ async function transformLoginPage() { `; - document.body.innerHTML = newHTML; + // Biztonságos DOM létrehozás innerHTML helyett + document.body.innerHTML = ''; + // Biztonságos HTML parsing DOMParser használatával + const parser = new DOMParser(); + const doc = parser.parseFromString(newHTML, 'text/html'); + const tempDiv = doc.body; + while (tempDiv.firstChild) { + document.body.appendChild(tempDiv.firstChild); + } setupEventListeners(); } catch (error) { @@ -191,6 +199,5 @@ function handleSubmit(event) { if (window.location.href.includes("idp.e-kreta.hu/Account/Login")) { transformLoginPage().catch((error) => { - console.error("Error:", error); }); } diff --git a/login/twofactor.css b/login/twofactor.css index 1fe4c4c..657bf81 100644 --- a/login/twofactor.css +++ b/login/twofactor.css @@ -247,11 +247,9 @@ body { .form-control.error { border:1px solid var(--error-accent) !important; } -/* Hide original elements */ header,main > .container-fluid,footer { display:none !important; } -/* Responsive adjustments */ @media (max-width:576px) { .login-container { width:100%; diff --git a/login/twofactor.js b/login/twofactor.js index 344969a..612c6d8 100644 --- a/login/twofactor.js +++ b/login/twofactor.js @@ -83,14 +83,19 @@ async function transformTwoFactorPage() { `; - document.body.innerHTML = newHTML; + document.body.innerHTML = ''; + const parser = new DOMParser(); + const doc = parser.parseFromString(newHTML, 'text/html'); + const tempDiv = doc.body; + while (tempDiv.firstChild) { + document.body.appendChild(tempDiv.firstChild); + } applyTheme(); setupEventListeners(); if (typeof loadingScreen !== "undefined") { loadingScreen.hide(); } } catch (error) { - console.error("Error transforming two-factor page:", error); if (typeof loadingScreen !== "undefined") { loadingScreen.hide(); } @@ -104,7 +109,6 @@ function applyTheme() { document.documentElement.setAttribute("data-theme", theme); } } catch (error) { - console.error("Error applying theme:", error); } } @@ -168,7 +172,14 @@ function handleSubmit(event) { const submitButton = form.querySelector(".btn-kreta"); if (submitButton) { submitButton.disabled = true; - submitButton.innerHTML = `${LanguageManager.t("twofactor.verifying")}`; + submitButton.innerHTML = ''; + const spinnerSpan = document.createElement('span'); + spinnerSpan.className = 'spinner'; + const textSpan = document.createElement('span'); + textSpan.className = 'btn-text'; + textSpan.textContent = LanguageManager.t('twofactor.verifying'); + submitButton.appendChild(spinnerSpan); + submitButton.appendChild(textSpan); } form.submit(); diff --git a/logout/logout.js b/logout/logout.js index b402989..49d01dc 100644 --- a/logout/logout.js +++ b/logout/logout.js @@ -34,8 +34,13 @@ `; - - document.body.innerHTML = newHTML; + document.body.innerHTML = ''; + const parser = new DOMParser(); + const doc = parser.parseFromString(newHTML, 'text/html'); + const tempDiv = doc.body; + while (tempDiv.firstChild) { + document.body.appendChild(tempDiv.firstChild); + } const timerElement = document.getElementById("automaticRedirectTimer"); let remainingTime = 5; diff --git a/manifest.json b/manifest.json index de4fff0..8aae416 100644 --- a/manifest.json +++ b/manifest.json @@ -15,7 +15,7 @@ "browser_specific_settings": { "gecko": { "id": "firxa@zan1456.hu", - "strict_min_version": "58.0" + "strict_min_version": "109.0" } }, "web_accessible_resources": [ diff --git a/profile/profile.js b/profile/profile.js index d4bc414..176eb61 100644 --- a/profile/profile.js +++ b/profile/profile.js @@ -208,7 +208,6 @@ throw new Error(LanguageManager.t("profile.contacts_save_error")); } } catch (error) { - console.error("Error saving contacts:", error); alert(LanguageManager.t("profile.save_error")); } }); @@ -276,7 +275,6 @@ throw new Error(LanguageManager.t("profile.settings_save_error")); } } catch (error) { - console.error("Error saving settings:", error); alert(LanguageManager.t("profile.save_error")); } }); @@ -333,7 +331,6 @@ throw new Error(LanguageManager.t("profile.password_change_error")); } } catch (error) { - console.error("Error changing password:", error); alert(LanguageManager.t("profile.password_change_error")); } }); @@ -402,9 +399,13 @@ async function init() { if (window.location.pathname.includes("/Adminisztracio/Profil")) { - - - document.body.innerHTML = createProfileHTML(); + document.body.innerHTML = ''; + const parser = new DOMParser(); + const doc = parser.parseFromString(createProfileHTML(), 'text/html'); + const tempDiv = doc.body; + while (tempDiv.firstChild) { + document.body.appendChild(tempDiv.firstChild); + } setupUserDropdown(); setupMobileNavigation(); setupEventListeners(); diff --git a/roleselect/roleselect.js b/roleselect/roleselect.js index a55a20a..5f73237 100644 --- a/roleselect/roleselect.js +++ b/roleselect/roleselect.js @@ -127,12 +127,17 @@ if (userName) { cookieManager.set("userName", userName); } - - document.body.innerHTML = createHTML( + document.body.innerHTML = ''; + const parser = new DOMParser(); + const doc = parser.parseFromString(createHTML( schoolCode, fullSchoolName, userName, - ); + ), 'text/html'); + const tempDiv = doc.body; + while (tempDiv.firstChild) { + document.body.appendChild(tempDiv.firstChild); + } diff --git a/search/search.css b/search/search.css index 25c758f..a3399e3 100644 --- a/search/search.css +++ b/search/search.css @@ -1,4 +1,3 @@ -/* Hide original elements */ header,footer,.page-title,.card-kreta { display:none !important; } diff --git a/search/search.js b/search/search.js index d4e8919..da311e8 100644 --- a/search/search.js +++ b/search/search.js @@ -41,21 +41,34 @@ function applyFirkaStyling() { searchWrapper.className = "firka-search-wrapper"; const firkaHeader = document.createElement("div"); firkaHeader.className = "firka-header"; - firkaHeader.innerHTML = ` -

- - Firka -

-

Válassz iskolát

- `; + const logoText = document.createElement('p'); + logoText.className = 'logo-text'; + + const logoImg = document.createElement('img'); + logoImg.src = chrome.runtime.getURL('images/firka_logo.png'); + logoImg.alt = 'Firka'; + logoImg.className = 'logo'; + + logoText.appendChild(logoImg); + logoText.appendChild(document.createTextNode('Firka')); + + const searchTitle = document.createElement('h1'); + searchTitle.className = 'search-title'; + searchTitle.textContent = 'Válassz iskolát'; + + firkaHeader.appendChild(logoText); + firkaHeader.appendChild(searchTitle); const formContainer = document.createElement("div"); formContainer.className = "firka-form-container"; const firkaFooter = document.createElement("div"); firkaFooter.className = "firka-footer"; - firkaFooter.innerHTML = ` -
Adatkezelési tájékoztató - `; + const privacyLink = document.createElement('a'); + privacyLink.href = 'https://tudasbazis.ekreta.hu/pages/viewpage.action?pageId=4064926'; + privacyLink.target = '_blank'; + privacyLink.className = 'privacy-link'; + privacyLink.textContent = 'Adatkezelési tájékoztató'; + + firkaFooter.appendChild(privacyLink); const existingWrapper = document.querySelector(".firka-search-wrapper"); if (existingWrapper) { existingWrapper.remove(); @@ -78,7 +91,6 @@ function applyFirkaStyling() { } observeAutocompleteValue(instituteCodeInput, redirectButton); } catch (error) { - console.error("Error applying Firka styling:", error); } } diff --git a/timetable/timetable.css b/timetable/timetable.css index d8f42a1..bdfb192 100644 --- a/timetable/timetable.css +++ b/timetable/timetable.css @@ -235,6 +235,24 @@ body { display:grid; grid-gap:16px; } +.lesson-slot.empty-slot { + border: 2px dashed var(--text-secondary); + opacity: 0.3; + background: transparent; + margin: 8px; + border-radius: 16px; + min-height: 84px; +} +.empty-lesson-placeholder { + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; + color: var(--text-secondary); + font-size: 14px; + opacity: 0.5; +} .lesson-card { display:flex; padding:16px; diff --git a/timetable/timetable.js b/timetable/timetable.js index 7d3bb4c..a3458fa 100644 --- a/timetable/timetable.js +++ b/timetable/timetable.js @@ -143,11 +143,6 @@ } else { } } catch (error) { - console.error( - `Hiba az API feldolgozása során (${index}):`, - error, - event, - ); } }); return lessons; @@ -172,7 +167,7 @@ LanguageManager.t("timetable.friday"), ]; - // Check if there are any special days to show notice row + const hasSpecialDays = specialDayLessons.length > 0; return ` @@ -210,7 +205,18 @@ ` : ""} ${times .map( - (time, timeIndex) => ` + (time, timeIndex) => { + + const lastLessonTimes = Array(5).fill().map((_, dayIndex) => { + const dayLessonsForDay = regularLessons.filter(l => l.day === dayIndex); + if (dayLessonsForDay.length === 0) return null; + const lastTime = dayLessonsForDay + .map(l => l.startTime) + .sort((a, b) => helper.convertTimeToMinutes(b) - helper.convertTimeToMinutes(a))[0]; + return lastTime; + }); + + return `
${time}
${Array(5) .fill() @@ -218,9 +224,19 @@ const dayLessons = regularLessons.filter( (l) => l.startTime === time && l.day === dayIndex, ); + - return ` -
+ const lastLessonTime = lastLessonTimes[dayIndex]; + const isAfterLastLesson = lastLessonTime && helper.convertTimeToMinutes(time) > helper.convertTimeToMinutes(lastLessonTime); + + + if (dayLessons.length === 0 && isAfterLastLesson) { + return `
`; + } + + return ` +
+ ${dayLessons.length === 0 ? '
' : ''} ${dayLessons .map( (lesson) => ` @@ -269,7 +285,8 @@ `; }) .join("")} - `, + `; + } ) .join("")} `; @@ -277,93 +294,213 @@ function showLessonModal(lesson) { const modal = document.createElement("div"); modal.className = "lesson-modal"; - modal.innerHTML = ` - - `; + + const modalContent = document.createElement('div'); + modalContent.className = 'modal-content'; + + + const header = document.createElement('div'); + header.className = 'modal-header'; + + const title = document.createElement('h3'); + title.className = 'modal-title'; + title.textContent = lesson.subject; + + const closeBtn = document.createElement('button'); + closeBtn.className = 'modal-close'; + + const closeIcon = document.createElement('img'); + closeIcon.src = chrome.runtime.getURL('icons/CloseCircle.svg'); + closeIcon.alt = 'Bezárás'; + closeIcon.style.width = '24px'; + closeIcon.style.height = '24px'; + closeBtn.appendChild(closeIcon); + + header.appendChild(title); + header.appendChild(closeBtn); + + + const body = document.createElement('div'); + body.className = 'modal-body'; + + + const lessonDetails = document.createElement('div'); + lessonDetails.className = 'lesson-details'; + + + const teacherItem = document.createElement('div'); + teacherItem.className = 'detail-item'; + const teacherLabel = document.createElement('span'); + teacherLabel.className = 'detail-label'; + teacherLabel.textContent = LanguageManager.t('timetable.teacher_label'); + const teacherValue = document.createElement('span'); + teacherValue.className = `detail-value ${lesson.originalTeacher != '' ? 'line-through' : ''}`; + teacherValue.textContent = lesson.originalTeacher != '' ? lesson.originalTeacher : lesson.teacher; + teacherItem.appendChild(teacherLabel); + teacherItem.appendChild(teacherValue); + lessonDetails.appendChild(teacherItem); + + + if (lesson.originalTeacher != '') { + const substituteItem = document.createElement('div'); + substituteItem.className = 'detail-item'; + const substituteLabel = document.createElement('span'); + substituteLabel.className = 'detail-label'; + substituteLabel.textContent = LanguageManager.t('timetable.substitute_teacher_label'); + const substituteValue = document.createElement('span'); + substituteValue.className = 'detail-value'; + substituteValue.textContent = lesson.teacher.replace('Helyettesítő:', ''); + substituteItem.appendChild(substituteLabel); + substituteItem.appendChild(substituteValue); + lessonDetails.appendChild(substituteItem); + } + + + const roomItem = document.createElement('div'); + roomItem.className = 'detail-item'; + const roomLabel = document.createElement('span'); + roomLabel.className = 'detail-label'; + roomLabel.textContent = LanguageManager.t('timetable.classroom_label'); + const roomValue = document.createElement('span'); + roomValue.className = 'detail-value'; + roomValue.textContent = lesson.room; + roomItem.appendChild(roomLabel); + roomItem.appendChild(roomValue); + lessonDetails.appendChild(roomItem); + + + const timeItem = document.createElement('div'); + timeItem.className = 'detail-item'; + const timeLabel = document.createElement('span'); + timeLabel.className = 'detail-label'; + timeLabel.textContent = LanguageManager.t('timetable.time_label'); + const timeValue = document.createElement('span'); + timeValue.className = 'detail-value'; + timeValue.textContent = `${lesson.startTime} - ${lesson.endTime}`; + timeItem.appendChild(timeLabel); + timeItem.appendChild(timeValue); + lessonDetails.appendChild(timeItem); + + + if (lesson.isSubstituted) { + const statusItem = document.createElement('div'); + statusItem.className = 'detail-item'; + const statusLabel = document.createElement('span'); + statusLabel.className = 'detail-label'; + statusLabel.textContent = LanguageManager.t('timetable.status_label'); + const statusValue = document.createElement('span'); + statusValue.className = 'detail-value'; + const statusIcon = document.createElement('span'); + statusIcon.className = 'material-icons-round'; + statusIcon.textContent = 'sync_alt'; + statusValue.appendChild(statusIcon); + statusValue.appendChild(document.createTextNode(' ' + LanguageManager.t('timetable.substitution'))); + statusItem.appendChild(statusLabel); + statusItem.appendChild(statusValue); + lessonDetails.appendChild(statusItem); + } + + if (lesson.isCancelled) { + const statusItem = document.createElement('div'); + statusItem.className = 'detail-item'; + const statusLabel = document.createElement('span'); + statusLabel.className = 'detail-label'; + statusLabel.textContent = LanguageManager.t('timetable.status_label'); + const statusValue = document.createElement('span'); + statusValue.className = 'detail-value'; + const statusIcon = document.createElement('span'); + statusIcon.className = 'material-icons-round'; + statusIcon.textContent = 'cancel'; + statusValue.appendChild(statusIcon); + statusValue.appendChild(document.createTextNode(' ' + LanguageManager.t('timetable.cancelled'))); + statusItem.appendChild(statusLabel); + statusItem.appendChild(statusValue); + lessonDetails.appendChild(statusItem); + } + + body.appendChild(lessonDetails); + + + if (lesson.hasHomework) { + const homeworkSection = document.createElement('div'); + homeworkSection.className = 'modal-section homework-section'; + + const homeworkH4 = document.createElement('h4'); + const homeworkIcon = document.createElement('img'); + homeworkIcon.src = chrome.runtime.getURL('icons/homework.svg'); + homeworkIcon.alt = 'Házi feladat'; + homeworkIcon.style.width = '20px'; + homeworkIcon.style.height = '20px'; + homeworkH4.appendChild(homeworkIcon); + homeworkH4.appendChild(document.createTextNode(LanguageManager.t('timetable.homework_indicator'))); + + const homeworkContent = document.createElement('div'); + homeworkContent.className = 'homework-content'; + + const homeworkP = document.createElement('p'); + homeworkP.textContent = lesson.homeworkDetails ? lesson.homeworkDetails : LanguageManager.t('timetable.has_homework'); + homeworkContent.appendChild(homeworkP); + + const moreLink = document.createElement('a'); + moreLink.href = `https://${window.location.hostname}/Tanulo/TanuloHaziFeladat`; + moreLink.className = 'more-link'; + moreLink.textContent = LanguageManager.t('timetable.open_homework'); + + const linkSvg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); + linkSvg.setAttribute('width', '16'); + linkSvg.setAttribute('height', '17'); + linkSvg.setAttribute('viewBox', '0 0 16 17'); + linkSvg.setAttribute('fill', 'none'); + + const linkPath = document.createElementNS('http://www.w3.org/2000/svg', 'path'); + linkPath.setAttribute('d', 'M11.2997 5.19947L5.64282 5.19947M11.2997 5.19947L11.2997 10.8563M11.2997 5.19947L4.70001 11.7991'); + linkPath.setAttribute('stroke', 'var(--accent-accent)'); + linkPath.setAttribute('stroke-width', '2'); + linkPath.setAttribute('stroke-linecap', 'round'); + linkPath.setAttribute('stroke-linejoin', 'round'); + + linkSvg.appendChild(linkPath); + moreLink.appendChild(linkSvg); + homeworkContent.appendChild(moreLink); + + homeworkSection.appendChild(homeworkH4); + homeworkSection.appendChild(homeworkContent); + body.appendChild(homeworkSection); + } + + + if (lesson.testInfo) { + const testSection = document.createElement('div'); + testSection.className = 'modal-section test-section'; + + const testH4 = document.createElement('h4'); + const testIcon = document.createElement('img'); + testIcon.src = chrome.runtime.getURL('icons/assigment.svg'); + testIcon.alt = 'Teszt'; + testIcon.style.width = '20px'; + testIcon.style.height = '20px'; + testH4.appendChild(testIcon); + testH4.appendChild(document.createTextNode(LanguageManager.t('timetable.test_indicator'))); + + const testContent = document.createElement('div'); + testContent.className = 'test-content'; + + const testP = document.createElement('p'); + testP.textContent = lesson.testInfo; + testContent.appendChild(testP); + + testSection.appendChild(testH4); + testSection.appendChild(testContent); + body.appendChild(testSection); + } + + + modalContent.appendChild(header); + modalContent.appendChild(body); + + + modal.innerHTML = ''; + modal.appendChild(modalContent); document.body.appendChild(modal); @@ -431,7 +568,16 @@ const allLessons = apiLessons; const timetableGrid = document.querySelector(".timetable-grid"); if (timetableGrid) { - timetableGrid.innerHTML = generateTimeGrid(allLessons, weekDates); + + const newContent = generateTimeGrid(lessons, weekDates); + timetableGrid.innerHTML = ''; + + const parser1 = new DOMParser(); + const doc = parser1.parseFromString(`
${newContent}
`, 'text/html'); + const tempDiv = doc.querySelector('div'); + while (tempDiv.firstChild) { + timetableGrid.appendChild(tempDiv.firstChild); + } setupLessonCardListeners(); } @@ -648,7 +794,7 @@ schoolYear = currentYear - 1; } - const schoolYearStart = new Date(schoolYear, 8, 1); // szeptember 1 + const schoolYearStart = new Date(schoolYear, 8, 1); const startDayOfWeek = schoolYearStart.getDay(); const daysToFirstMonday = startDayOfWeek === 1 ? 0 : (8 - startDayOfWeek) % 7; @@ -664,8 +810,8 @@ } function getDateOfWeek(year, week, dayOfWeek) { - // Tanév alapú hét számítás: szeptember 1-től kezdődik - const schoolYearStart = new Date(year, 8, 1); // szeptember 1 + + const schoolYearStart = new Date(year, 8, 1); const startDayOfWeek = schoolYearStart.getDay(); const daysToFirstMonday = startDayOfWeek === 1 ? 0 : (8 - startDayOfWeek) % 7; @@ -768,19 +914,19 @@ }); } - modalGrid.innerHTML = allWeeks - .map( - (week) => ` -
- ${week.value} -
- `, - ) - .join(""); + + modalGrid.innerHTML = ''; + allWeeks.forEach((week) => { + const weekCell = document.createElement('div'); + weekCell.className = `week-cell ${week.selected ? 'selected' : ''} ${week.selected ? 'current-week' : ''}`; + weekCell.setAttribute('data-week', week.value); + weekCell.setAttribute('data-start', week.startDate); + weekCell.setAttribute('data-end', week.endDate); + weekCell.title = week.text; + weekCell.textContent = week.value; + + modalGrid.appendChild(weekCell); + }); modalGrid.addEventListener("click", async (e) => { if (e.target.classList.contains("week-cell")) { const weekValue = e.target.dataset.week; @@ -856,19 +1002,19 @@ function updateMainWeekGrid(newWeekOptions) { const weekGrid = document.getElementById("week-grid"); if (weekGrid) { - weekGrid.innerHTML = newWeekOptions - .map( - (opt) => ` -
- ${opt.value} -
- `, - ) - .join(""); + + weekGrid.innerHTML = ''; + newWeekOptions.forEach((opt) => { + const weekCell = document.createElement('div'); + weekCell.className = `week-cell ${opt.selected ? 'selected' : ''}`; + weekCell.setAttribute('data-week', opt.value); + weekCell.setAttribute('data-start', opt.startDate); + weekCell.setAttribute('data-end', opt.endDate); + weekCell.title = opt.text; + weekCell.textContent = opt.value; + + weekGrid.appendChild(weekCell); + }); } } @@ -903,63 +1049,183 @@ lessons: lessons, }; - document.body.innerHTML = ` -
- ${createTemplate.header()} -
-
-
-
- -
-
- - -
-
-
-
- - - - -
- - -
- -
-
- ${generateTimeGrid(data.lessons, data.weekDates)} -
-
-
-
- `; + document.body.innerHTML = ''; + + + const kretaContainer = document.createElement('div'); + kretaContainer.className = 'kreta-container'; + + + const headerDiv = document.createElement('div'); + + const parser2 = new DOMParser(); + const headerDoc = parser2.parseFromString(createTemplate.header(), 'text/html'); + const headerContent = headerDoc.body; + while (headerContent.firstChild) { + headerDiv.appendChild(headerContent.firstChild); + } + kretaContainer.appendChild(headerDiv); + + + const main = document.createElement('main'); + main.className = 'kreta-main'; + + + const weekControls = document.createElement('div'); + weekControls.className = 'week-controls'; + + const weekSelectorContainer = document.createElement('div'); + weekSelectorContainer.className = 'week-selector-container'; + + const weekSelector = document.createElement('div'); + weekSelector.className = 'week-selector'; + weekSelector.id = 'week-selector'; + + + const prevWeekBtn = document.createElement('button'); + prevWeekBtn.className = 'week-nav-btn'; + prevWeekBtn.id = 'prevWeekBtn'; + prevWeekBtn.title = 'Előző hét'; + const prevIcon = document.createElement('img'); + prevIcon.src = chrome.runtime.getURL('icons/ChevronLeftCircle.svg'); + prevIcon.alt = 'Előző'; + prevIcon.style.width = '24px'; + prevIcon.style.height = '24px'; + prevWeekBtn.appendChild(prevIcon); + + + const weekDisplay = document.createElement('div'); + weekDisplay.className = 'week-display'; + weekDisplay.id = 'week-display'; + + + const nextWeekBtn = document.createElement('button'); + nextWeekBtn.className = 'week-nav-btn'; + nextWeekBtn.id = 'nextWeekBtn'; + nextWeekBtn.title = 'Következő hét'; + const nextIcon = document.createElement('img'); + nextIcon.src = chrome.runtime.getURL('icons/ChevronRightCircle.svg'); + nextIcon.alt = 'Következő'; + nextIcon.style.width = '24px'; + nextIcon.style.height = '24px'; + nextWeekBtn.appendChild(nextIcon); + + + const expandBtn = document.createElement('button'); + expandBtn.className = 'expand-week-view-btn'; + expandBtn.id = 'expandWeekView'; + expandBtn.title = 'Teljes nézet'; + const expandIcon = document.createElement('img'); + expandIcon.src = chrome.runtime.getURL('icons/ArrowsExpandFull.svg'); + expandIcon.alt = 'Teljes nézet'; + expandIcon.style.width = '18px'; + expandIcon.style.height = '18px'; + expandBtn.appendChild(expandIcon); + + weekSelector.appendChild(prevWeekBtn); + weekSelector.appendChild(weekDisplay); + weekSelector.appendChild(nextWeekBtn); + weekSelector.appendChild(expandBtn); + + const weekTooltip = document.createElement('div'); + weekTooltip.className = 'week-tooltip'; + weekTooltip.id = 'week-tooltip'; + + weekSelectorContainer.appendChild(weekSelector); + weekSelectorContainer.appendChild(weekTooltip); + weekControls.appendChild(weekSelectorContainer); + + + const weekModal = document.createElement('div'); + weekModal.className = 'week-modal'; + weekModal.id = 'weekModal'; + weekModal.style.display = 'none'; + + const weekModalContent = document.createElement('div'); + weekModalContent.className = 'week-modal-content'; + + const weekModalHeader = document.createElement('div'); + weekModalHeader.className = 'week-modal-header'; + + const modalH3 = document.createElement('h3'); + weekModalHeader.appendChild(modalH3); + + const closeWeekModalBtn = document.createElement('button'); + closeWeekModalBtn.className = 'week-modal-close'; + closeWeekModalBtn.id = 'closeWeekModal'; + const closeModalIcon = document.createElement('img'); + closeModalIcon.src = chrome.runtime.getURL('icons/CloseCircle.svg'); + closeModalIcon.alt = 'Bezárás'; + closeModalIcon.style.width = '24px'; + closeModalIcon.style.height = '24px'; + closeWeekModalBtn.appendChild(closeModalIcon); + weekModalHeader.appendChild(closeWeekModalBtn); + + const weekModalGrid = document.createElement('div'); + weekModalGrid.className = 'week-modal-grid'; + weekModalGrid.id = 'weekModalGrid'; + + weekModalContent.appendChild(weekModalHeader); + weekModalContent.appendChild(weekModalGrid); + weekModal.appendChild(weekModalContent); + + + const dayNavigation = document.createElement('div'); + dayNavigation.className = 'day-navigation'; + + const prevDayBtn = document.createElement('button'); + prevDayBtn.className = 'day-nav-btn'; + prevDayBtn.id = 'prevDay'; + const prevDayIcon = document.createElement('img'); + prevDayIcon.src = chrome.runtime.getURL('icons/ChevronLeftCircle.svg'); + prevDayIcon.alt = 'Előző'; + prevDayIcon.style.width = '24px'; + prevDayIcon.style.height = '24px'; + prevDayBtn.appendChild(prevDayIcon); + prevDayBtn.appendChild(document.createTextNode('Előző')); + + const nextDayBtn = document.createElement('button'); + nextDayBtn.className = 'day-nav-btn'; + nextDayBtn.id = 'nextDay'; + nextDayBtn.appendChild(document.createTextNode('Következő')); + const nextDayIcon = document.createElement('img'); + nextDayIcon.src = chrome.runtime.getURL('icons/ChevronRightCircle.svg'); + nextDayIcon.alt = 'Következő'; + nextDayIcon.style.width = '24px'; + nextDayIcon.style.height = '24px'; + nextDayBtn.appendChild(nextDayIcon); + + dayNavigation.appendChild(prevDayBtn); + dayNavigation.appendChild(nextDayBtn); + + + const timetableContainer = document.createElement('div'); + timetableContainer.className = 'timetable-container'; + + const timetableGrid = document.createElement('div'); + timetableGrid.className = 'timetable-grid'; + + + const gridContent = generateTimeGrid(data.lessons, data.weekDates); + + const parser3 = new DOMParser(); + const doc = parser3.parseFromString(`
${gridContent}
`, 'text/html'); + const tempDiv = doc.querySelector('div'); + while (tempDiv.firstChild) { + timetableGrid.appendChild(tempDiv.firstChild); + } + + timetableContainer.appendChild(timetableGrid); + + + main.appendChild(weekControls); + main.appendChild(weekModal); + main.appendChild(dayNavigation); + main.appendChild(timetableContainer); + + kretaContainer.appendChild(main); + document.body.appendChild(kretaContainer); setupUserDropdown(); @@ -990,7 +1256,7 @@ const weekDisplay = document.getElementById("week-display"); if (!weekDisplay) return; - // Mindig 5 hetet mutatunk, a kiválasztott hét középen + const visibleWeeks = []; for (let i = -2; i <= 2; i++) { let weekNum = selectedWeekNumber + i; @@ -999,21 +1265,31 @@ visibleWeeks.push(weekNum); } - weekDisplay.innerHTML = visibleWeeks - .map((weekNum, index) => { - const isSelected = index === 2; // A középső elem mindig a kiválasztott - const isCurrent = weekNum === currentWeekNumber; - return ` -
- ${weekNum} - ${isCurrent ? '' : ""} -
- `; - }) - .join(""); + weekDisplay.innerHTML = ''; + visibleWeeks.forEach((weekNum, index) => { + const isSelected = index === 2; + const isCurrent = weekNum === currentWeekNumber; + + const weekCell = document.createElement('div'); + weekCell.className = `week-cell ${isSelected ? 'selected' : ''} ${isCurrent ? 'current-week' : ''}`; + weekCell.setAttribute('data-week', weekNum); + weekCell.title = `${weekNum}. hét${isCurrent ? ' (Jelenlegi hét)' : ''}`; + + const weekNumber = document.createElement('span'); + weekNumber.className = 'week-number'; + weekNumber.textContent = weekNum; + weekCell.appendChild(weekNumber); + + if (isCurrent) { + const currentIndicator = document.createElement('span'); + currentIndicator.className = 'current-indicator'; + currentIndicator.textContent = '●'; + weekCell.appendChild(currentIndicator); + } + + weekDisplay.appendChild(weekCell); + }); } function setupWeekNavigation() { @@ -1065,11 +1341,11 @@ } function loadWeekData(weekNumber) { - // Hét adatainak betöltése + const today = new Date(); let currentYear = today.getFullYear(); - // Ha szeptember előtt vagyunk, akkor az előző tanévet használjuk + if (today.getMonth() < 8) { currentYear--; } @@ -1086,7 +1362,16 @@ const timetableContainer = document.querySelector(".timetable-grid"); if (timetableContainer) { - timetableContainer.innerHTML = generateTimeGrid(lessons, weekDates); + + timetableContainer.innerHTML = ''; + const gridContent = generateTimeGrid(lessons, weekDates); + + const parser2 = new DOMParser(); + const doc = parser2.parseFromString(`
${gridContent}
`, 'text/html'); + const tempDiv = doc.querySelector('div'); + while (tempDiv.firstChild) { + timetableContainer.appendChild(tempDiv.firstChild); + } setupLessonCardListeners(); } }) @@ -1106,21 +1391,31 @@ allWeeks.push(week); } - modalGrid.innerHTML = allWeeks - .map((weekNumber) => { - const isSelected = weekNumber === selectedWeekNumber; - const isCurrent = weekNumber === currentWeekNumber; - - return ` - - `; - }) - .join(""); + + modalGrid.innerHTML = ''; + allWeeks.forEach((weekNumber) => { + const isSelected = weekNumber === selectedWeekNumber; + const isCurrent = weekNumber === currentWeekNumber; + + const weekCell = document.createElement('div'); + weekCell.className = `week-cell modal-week-cell ${isSelected ? 'selected' : ''} ${isCurrent ? 'current-week' : ''}`; + weekCell.setAttribute('data-week', weekNumber); + weekCell.title = `${weekNumber}. hét${isCurrent ? ' (Jelenlegi hét)' : ''}`; + + const weekNumberSpan = document.createElement('span'); + weekNumberSpan.className = 'week-number'; + weekNumberSpan.textContent = weekNumber; + weekCell.appendChild(weekNumberSpan); + + if (isCurrent) { + const currentIndicator = document.createElement('span'); + currentIndicator.className = 'current-indicator'; + currentIndicator.textContent = '●'; + weekCell.appendChild(currentIndicator); + } + + modalGrid.appendChild(weekCell); + }); modal.style.display = "flex"; document.body.style.overflow = "hidden"; diff --git a/tools/loadingScreen.js b/tools/loadingScreen.js index 9d95d8f..d7fbc2a 100644 --- a/tools/loadingScreen.js +++ b/tools/loadingScreen.js @@ -6,13 +6,29 @@ const loadingScreen = { const loadingScreen = document.createElement("div"); loadingScreen.className = "loading-screen"; - loadingScreen.innerHTML = ` -
- -
Betöltés alatt...
-
Kis türelmet!
-
- `; + + const loadingContent = document.createElement('div'); + loadingContent.className = 'loading-content'; + + const loadingLogo = document.createElement('img'); + loadingLogo.src = chrome.runtime.getURL("images/loading.gif"); + loadingLogo.alt = 'Firka'; + loadingLogo.className = 'loading-logo'; + + const loadingText = document.createElement('div'); + loadingText.className = 'loading-text'; + loadingText.setAttribute('data-i18n', 'loading.text'); + loadingText.textContent = 'Betöltés alatt...'; + + const loadingText2 = document.createElement('div'); + loadingText2.className = 'loading-text2'; + loadingText2.setAttribute('data-i18n', 'loading.subtext'); + loadingText2.textContent = 'Kis türelmet!'; + + loadingContent.appendChild(loadingLogo); + loadingContent.appendChild(loadingText); + loadingContent.appendChild(loadingText2); + loadingScreen.appendChild(loadingContent); document.body.appendChild(loadingScreen); document.body.classList.add("loaded"); },