21 Commits
1.4.4 ... main

Author SHA1 Message Date
Zan
6a5ecadbdc new web 2026-03-29 16:18:52 +02:00
Zan
1bdc8b5692 Few fixes 2026-03-28 23:55:27 +01:00
Zan
aea3b20ff9 fix light text in absences 2026-03-11 18:16:08 +01:00
Zan
ee42a064d2 update build 2026-02-23 20:58:45 +01:00
Zan
89296804be Profile page rework 2026-01-19 21:47:12 +01:00
Zan
29566f4fae few fixes to settings 2026-01-19 20:55:54 +01:00
Zan
93c9c2d307 Update timetable.js 2026-01-15 19:24:12 +01:00
Zan
a94c06d893 Dupla óra 2026-01-15 19:10:30 +01:00
Zan
7cd8c065b3 fix 2026-01-15 17:59:19 +01:00
Zan
d44be3b029 Message attachments 2026-01-15 17:56:40 +01:00
Zan
3243ebdc2e Merge branch 'main' of https://github.com/QwIT-Development/firka-extension 2026-01-15 17:43:44 +01:00
Zan
0f69a1583b Online ora 2026-01-15 17:42:53 +01:00
Zan
15ab433064 Sy removed 2026-01-15 17:23:09 +01:00
Zan
4aab9afebd message html fix 2026-01-15 17:18:19 +01:00
Zan
e0df578dca Update logo image source in README.md 2026-01-15 17:10:59 +01:00
Zan
dd320d3dc4 Online óra 2026-01-15 17:07:59 +01:00
Zan
5248cfc12e Revert "#23 fix"
This reverts commit 1429943dbe.
2026-01-15 16:27:36 +01:00
Zan
1f34cacf25 updater fix 2026-01-12 20:34:48 +01:00
Zan
f35d29f56c fix custom homework 2026-01-12 20:09:41 +01:00
Zan
1429943dbe #23 fix 2026-01-12 19:53:35 +01:00
Zan
2ca1c9949a updater 2026-01-12 19:33:19 +01:00
28 changed files with 1961 additions and 944 deletions

View File

@@ -1,71 +1,82 @@
name: Package and Release Extension
name: Build and Release
on:
workflow_dispatch:
push:
branches:
- test
inputs:
version:
description: 'Release version (pl. v1.0.0)'
required: true
default: 'v1.0.0'
jobs:
build-and-release:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
- name: Checkout
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Get current date
id: date
- name: Set up build directories
run: |
echo "DATE=$(date +'%Y.%m.%d. %H:%M')" >> $GITHUB_ENV
echo "DATE_FOR_ZIP=$(date +'%Y%m%d-%H%M')" >> $GITHUB_ENV
mkdir -p build/chrome
mkdir -p build/firefox
- name: Create ZIP file
- name: Copy files Chrome
run: |
zip -r "pre-firxa-${{ env.DATE_FOR_ZIP }}.zip" . -x "*.git*" "*.github*" "*.idea*"
rsync -av \
--exclude='.git' \
--exclude='.gitea' \
--exclude='README*' \
--exclude='readme*' \
--exclude='LICENSE*' \
--exclude='license*' \
--exclude='*.md' \
--exclude='build/' \
. build/chrome/
- name: Delete previous pre-release
uses: dev-drprasad/delete-tag-and-release@v0.2.1
with:
delete_release: true
tag_name: pre-release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
continue-on-error: true
- name: Copy files Firefox
run: |
rsync -av \
--exclude='.git' \
--exclude='.gitea' \
--exclude='README*' \
--exclude='readme*' \
--exclude='LICENSE*' \
--exclude='license*' \
--exclude='*.md' \
--exclude='build/' \
. build/firefox/
- name: Create new pre-release
id: create_release
uses: softprops/action-gh-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Prepare Chrome build
run: |
rm -f build/chrome/manifest_fox.json
- name: Prepare Firefox build
run: |
rm -f build/firefox/manifest.json
mv build/firefox/manifest_fox.json build/firefox/manifest.json
- name: Create ZIP archives
run: |
cd build/chrome
zip -r ../../firka-extension-chrome-${{ github.event.inputs.version }}.zip .
cd ../firefox
zip -r ../../firka-extension-firefox-${{ github.event.inputs.version }}.zip .
- name: Create Release
uses: actions/gitea-release@v1
with:
tag_name: pre-release
release_name: Fejlesztői build
token: ${{ secrets.GITEA_TOKEN }}
tag_name: ${{ github.event.inputs.version }}
release_name: ${{ github.event.inputs.version }}
body: |
Ez egy kiadás előtti build, amely minden egyes commit után frissül!
A build automatikusan készült ekkor: ${{ env.DATE }}
## Firka Extension ${{ github.event.inputs.version }}
### Letöltések
- **Chrome / Chromium** `firka-extension-chrome-${{ github.event.inputs.version }}.zip`
- **Firefox** `firka-extension-firefox-${{ github.event.inputs.version }}.zip`
files: |
firka-extension-chrome-${{ github.event.inputs.version }}.zip
firka-extension-firefox-${{ github.event.inputs.version }}.zip
draft: false
prerelease: true
- name: Upload ZIP to release
if: steps.create_release.outputs.upload_url != ''
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./pre-firxa-${{ env.DATE_FOR_ZIP }}.zip
asset_name: pre-firxa-${{ env.DATE_FOR_ZIP }}.zip
asset_content_type: application/zip
check-links:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Link Checker
id: lychee
uses: lycheeverse/lychee-action@v2
with:
fail: false
prerelease: false

View File

@@ -1,5 +1,5 @@
<p align="center">
<img width="150" height="150" alt="firka_logo_128" src="https://github.com/user-attachments/assets/089b37c8-bdb1-48af-93e5-9fc656fe8c15" />
<img width="150" height="150" alt="firka_logo_128" src="https://github.com/QwIT-Development/firka-extension/blob/main/images/firka_logo_128.png?raw=true" />
<h1 align="center">Firka extension</h1>
</p>

View File

@@ -197,7 +197,7 @@ body {
.month-header {
background: var(--button-secondaryFill);
color: white;
color: var(--text-primary);
padding: 16px 20px;
font-size: 16px;
font-weight: 600;
@@ -377,7 +377,7 @@ body {
.modal-header {
background: var(--button-secondaryFill);
border-bottom: 1px solid #00000000 !important;
color: white;
color: var(--text-primary);
padding: 14px 18px !important;
display: flex;
align-items: center;

View File

@@ -186,5 +186,6 @@
{ code: "en", name: "English" },
{ code: "de", name: "Deutsch" },
],
init: initializeLanguage,
};
})();

View File

@@ -197,7 +197,7 @@
}
.dropdown-item:hover img {
filter: none;
filter: brightness(0) saturate(100%) invert(25%) sepia(50%) saturate(2000%) hue-rotate(90deg) brightness(90%) contrast(95%);
}
@keyframes dropdownShow {
@@ -418,7 +418,7 @@
}
.mobile-dropdown-item:hover img {
filter: none;
filter: brightness(0) saturate(100%) invert(25%) sepia(50%) saturate(2000%) hue-rotate(90deg) brightness(90%) contrast(95%);
}
body {

View File

@@ -278,10 +278,23 @@
"school": "Schule",
"student_id": "Schüler-ID",
"settings_title": "Profileinstellungen",
"tab_my_data": "Meine Daten",
"tab_settings": "Einstellungen",
"tab_password": "Passwort ändern",
"tab_security": "Sicherheitseinstellungen",
"tab_contacts": "Kontakte",
"loading_data": "Daten werden geladen...",
"loading_error": "Fehler beim Laden der Daten.",
"my_data_title": "Meine persönlichen Daten",
"personal_data": "Persönliche Daten",
"contact_data": "Kontaktdaten",
"address_data": "Adressdaten",
"bank_account_data": "Bankverbindung",
"student_card_data": "Schülerausweis Daten",
"default_address": "Standard",
"password_change_unavailable": "Die Passwortänderungsfunktion ist derzeit nicht verfügbar.",
"security_settings_info": "Um Sicherheitseinstellungen zu verwalten, klicken Sie auf die Schaltfläche unten:",
"open_security_settings": "Sicherheitseinstellungen öffnen",
"two_factor_description": "Um die Zwei-Faktor-Authentifizierung zu verwenden, installieren Sie eine zeitbasierte Einmalpasswort-App (TOTP):",
"android": "Android",
"iphone": "iPhone",
@@ -315,7 +328,31 @@
"passwords_not_match": "Die neuen Passwörter stimmen nicht überein!",
"password_too_short": "Das neue Passwort muss mindestens 8 Zeichen lang sein!",
"password_changed": "Passwort erfolgreich geändert!",
"password_change_error": "Fehler beim Ändern des Passworts. Bitte versuchen Sie es später erneut."
"password_change_error": "Fehler beim Ändern des Passworts. Bitte versuchen Sie es später erneut.",
"field_familyName": "Familienname",
"field_firstName": "Vorname",
"field_birthFamilyName": "Geburts-Familienname",
"field_birthFirstName": "Geburts-Vorname",
"field_motherFamilyName": "Geburts-Familienname der Mutter",
"field_motherFirstName": "Geburts-Vorname der Mutter",
"field_birthDate": "Geburtsdatum",
"field_birthPlace": "Geburtsort",
"field_birthCountry": "Geburtsland",
"field_motherTongue": "Muttersprache",
"field_citizenship": "Staatsangehörigkeit",
"field_classTeacher": "Klassenlehrer",
"field_className": "Klasse",
"field_classroom": "Klassenzimmer",
"field_username": "Benutzername",
"field_phone": "Telefonnummer",
"field_email": "Benachrichtigungs-E-Mail-Adresse",
"field_accountNumber": "Bankkontonummer",
"field_bankName": "Bankname",
"field_accountOwner": "Kontoinhaber",
"field_cardNumber": "Kartennummer",
"field_taxId": "Steuer-ID",
"field_studentCardNumber": "Studentenausweisnummer",
"field_socialSecurityNumber": "Sozialversicherungsnummer"
},
"login": {
"title": "Anmelden",

View File

@@ -278,10 +278,23 @@
"school": "School",
"student_id": "Student ID",
"settings_title": "Profile settings",
"tab_my_data": "My Data",
"tab_settings": "Settings",
"tab_password": "Change password",
"tab_security": "Security settings",
"tab_contacts": "Contact information",
"loading_data": "Loading data...",
"loading_error": "An error occurred while loading the data.",
"my_data_title": "My Personal Data",
"personal_data": "Personal Information",
"contact_data": "Contact Information",
"address_data": "Address Data",
"bank_account_data": "Bank Account Data",
"student_card_data": "Student Card Data",
"default_address": "Default",
"password_change_unavailable": "The password change function is currently unavailable.",
"security_settings_info": "To manage security settings, click the button below:",
"open_security_settings": "Open Security Settings",
"two_factor_description": "To use two-factor authentication, install a time-based one-time password (TOTP) application:",
"android": "Android",
"iphone": "iPhone",
@@ -315,7 +328,31 @@
"passwords_not_match": "New passwords do not match!",
"password_too_short": "New password must be at least 8 characters long!",
"password_changed": "Password changed successfully!",
"password_change_error": "An error occurred while changing password. Please try again later."
"password_change_error": "An error occurred while changing password. Please try again later.",
"field_familyName": "Family name",
"field_firstName": "First name",
"field_birthFamilyName": "Birth family name",
"field_birthFirstName": "Birth first name",
"field_motherFamilyName": "Mother's birth family name",
"field_motherFirstName": "Mother's birth first name",
"field_birthDate": "Date of birth",
"field_birthPlace": "Place of birth",
"field_birthCountry": "Country of birth",
"field_motherTongue": "Mother tongue",
"field_citizenship": "Citizenship",
"field_classTeacher": "Class teacher",
"field_className": "Class",
"field_classroom": "Classroom",
"field_username": "Username",
"field_phone": "Phone number",
"field_email": "Notification email address",
"field_accountNumber": "Bank account number",
"field_bankName": "Bank name",
"field_accountOwner": "Account owner's name",
"field_cardNumber": "Card number",
"field_taxId": "Tax ID",
"field_studentCardNumber": "Student card number",
"field_socialSecurityNumber": "Social security number"
},
"login": {
"title": "Login",

View File

@@ -280,10 +280,23 @@
"school": "Iskola",
"student_id": "Diák azonosító",
"settings_title": "Profil beállítások",
"tab_my_data": "Adataim",
"tab_settings": "Beállítások",
"tab_password": "Jelszó módosítása",
"tab_security": "Biztonsági beállítások",
"tab_contacts": "Elérhetőségek",
"loading_data": "Adatok betöltése...",
"loading_error": "Hiba történt az adatok betöltése során.",
"my_data_title": "Személyes adataim",
"personal_data": "Személyes adatok",
"contact_data": "Elérhetőségi adatok",
"address_data": "Lakcím adatok",
"bank_account_data": "Bankszámla adatok",
"student_card_data": "Tanulói igazolvány adatok",
"default_address": "Alapértelmezett",
"password_change_unavailable": "A jelszó módosítás funkció jelenleg nem érhető el.",
"security_settings_info": "A biztonsági beállítások kezeléséhez kattints az alábbi gombra:",
"open_security_settings": "Biztonsági beállítások megnyitása",
"two_factor_description": "A kétfaktoros hitelesítés használatához telepítsen egy időalapú, egyszer használatos jelszó (TOTP) alkalmazást:",
"android": "Android",
"iphone": "iPhone",
@@ -317,7 +330,31 @@
"passwords_not_match": "Az új jelszavak nem egyeznek!",
"password_too_short": "Az új jelszónak legalább 8 karakter hosszúnak kell lennie!",
"password_changed": "Jelszó sikeresen módosítva!",
"password_change_error": "Hiba történt a jelszó módosítása során. Kérjük, próbálja újra később."
"password_change_error": "Hiba történt a jelszó módosítása során. Kérjük, próbálja újra később.",
"field_familyName": "Családi név",
"field_firstName": "Utónév",
"field_birthFamilyName": "Születési családi név",
"field_birthFirstName": "Születési utónév",
"field_motherFamilyName": "Anyja születési családi neve",
"field_motherFirstName": "Anyja születési utóneve",
"field_birthDate": "Születési idő",
"field_birthPlace": "Születési hely",
"field_birthCountry": "Születési ország",
"field_motherTongue": "Anyanyelv",
"field_citizenship": "Állampolgárság",
"field_classTeacher": "Osztályfőnök",
"field_className": "Osztály",
"field_classroom": "Terem",
"field_username": "Felhasználónév",
"field_phone": "Telefonszám",
"field_email": "Értesítési e-mail cím",
"field_accountNumber": "Bankszámlaszám",
"field_bankName": "Számlavezető bank",
"field_accountOwner": "Bankszámla tulajdonos neve",
"field_cardNumber": "Igazolvány száma",
"field_taxId": "Adóazonosító jel",
"field_studentCardNumber": "Diákigazolvány szám",
"field_socialSecurityNumber": "TAJ-szám"
},
"login": {
"title": "Bejelentkezés",

1
icons/contact.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 3.223a9.003 9.003 0 0 0-5.605 13.592L3 21l4.185-1.395A9.003 9.003 0 0 0 20.777 14m0-4A9.01 9.01 0 0 0 14 3.223M17 12a5 5 0 0 0-5-5m1 5a1 1 0 0 0-1-1"/></svg>

After

Width:  |  Height:  |  Size: 353 B

View File

@@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewBox="0 0 28 28" fill="none"><g fill-rule="evenodd" clip-rule="evenodd" fill="currentColor" stroke="currentColor" stroke-width="1.66667" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="8" r="5" fill="currentColor"/><path d="M20 21a8 8 0 1 0-16 0"/></g></svg>
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewBox="3 2 22 24" fill="none"><g fill-rule="evenodd" clip-rule="evenodd" fill="currentColor" stroke="currentColor" stroke-width="1.66667" stroke-linecap="round" stroke-linejoin="round"><circle cx="14" cy="9" r="5" fill="currentColor"/><path d="M22 22a8 8 0 1 0-16 0"/></g></svg>

Before

Width:  |  Height:  |  Size: 343 B

After

Width:  |  Height:  |  Size: 343 B

1
icons/project.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 24 24"><g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><path d="M3 20h.01M7 20a4 4 0 0 0-4-4m8 4a8 8 0 0 0-8-8"/><path fill="currentColor" d="M19 4H5a2 2 0 0 0-2 2v2.5c4 .167 12 2.7 12 11.5h4a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2"/></g></svg>

After

Width:  |  Height:  |  Size: 365 B

View File

@@ -1 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewBox="0 0 28 28" fill="none"><path fill="currentColor" fill-rule="evenodd" d="M9.024 2.783A1 1 0 0 1 10 2h4a1 1 0 0 1 .976.783l.44 1.981q.6.285 1.14.66l1.938-.61a1 1 0 0 1 1.166.454l2 3.464a1 1 0 0 1-.19 1.237l-1.497 1.373a8 8 0 0 1 0 1.316l1.497 1.373a1 1 0 0 1 .19 1.237l-2 3.464a1 1 0 0 1-1.166.454l-1.937-.61q-.54.375-1.14.66l-.44 1.98A1 1 0 0 1 14 22h-4a1 1 0 0 1-.976-.783l-.44-1.981q-.6-.285-1.14-.66l-1.938.61a1 1 0 0 1-1.166-.454l-2-3.464a1 1 0 0 1 .19-1.237l1.497-1.373a8 8 0 0 1 0-1.316L2.53 9.97a1 1 0 0 1-.19-1.237l2-3.464a1 1 0 0 1 1.166-.454l1.937.61q.54-.375 1.14-.66l.44-1.98zM12 15a3 3 0 1 0 0-6a3 3 0 0 0 0 6" clip-rule="evenodd"/></svg>
<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewBox="2 2 24 24" fill="none">
<path fill="currentColor" fill-rule="evenodd" d="M 10.748 4.096 C 10.85 3.638 11.255 3.313 11.724 3.313 L 15.724 3.313 C 16.193 3.313 16.598 3.638 16.7 4.096 L 17.14 6.077 C 17.54 6.267 17.92 6.487 18.28 6.737 L 20.218 6.127 C 20.665 5.986 21.15 6.175 21.384 6.581 L 23.384 10.045 C 23.618 10.451 23.539 10.965 23.194 11.282 L 21.697 12.655 C 21.733 13.093 21.733 13.533 21.697 13.971 L 23.194 15.344 C 23.539 15.661 23.618 16.175 23.384 16.581 L 21.384 20.045 C 21.15 20.451 20.665 20.639 20.218 20.499 L 18.281 19.889 C 17.921 20.139 17.541 20.359 17.141 20.549 L 16.701 22.529 C 16.6 22.987 16.193 23.313 15.724 23.313 L 11.724 23.313 C 11.255 23.313 10.85 22.987 10.748 22.53 L 10.308 20.549 C 9.908 20.359 9.528 20.139 9.168 19.889 L 7.23 20.499 C 6.783 20.639 6.298 20.451 6.064 20.045 L 4.064 16.581 C 3.83 16.175 3.908 15.661 4.254 15.344 L 5.751 13.971 C 5.715 13.533 5.715 13.093 5.751 12.655 L 4.254 11.283 C 3.908 10.966 3.83 10.452 4.064 10.046 L 6.064 6.582 C 6.298 6.176 6.783 5.987 7.23 6.128 L 9.167 6.738 C 9.527 6.488 9.907 6.268 10.307 6.078 L 10.747 4.098 L 10.748 4.096 Z M 13.931 17.38 C 17.01 17.38 18.935 14.046 17.395 11.38 C 16.68 10.142 15.36 9.38 13.931 9.38 C 10.852 9.38 8.927 12.713 10.467 15.38 C 11.181 16.617 12.502 17.38 13.931 17.38" clip-rule="evenodd"/>
</svg>

Before

Width:  |  Height:  |  Size: 722 B

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
images/folio.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

View File

@@ -1,7 +1,7 @@
{
"manifest_version": 3,
"name": "Firxa",
"version": "1.4.6",
"version": "1.4.8",
"description": "KRÉTA webes verziójának újraírása",
"icons": {
"128": "images/firka_logo_128.png"
@@ -40,9 +40,7 @@
"grades/chart.js",
"i18n/*.json",
"tools/storageManager.js",
"tools/storageTest.js",
"tools/sentry.js",
"tools/sentry-browser.min.js"
"tools/storageTest.js"
],
"matches": [
"<all_urls>"
@@ -67,8 +65,6 @@
"https://eugyintezes.e-kreta.hu/*"
],
"js": [
"tools/sentry-browser.min.js",
"tools/sentry.js",
"global/language.js",
"global/theme.js",
"tools/loadingScreen.js",

View File

@@ -1,7 +1,7 @@
{
"manifest_version": 3,
"name": "Firxa",
"version": "1.4.6",
"version": "1.4.8",
"description": "KRÉTA webes verziójának újraírása",
"icons": {
"128": "images/firka_logo_128.png"
@@ -40,9 +40,7 @@
"grades/chart.js",
"i18n/*.json",
"tools/storageManager.js",
"tools/storageTest.js",
"tools/sentry.js",
"tools/sentry-browser.min.js"
"tools/storageTest.js"
],
"matches": [
"<all_urls>"
@@ -67,8 +65,6 @@
"https://eugyintezes.e-kreta.hu/*"
],
"js": [
"tools/sentry-browser.min.js",
"tools/sentry.js",
"global/language.js",
"global/theme.js",
"tools/loadingScreen.js",

View File

@@ -440,7 +440,6 @@ body.modal-open {
align-items: center;
padding: 20px;
border-bottom: 1px solid var(--background-0);
background: var(--background);
border-radius: 12px 12px 0 0;
}
@@ -525,7 +524,7 @@ body.modal-open {
}
.message-info {
background-color: var(--card-card);
background-color: var(--button-secondaryFill);
padding: 15px;
border-radius: 6px;
margin-bottom: 20px;
@@ -564,7 +563,7 @@ body.modal-open {
}
.message-text {
background-color: var(--card-card);
background-color: var(--button-secondaryFill);
border-radius: 6px;
padding: 15px;
line-height: 1.6;
@@ -591,14 +590,14 @@ body.modal-open {
}
.message-attachments {
background: #f9f9f9;
background: var(--button-secondaryFill);
padding: 15px;
border-radius: 6px;
}
.message-attachments h4 {
margin: 0 0 10px 0;
color: #333;
color: var(--text-secondary);
font-size: 1.1em;
}

View File

@@ -310,7 +310,8 @@
messageContent.appendChild(contentTitle);
const messageText = document.createElement('div');
messageText.className = 'message-text';
messageText.textContent = content;
messageText.innerHTML = content;
messageContent.appendChild(messageText);
messageDetails.appendChild(messageContent);
@@ -320,14 +321,17 @@
const attachTitle = document.createElement('h4');
attachTitle.textContent = 'Mellékletek:';
messageAttachments.appendChild(attachTitle);
const attachList = document.createElement('ul');
message.csatolmanyok.forEach(attachment => {
const li = document.createElement('li');
const a = document.createElement('a');
a.href = '#';
a.textContent = sanitizeHTML(attachment.nev);
a.onclick = () => downloadAttachment(attachment.azonosito);
a.textContent = sanitizeHTML(attachment.fajlNev || attachment.nev || 'Ismeretlen fájl');
a.onclick = (e) => {
e.preventDefault();
downloadAttachment(attachment.azonosito, attachment.fajlNev || attachment.nev);
};
li.appendChild(a);
attachList.appendChild(li);
});
@@ -345,6 +349,32 @@
}
document.body.classList.remove('modal-open');
}
async function downloadAttachment(azonosito, fileName) {
try {
const response = await chrome.runtime.sendMessage({
action: 'download_attachment',
azonosito: azonosito,
fileName: fileName
});
if (response.success && response.data) {
const a = document.createElement('a');
a.href = response.data;
a.download = response.fileName || 'letoltes';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
} else {
console.error('Melléklet letöltési hiba:', response.error);
alert('Nem sikerült letölteni a mellékletet.');
}
} catch (error) {
console.error('Melléklet letöltési hiba:', error);
alert('Hiba történt a melléklet letöltése során.');
}
}
window.openMessageModal = openMessageModal;
window.closeMessageModal = closeMessageModal;

View File

@@ -1,6 +1,5 @@
@import url('../global/theme.css');
.main-header,
.main-menu,
.main-sidebar,
@@ -11,11 +10,17 @@
.navbar,
.sidebar-container,
#sidepanel_tabs,
.sidepanel-wrapper {
.sidepanel-wrapper,
.main-footer2,
.lakatimg,
.modalContainer,
.modalOuter,
#ProfilTab,
#KretaProgressBar {
display: none !important;
visibility: hidden !important;
}
body {
margin: 0;
padding: 0;
@@ -26,6 +31,11 @@ body {
font-size: 16px;
}
h2 {
background-color: var(--card-card) !important;
border-bottom: none !important;
}
.page-wrapper {
background-color: var(--background) !important;
min-height: 100vh;
@@ -50,271 +60,295 @@ body {
padding: 0;
}
.content-container {
max-width: 1200px;
.profile-container {
max-width: 1400px;
margin: 0 auto;
padding: clamp(1rem, 3vw, 2rem);
background-color: var(--background) !important;
padding: 2rem;
}
.profile-wrapper {
display: grid;
grid-template-columns: 280px 1fr;
gap: 2rem;
min-height: calc(100vh - 200px);
}
.firka-header {
padding: clamp(1rem, 3vw, 2rem);
.profile-sidebar {
position: sticky;
top: 2rem;
height: fit-content;
}
.profile-tabs {
background: var(--card-card);
border-radius: 16px;
padding: 1rem;
box-shadow: 0px 1px 2px 0px var(--accent-shadow);
}
.profile-tab {
width: 100%;
display: flex;
align-items: center;
gap: 1rem;
background-color: var(--background);
gap: 0.75rem;
padding: 1rem;
border: none;
background: transparent;
color: var(--text-secondary);
font-family: 'Montserrat', sans-serif;
font-size: 14px;
font-weight: 500;
cursor: pointer;
border-radius: 12px;
transition: all 0.2s ease;
text-align: left;
}
.profile-tab:hover {
background: var(--button-secondaryFill);
color: var(--text-primary);
}
.profile-tab.active {
background: var(--accent-accent);
color: white;
}
.profile-tab svg {
flex-shrink: 0;
}
.profile-content {
background: var(--card-card);
border-radius: 16px;
padding: 2rem;
box-shadow: 0px 1px 2px 0px var(--accent-shadow);
min-height: 500px;
}
.tab-content {
display: none;
}
.tab-content.active {
display: block;
}
.tab-header {
margin-bottom: 2rem;
padding-bottom: 1rem;
border-bottom: 2px solid var(--accent-15);
}
.tab-header h2 {
margin: 0;
color: var(--text-primary);
font-size: 28px;
font-weight: 600;
}
.data-section {
margin-bottom: 2.5rem;
}
.data-section:last-child {
margin-bottom: 0;
}
.data-section h3 {
color: var(--text-primary);
font-size: 20px;
font-weight: 600;
margin: 0 0 1.5rem 0;
padding-bottom: 0.75rem;
border-bottom: 1px solid var(--accent-15);
}
.back-button {
.data-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 1.5rem;
}
.data-item {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.data-item label {
color: var(--text-secondary);
font-size: 13px;
font-weight: 500;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.data-item span {
color: var(--text-primary);
font-size: 15px;
font-weight: 500;
padding: 0.75rem;
background: var(--button-secondaryFill);
border-radius: 8px;
word-break: break-word;
}
.address-list {
display: flex;
flex-direction: column;
gap: 1rem;
}
.address-item {
padding: 1.25rem;
background: var(--button-secondaryFill);
border-radius: 12px;
border-left: 4px solid var(--accent-15);
transition: all 0.2s ease;
}
.address-item:hover {
transform: translateX(4px);
box-shadow: 0px 2px 8px 0px var(--accent-shadow);
}
.address-item.default {
border-left-color: var(--accent-accent);
background: var(--accent-15);
}
.address-type {
display: flex;
align-items: center;
gap: 0.5rem;
background: var(--card-card);
border: none;
border-radius: 12px;
padding: 12px 16px;
gap: 0.75rem;
margin-bottom: 0.5rem;
}
.address-type strong {
color: var(--text-primary);
font-family: 'Montserrat', sans-serif;
font-weight: 500;
font-size: 14px;
cursor: pointer;
transition: all 0.2s ease;
text-decoration: none;
box-shadow: 0px 1px var(--shadow-blur, 2px) 0px var(--accent-shadow);
}
.back-button:hover {
background: var(--button-secondaryFill);
transform: translateY(-1px);
box-shadow: 0px 2px var(--shadow-blur, 4px) 0px var(--accent-shadow);
}
.back-button svg {
width: 16px;
height: 16px;
fill: var(--text-primary);
}
.page-title {
color: var(--text-primary);
font-size: 24px;
font-size: 15px;
font-weight: 600;
}
.badge {
display: inline-block;
padding: 0.25rem 0.75rem;
background: var(--accent-accent);
color: white;
font-size: 11px;
font-weight: 600;
border-radius: 12px;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.address-details {
color: var(--text-secondary);
font-size: 14px;
line-height: 1.5;
}
.loading-spinner {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 4rem 2rem;
gap: 1.5rem;
}
.spinner {
width: 48px;
height: 48px;
border: 4px solid var(--accent-15);
border-top-color: var(--accent-accent);
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
to {
transform: rotate(360deg);
}
}
.loading-spinner p {
color: var(--text-secondary);
font-size: 16px;
margin: 0;
}
.k-content {
background-color: var(--background) !important;
}
.k-content h4 {
color: var(--text-primary) !important;
font-family: 'Montserrat', sans-serif !important;
font-size: 28px !important;
font-weight: 600 !important;
margin: 0 0 2rem 0 !important;
.info-message {
display: flex;
flex-direction: column;
align-items: center;
gap: 1.5rem;
padding: 3rem 2rem;
text-align: center;
}
.k-tabstrip-wrapper {
background: var(--card-card) !important;
border-radius: 24px !important;
overflow: hidden;
box-shadow: 0px 1px var(--shadow-blur, 2px) 0px var(--accent-shadow);
border: none !important;
}
.k-tabstrip {
background: var(--card-card) !important;
border: none !important;
}
.k-tabstrip-items {
background: var(--card-card) !important;
border: none !important;
border-radius: 24px 24px 0 0 !important;
padding: 0 20px !important;
}
.k-tabstrip-items .k-item {
background: transparent !important;
border: none !important;
margin: 0 !important;
border-radius: 0 !important;
}
.k-tabstrip-items .k-item .k-link {
color: var(--text-secondary) !important;
font-family: 'Montserrat', sans-serif !important;
font-weight: 500 !important;
font-size: 14px !important;
padding: 16px 20px !important;
border: none !important;
background: transparent !important;
border-radius: 0 !important;
transition: all 0.2s ease !important;
}
.k-tabstrip-items .k-item.k-state-active .k-link {
color: var(--accent-accent) !important;
font-weight: 600 !important;
border-bottom: 2px solid var(--accent-accent) !important;
}
.k-tabstrip-items .k-item:hover .k-link {
color: var(--text-primary) !important;
}
.k-tabstrip .k-content {
background: var(--card-card) !important;
border: none !important;
padding: 20px !important;
border-radius: 0 0 24px 24px !important;
}
form {
background: transparent !important;
}
.container-fluid.details {
background: transparent !important;
margin-bottom: 2rem;
}
.row {
margin-bottom: 1rem;
align-items: center;
}
.windowInputLabel {
color: var(--text-primary) !important;
font-family: 'Montserrat', sans-serif !important;
font-weight: 500 !important;
font-size: 14px !important;
margin: 0 !important;
}
input[type="text"],
input[type="password"],
input[type="email"],
select,
textarea {
background: var(--button-secondaryFill) !important;
border: 1px solid var(--accent-15) !important;
border-radius: 12px !important;
padding: 12px 16px !important;
color: var(--text-primary) !important;
font-family: 'Montserrat', sans-serif !important;
font-size: 14px !important;
transition: all 0.2s ease !important;
}
input[type="text"]:focus,
input[type="password"]:focus,
input[type="email"]:focus,
select:focus,
textarea:focus {
outline: none !important;
border-color: var(--accent-accent) !important;
box-shadow: 0 0 0 3px var(--accent-15) !important;
}
.k-checkbox {
appearance: none;
width: 20px !important;
height: 20px !important;
border: 2px solid var(--accent-15) !important;
border-radius: 4px !important;
background: var(--button-secondaryFill) !important;
cursor: pointer !important;
position: relative !important;
transition: all 0.2s ease !important;
}
.k-checkbox:checked {
background: var(--accent-accent) !important;
border-color: var(--accent-accent) !important;
}
.k-checkbox:checked::after {
content: '✓';
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
.info-message svg {
color: white;
font-size: 12px;
font-weight: bold;
}
.k-checkbox-label {
margin-left: 8px !important;
color: var(--text-primary) !important;
font-family: 'Montserrat', sans-serif !important;
cursor: pointer !important;
.info-message p {
color: var(--text-secondary);
font-size: 16px;
line-height: 1.6;
margin: 0;
max-width: 600px;
}
.k-button,
button {
background: var(--accent-accent) !important;
border: none !important;
border-radius: 12px !important;
padding: 12px 24px !important;
color: white !important;
font-family: 'Montserrat', sans-serif !important;
font-weight: 600 !important;
font-size: 14px !important;
cursor: pointer !important;
transition: all 0.2s ease !important;
box-shadow: 0px 1px var(--shadow-blur, 2px) 0px var(--accent-shadow) !important;
.error-message {
display: flex;
flex-direction: column;
align-items: center;
gap: 1.5rem;
padding: 4rem 2rem;
text-align: center;
}
.k-button:hover,
button:hover {
background: var(--accent-secondary) !important;
transform: translateY(-1px) !important;
box-shadow: 0px 2px var(--shadow-blur, 4px) 0px var(--accent-shadow) !important;
.error-message svg {
color: #e74c3c;
}
.k-button:active,
button:active {
transform: translateY(0) !important;
.error-message p {
color: var(--text-secondary);
font-size: 16px;
margin: 0;
}
@media (max-width: 768px) {
.content-container {
padding: 1rem;
}
.firka-header {
padding: 1rem;
}
.page-title {
font-size: 20px;
}
.k-content h4 {
font-size: 24px !important;
}
.k-tabstrip-items {
padding: 0 10px !important;
}
.k-tabstrip-items .k-item .k-link {
padding: 12px 16px !important;
font-size: 13px !important;
}
.security-btn {
display: inline-flex;
align-items: center;
gap: 0.75rem;
padding: 1rem 2rem;
background: var(--accent-accent);
color: white;
border: none;
border-radius: 12px;
font-family: 'Montserrat', sans-serif;
font-size: 15px;
font-weight: 600;
cursor: pointer;
transition: all 0.2s ease;
box-shadow: 0px 2px 4px 0px var(--accent-shadow);
}
.security-btn:hover {
background: var(--accent-secondary);
transform: translateY(-2px);
box-shadow: 0px 4px 8px 0px var(--accent-shadow);
}
.security-btn:active {
transform: translateY(0);
}
.security-btn svg {
flex-shrink: 0;
}
@keyframes fadeIn {
from {
@@ -327,159 +361,267 @@ button:active {
}
}
.k-tabstrip-wrapper {
.profile-wrapper {
animation: fadeIn 0.4s ease forwards;
}
.data-section {
animation: fadeIn 0.5s ease forwards;
}
.k-widget,
.k-header {
background: var(--card-card) !important;
color: var(--text-primary) !important;
border: none !important;
.data-section:nth-child(2) {
animation-delay: 0.1s;
}
.k-state-default {
background: transparent !important;
border: none !important;
.data-section:nth-child(3) {
animation-delay: 0.2s;
}
.k-state-active {
background: transparent !important;
.data-section:nth-child(4) {
animation-delay: 0.3s;
}
@media (max-width: 1024px) {
.profile-wrapper {
grid-template-columns: 1fr;
gap: 1.5rem;
}
.k-overlay,
.k-window,
.k-notification {
display: none !important;
.profile-sidebar {
position: static;
}
.profile-tabs {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 0.5rem;
padding: 0.5rem;
}
.profile-tab {
flex-direction: column;
justify-content: center;
align-items: center;
text-align: center;
gap: 0.5rem;
padding: 1rem 0.5rem;
font-size: 13px;
min-height: 75px;
}
.profile-tab svg {
width: 22px;
height: 22px;
}
.profile-tab span {
line-height: 1.2;
word-break: break-word;
hyphens: auto;
}
.data-grid {
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
}
}
@media (max-width: 768px) {
.profile-container {
padding: 0.75rem;
}
.main-content .content-content {
display: block !important;
.profile-wrapper {
gap: 0.75rem;
}
.profile-content {
padding: 1rem;
}
.data-grid {
grid-template-columns: 1fr;
gap: 1rem;
}
.tab-header h2 {
font-size: 22px;
}
.data-section h3 {
font-size: 17px;
}
.profile-tabs {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 0.375rem;
padding: 0.375rem;
}
.profile-tab {
flex-direction: column;
justify-content: center;
align-items: center;
text-align: center;
gap: 0.375rem;
padding: 0.625rem 0.25rem;
font-size: 11px;
min-height: 55px;
}
.profile-tab svg {
width: 18px;
height: 18px;
}
.profile-tab span {
line-height: 1.1;
word-break: break-word;
hyphens: auto;
}
.address-item {
padding: 1rem;
}
.security-btn {
width: 100%;
justify-content: center;
}
.info-message,
.error-message,
.loading-spinner {
padding: 2rem 1rem;
}
}
@media (max-width: 480px) {
.profile-container {
padding: 0.5rem;
}
div[style*="display:flex;justify-content:space-between"] {
display: flex !important;
justify-content: space-between !important;
align-items: center !important;
margin-top: 2rem !important;
padding-top: 2rem !important;
border-top: 1px solid var(--accent-15) !important;
.profile-wrapper {
gap: 0.5rem;
}
.profile-content {
padding: 0.875rem;
border-radius: 12px;
}
.tab-header {
margin-bottom: 1.25rem;
}
.tab-header h2 {
font-size: 18px;
}
.data-section h3 {
font-size: 15px;
margin-bottom: 1rem;
}
.data-item label {
font-size: 11px;
}
.data-item span {
font-size: 13px;
padding: 0.5rem;
}
.profile-tabs {
padding: 0.25rem;
gap: 0.25rem;
border-radius: 10px;
}
.profile-tab {
padding: 0.5rem 0.25rem;
min-height: 50px;
font-size: 10px;
border-radius: 8px;
}
.profile-tab svg {
width: 16px;
height: 16px;
}
.profile-tab span {
font-size: 10px;
}
.data-section {
margin-bottom: 1.75rem;
}
.address-item {
padding: 0.75rem;
}
.badge {
font-size: 9px;
padding: 0.2rem 0.5rem;
}
}
div[style*="display:flex;justify-content:space-between"] label {
color: var(--text-secondary) !important;
font-size: 12px !important;
font-style: italic !important;
margin: 0 !important;
@media (prefers-color-scheme: dark) {
.error-message svg {
color: #ff6b6b;
}
}
.hidden-contact-info {
display: none !important;
visibility: hidden !important;
@media print {
.profile-sidebar,
.security-btn,
.kreta-header,
.mobile-header,
.mobile-bottom-nav {
display: none !important;
}
.profile-wrapper {
grid-template-columns: 1fr;
}
.profile-content {
box-shadow: none;
border: 1px solid #ddd;
}
.tab-content {
display: block !important;
}
.data-section {
page-break-inside: avoid;
}
}
.hidden-tab {
display: none !important;
.profile-tab:focus,
.security-btn:focus {
outline: 2px solid var(--accent-accent);
outline-offset: 2px;
}
#ProfilTab-3 {
padding: 20px;
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
min-height: 500px;
.profile-tab:focus:not(:focus-visible),
.security-btn:focus:not(:focus-visible) {
outline: none;
}
#ProfilTab-3 .container-fluid {
background: white;
border-radius: 12px;
padding: 30px;
margin-top: 20px;
html {
scroll-behavior: smooth;
}
#ProfilTab-3 h4 {
color: #2c3e50;
font-weight: 600;
margin-bottom: 25px;
padding-bottom: 10px;
border-bottom: 3px solid #3498db;
display: inline-block;
}
#ProfilTab-3 .row {
margin-bottom: 20px;
padding: 15px;
background: #f8f9fa;
border-radius: 8px;
border-left: 4px solid #3498db;
transition: all 0.3s ease;
}
#ProfilTab-3 .row:hover {
background: #e3f2fd;
transform: translateX(5px);
box-shadow: 0 2px 10px rgba(52, 152, 219, 0.2);
}
#ProfilTab-3 .windowInputLabel {
color: #34495e;
font-weight: 500;
font-size: 14px;
}
#ProfilTab-3 .k-button {
background: linear-gradient(135deg, #3498db, #2980b9);
border: none;
border-radius: 6px;
padding: 10px 20px;
::selection {
background: var(--accent-accent);
color: white;
font-weight: 500;
transition: all 0.3s ease;
}
#ProfilTab-3 .k-button:hover {
background: linear-gradient(135deg, #2980b9, #1f5f8b);
transform: translateY(-2px);
box-shadow: 0 4px 15px rgba(52, 152, 219, 0.4);
::-moz-selection {
background: var(--accent-accent);
color: white;
}
#ProfilTab-3 .k-input {
border: 2px solid #e0e6ed;
border-radius: 6px;
padding: 10px;
transition: border-color 0.3s ease;
}
#ProfilTab-3 .k-input:focus {
border-color: #3498db;
box-shadow: 0 0 0 3px rgba(52, 152, 219, 0.1);
}
#ProfilTab-3 .alert {
border-radius: 8px;
border: none;
padding: 15px;
margin: 15px 0;
}
#ProfilTab-3 .alert-info {
background: linear-gradient(135deg, #e3f2fd, #bbdefb);
color: #1565c0;
}
#ProfilTab-3 .alert-success {
background: linear-gradient(135deg, #e8f5e8, #c8e6c9);
color: #2e7d32;
}
#ProfilTab-3 .alert-warning {
background: linear-gradient(135deg, #fff3e0, #ffcc02);
color: #ef6c00;
}
.details .row {
border-bottom: none !important;
}

View File

@@ -1,228 +1,497 @@
(function() {
'use strict';
function hideLoadingScreen() {
const loadingElement = document.getElementById('KretaProgressBar');
if (loadingElement) {
loadingElement.style.display = 'none !important';
loadingElement.style.visibility = 'hidden';
loadingElement.style.opacity = '0';
loadingElement.remove();
}
const TABS = {
MY_DATA: 'my-data',
PASSWORD: 'password',
SECURITY: 'security'
};
const loadingElements = document.querySelectorAll('[class*="loading"], [id*="loading"], [class*="Loading"], [id*="Loading"]');
loadingElements.forEach(el => {
el.style.display = 'none !important';
el.style.visibility = 'hidden';
el.style.opacity = '0';
});
let currentTab = TABS.MY_DATA;
let profileData = null;
let addressData = null;
function getApiUrls(subdomain) {
return {
PROFILE_DATA: `https://${subdomain}.e-kreta.hu/Adminisztracio/Profil/SajatAdatlapPopUp`,
ADDRESS_DATA: `https://${subdomain}.e-kreta.hu/api/ProfilApi/GetElerhetosegCimGrid?sort=&page=1&pageSize=100&group=&filter=&data=%7B%7D&_=`
};
}
function addBackButton() {
function hideOriginalElements() {
const elementsToHide = [
'#KretaProgressBar',
'.main-header',
'.main-menu',
'.main-sidebar',
'.content-header',
'.favoriteIconContainer',
'#frissitesDatumDiv',
'#layout_navigationBar',
'.navbar',
'.sidebar-container',
'#sidepanel_tabs',
'.sidepanel-wrapper',
'.main-footer2',
'.lakatimg',
'.modalContainer',
'.modalOuter',
'#ProfilTab'
];
if (document.getElementById('firka-back-button')) {
return;
}
const backButton = document.createElement('button');
backButton.id = 'firka-back-button';
backButton.textContent = '← Vissza';
backButton.style.cssText = `
position: static;
margin: 20px;
z-index: 100;
background-color: var(--card-background, #ffffff);
color: var(--text-primary, #333333);
border: 1px solid var(--border-color, #e0e0e0);
border-radius: 8px;
padding: 10px 16px;
font-family: 'Montserrat', sans-serif;
font-size: 14px;
font-weight: 500;
cursor: pointer;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
transition: all 0.2s ease;
display: inline-flex;
align-items: center;
gap: 8px;
width: auto;
`;
backButton.addEventListener('mouseenter', function() {
this.style.backgroundColor = 'var(--card-hover, #f5f5f5)';
this.style.transform = 'translateY(-1px)';
this.style.boxShadow = '0 4px 12px rgba(0, 0, 0, 0.15)';
elementsToHide.forEach(selector => {
const elements = document.querySelectorAll(selector);
elements.forEach(el => {
el.style.display = 'none';
el.style.visibility = 'hidden';
});
});
backButton.addEventListener('mouseleave', function() {
this.style.backgroundColor = 'var(--card-background, #ffffff)';
this.style.transform = 'translateY(0)';
this.style.boxShadow = '0 2px 8px rgba(0, 0, 0, 0.1)';
document.body.innerHTML = '';
}
async function createNavbar() {
const header = await createTemplate.header();
const headerContainer = document.createElement('div');
headerContainer.innerHTML = header;
document.body.appendChild(headerContainer);
setupUserDropdown();
setupSettingsButton();
}
function setupUserDropdown() {
const userBtn = document.querySelector('.user-dropdown-btn');
const userDropdown = document.querySelector('.user-dropdown');
userBtn?.addEventListener('click', (e) => {
e.stopPropagation();
userDropdown?.classList.toggle('show');
userBtn?.classList.toggle('open');
});
backButton.addEventListener('click', function() {
window.history.back();
const mobileUserBtn = document.querySelector('#mobileUserBtn');
const mobileUserDropdown = document.querySelector('#mobileUserDropdown');
mobileUserBtn?.addEventListener('click', (e) => {
e.stopPropagation();
mobileUserDropdown?.classList.toggle('show');
mobileUserBtn?.classList.toggle('active');
});
document.body.insertBefore(backButton, document.body.firstChild);
document.addEventListener('click', (e) => {
if (!userBtn?.contains(e.target) && !userDropdown?.contains(e.target)) {
userDropdown?.classList.remove('show');
userBtn?.classList.remove('open');
}
}
function hideMainFooter2() {
const footer2 = document.querySelector('.main-footer2');
if (footer2) {
footer2.style.display = 'none';
}
}
function hideLakatImg() {
const lakatImg = document.querySelector('.lakatimg');
if (lakatImg) {
lakatImg.style.display = 'none';
}
}
function hideCustomUserSettingsTab() {
const firstTab = document.querySelector('#ProfilTab .k-tabstrip-items li[aria-controls="ProfilTab-1"]');
if (firstTab) {
firstTab.classList.add('hidden-tab');
}
const tabLinks = document.querySelectorAll('#ProfilTab .k-tabstrip-items .k-link');
tabLinks.forEach(link => {
if (link.textContent && link.textContent.includes('Egyedi felhasználó beállítások')) {
const parentTab = link.closest('li');
if (parentTab) {
parentTab.classList.add('hidden-tab');
}
if (!mobileUserBtn?.contains(e.target) && !mobileUserDropdown?.contains(e.target)) {
mobileUserDropdown?.classList.remove('show');
mobileUserBtn?.classList.remove('active');
}
});
const contentPanel = document.querySelector('#ProfilTab-1');
if (contentPanel) {
contentPanel.classList.add('hidden-tab');
const mobileDropdownItems = document.querySelectorAll('.mobile-dropdown-item');
mobileDropdownItems.forEach(item => {
item.addEventListener('click', () => {
mobileUserDropdown?.classList.remove('show');
mobileUserBtn?.classList.remove('active');
});
});
}
function setupSettingsButton() {
document.getElementById('settingsBtn')?.addEventListener('click', (e) => {
e.preventDefault();
e.stopPropagation();
const url = chrome.runtime.getURL('settings/index.html');
window.open(url, '_blank', 'width=400,height=600');
});
document.getElementById('mobileSettingsBtn')?.addEventListener('click', (e) => {
e.preventDefault();
e.stopPropagation();
const url = chrome.runtime.getURL('settings/index.html');
window.open(url, '_blank', 'width=400,height=600');
});
}
function createProfilePage() {
const t = window.LanguageManager?.t || ((key) => key);
const container = document.createElement('div');
container.className = 'profile-container';
container.innerHTML = `
<div class="profile-wrapper">
<div class="profile-sidebar">
<div class="profile-tabs">
<button class="profile-tab active" data-tab="${TABS.MY_DATA}">
<svg viewBox="0 0 24 24" width="20" height="20">
<path fill="currentColor" d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"/>
</svg>
<span>${t('profile.tab_my_data')}</span>
</button>
<button class="profile-tab" data-tab="${TABS.PASSWORD}">
<svg viewBox="0 0 24 24" width="20" height="20">
<path fill="currentColor" d="M18 8h-1V6c0-2.76-2.24-5-5-5S7 3.24 7 6v2H6c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V10c0-1.1-.9-2-2-2zm-6 9c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2zm3.1-9H8.9V6c0-1.71 1.39-3.1 3.1-3.1 1.71 0 3.1 1.39 3.1 3.1v2z"/>
</svg>
<span>${t('profile.tab_password')}</span>
</button>
<button class="profile-tab" data-tab="${TABS.SECURITY}">
<svg viewBox="0 0 24 24" width="20" height="20">
<path fill="currentColor" d="M12 1L3 5v6c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V5l-9-4zm0 10.99h7c-.53 4.12-3.28 7.79-7 8.94V12H5V6.3l7-3.11v8.8z"/>
</svg>
<span>${t('profile.tab_security')}</span>
</button>
</div>
</div>
<div class="profile-content">
<div id="tab-${TABS.MY_DATA}" class="tab-content active">
<div class="loading-spinner">
<div class="spinner"></div>
<p>${t('profile.loading_data')}</p>
</div>
</div>
<div id="tab-${TABS.PASSWORD}" class="tab-content">
<div class="tab-header">
<h2>${t('profile.tab_password')}</h2>
</div>
<div class="info-message">
<svg viewBox="0 0 24 24" width="24" height="24">
<path fill="currentColor" d="M11 15h2v2h-2zm0-8h2v6h-2zm.99-5C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z"/>
</svg>
<p>${t('profile.password_change_unavailable')}</p>
</div>
</div>
<div id="tab-${TABS.SECURITY}" class="tab-content">
<div class="tab-header">
<h2>${t('profile.tab_security')}</h2>
</div>
<div class="info-message">
<p>${t('profile.security_settings_info')}</p>
<button id="security-redirect-btn" class="security-btn">
<svg viewBox="0 0 24 24" width="20" height="20">
<path fill="currentColor" d="M12 1L3 5v6c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V5l-9-4zm0 10.99h7c-.53 4.12-3.28 7.79-7 8.94V12H5V6.3l7-3.11v8.8z"/>
</svg>
${t('profile.open_security_settings')}
</button>
</div>
</div>
</div>
</div>
`;
document.body.appendChild(container);
}
async function fetchProfileData() {
try {
const subdomain = await storageManager.get('schoolSubdomain', '');
if (!subdomain) {
console.error('Nincs beállítva az iskola alcím');
return null;
}
const apiUrls = getApiUrls(subdomain);
const response = await fetch(apiUrls.PROFILE_DATA);
const html = await response.text();
return parseProfileHTML(html);
} catch (error) {
console.error('Hiba a profil adatok lekérésekor:', error);
return null;
}
}
function hideAdditionalContactInfo() {
async function fetchAddressData() {
try {
const subdomain = await storageManager.get('schoolSubdomain', '');
if (!subdomain) {
console.error('Nincs beállítva az iskola alcím');
return null;
}
function hideElementsWithText(text) {
const elements = document.querySelectorAll('h4');
elements.forEach(h4 => {
if (h4.textContent && h4.textContent.includes(text)) {
// Hide the parent row
let parent = h4.closest('.row');
if (parent) {
parent.classList.add('hidden-contact-info');
const apiUrls = getApiUrls(subdomain);
const timestamp = new Date().getTime();
const response = await fetch(apiUrls.ADDRESS_DATA + timestamp);
const data = await response.json();
return data;
} catch (error) {
console.error('Hiba a cím adatok lekérésekor:', error);
return null;
}
}
function parseProfileHTML(html) {
const parser = new DOMParser();
const doc = parser.parseFromString(html, 'text/html');
const data = {
personal: {},
contact: {},
bankAccount: {},
studentCard: {}
};
const personalFields = [
{ id: 'AlapAdat_CsaladiNev', key: 'familyName' },
{ id: 'AlapAdat_Utonev', key: 'firstName' },
{ id: 'AlapAdat_SzuletesiCsaladNev', key: 'birthFamilyName' },
{ id: 'AlapAdat_SzuletesiUtonev', key: 'birthFirstName' },
{ id: 'AlapAdat_AnyjaCsaladiNeve', key: 'motherFamilyName' },
{ id: 'AlapAdat_AnyjaUtonev', key: 'motherFirstName' },
{ id: 'AlapAdat_SzuletesiIdo_SDATE', key: 'birthDate' },
{ id: 'AlapAdat_SzuletesiHely', key: 'birthPlace' },
{ id: 'AlapAdat_SzuletesiOrszag', key: 'birthCountry' },
{ id: 'AlapAdat_Anyanyelv', key: 'motherTongue' },
{ id: 'AlapAdat_Allampolgarsag', key: 'citizenship' },
{ id: 'AlapAdat_OsztalyfonokNev', key: 'classTeacher' },
{ id: 'AlapAdat_OsztalyNev', key: 'className' },
{ id: 'AlapAdat_TeremNev', key: 'classroom' },
{ id: 'AlapAdat_BelepesiNev', key: 'username' }
];
personalFields.forEach(field => {
const label = doc.querySelector(`label[displayfor="${field.id}"]`);
if (label) {
data.personal[field.key] = {
key: field.key,
value: label.textContent.trim()
};
}
});
const phoneInput = doc.querySelector('#Elerhetosegek_ErtesitesiTelefon_TelefonSzam');
const emailInput = doc.querySelector('#Elerhetosegek_ErtesitesiEmail_EmailCim');
if (phoneInput) {
data.contact.phone = {
key: 'phone',
value: phoneInput.value || ''
};
}
if (emailInput) {
data.contact.email = {
key: 'email',
value: emailInput.value || ''
};
}
const bankFields = [
{ id: 'BankszamlaSzam', key: 'accountNumber' },
{ id: 'SzamlavezetoBank', key: 'bankName' },
{ id: 'BankszamlaTulajdonosNeve', key: 'accountOwner' }
];
bankFields.forEach(field => {
const input = doc.querySelector(`#${field.id}`);
if (input) {
data.bankAccount[field.key] = {
key: field.key,
value: input.value || ''
};
}
});
const cardFields = [
{ id: 'TanuloIgazolvany_Igazolvanyszam', key: 'cardNumber' },
{ id: 'TanuloIgazolvany_AdoazonositoJel', key: 'taxId' },
{ id: 'TanuloIgazolvany_DiakigazolvanySzam', key: 'studentCardNumber' },
{ id: 'TanuloIgazolvany_TajSzam', key: 'socialSecurityNumber' }
];
cardFields.forEach(field => {
const label = doc.querySelector(`label[displayfor="${field.id}"]`);
if (label) {
data.studentCard[field.key] = {
key: field.key,
value: label.textContent.trim()
};
}
});
return data;
}
function renderProfileData() {
const t = window.LanguageManager?.t || ((key) => key);
const container = document.getElementById(`tab-${TABS.MY_DATA}`);
if (!profileData && !addressData) {
container.innerHTML = `
<div class="error-message">
<svg viewBox="0 0 24 24" width="48" height="48">
<path fill="currentColor" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"/>
</svg>
<p>${t('profile.loading_error')}</p>
</div>
`;
return;
}
let html = `<div class="tab-header"><h2>${t('profile.my_data_title')}</h2></div>`;
if (profileData && profileData.personal && Object.keys(profileData.personal).length > 0) {
html += `<div class="data-section"><h3>${t('profile.personal_data')}</h3><div class="data-grid">`;
Object.values(profileData.personal).forEach(field => {
if (field.value && field.value !== 'XY') {
html += `
<div class="data-item">
<label>${t(`profile.field_${field.key}`)}</label>
<span>${field.value}</span>
</div>
`;
}
});
html += '</div></div>';
}
if (profileData && profileData.contact && Object.keys(profileData.contact).length > 0) {
html += `<div class="data-section"><h3>${t('profile.contact_data')}</h3><div class="data-grid">`;
Object.values(profileData.contact).forEach(field => {
if (field.value) {
html += `
<div class="data-item">
<label>${t(`profile.field_${field.key}`)}</label>
<span>${field.value}</span>
</div>
`;
}
});
html += '</div></div>';
}
if (addressData && addressData.Data && addressData.Data.length > 0) {
html += `<div class="data-section"><h3>${t('profile.address_data')}</h3><div class="address-list">`;
addressData.Data.forEach(address => {
const fullAddress = `${address.Irsz} ${address.Varos}, ${address.Kozterulet} ${address.KozteruletJellegeNev || ''} ${address.HazSzam}${address.Emelet ? ' ' + address.Emelet : ''}${address.Ajto ? ' ' + address.Ajto : ''}`;
const isDefault = address.Alapertelmezett_BOOL;
html += `
<div class="address-item ${isDefault ? 'default' : ''}">
<div class="address-type">
<strong>${address.CimTipus_DNAME}</strong>
${isDefault ? `<span class="badge">${t('profile.default_address')}</span>` : ''}
</div>
<div class="address-details">${fullAddress}</div>
</div>
`;
});
html += '</div></div>';
}
if (profileData && profileData.bankAccount && Object.keys(profileData.bankAccount).length > 0) {
const hasData = Object.values(profileData.bankAccount).some(field => field.value);
if (hasData) {
html += `<div class="data-section"><h3>${t('profile.bank_account_data')}</h3><div class="data-grid">`;
Object.values(profileData.bankAccount).forEach(field => {
if (field.value) {
html += `
<div class="data-item">
<label>${t(`profile.field_${field.key}`)}</label>
<span>${field.value}</span>
</div>
`;
}
}
});
html += '</div></div>';
}
}
if (profileData && profileData.studentCard && Object.keys(profileData.studentCard).length > 0) {
const hasData = Object.values(profileData.studentCard).some(field => field.value && field.value !== 'XY');
if (hasData) {
html += `<div class="data-section"><h3>${t('profile.student_card_data')}</h3><div class="data-grid">`;
Object.values(profileData.studentCard).forEach(field => {
if (field.value && field.value !== 'XY') {
html += `
<div class="data-item">
<label>${t(`profile.field_${field.key}`)}</label>
<span>${field.value}</span>
</div>
`;
}
});
html += '</div></div>';
}
}
container.innerHTML = html;
}
function setupTabSwitching() {
const tabs = document.querySelectorAll('.profile-tab');
const tabContents = document.querySelectorAll('.tab-content');
tabs.forEach(tab => {
tab.addEventListener('click', () => {
const tabId = tab.getAttribute('data-tab');
tabs.forEach(t => t.classList.remove('active'));
tab.classList.add('active');
tabContents.forEach(tc => tc.classList.remove('active'));
document.getElementById(`tab-${tabId}`).classList.add('active');
currentTab = tabId;
});
});
}
async function setupSecurityRedirect() {
const btn = document.getElementById('security-redirect-btn');
if (btn) {
btn.addEventListener('click', async () => {
const subdomain = await storageManager.get('schoolSubdomain', '');
const url = `https://idp.e-kreta.hu/security?returnUrl=https%3A%2F%2F${subdomain}.e-kreta.hu%2FAdminisztracio%2FProfil`;
window.location.href = url;
});
}
hideElementsWithText('TOVÁBBI E-MAIL ELÉRHETŐSÉGEK');
hideElementsWithText('TOVÁBBI TELEFONSZÁMOK');
const rows = document.querySelectorAll('.row');
rows.forEach(row => {
const h4Elements = row.querySelectorAll('h4');
h4Elements.forEach(h4 => {
if (h4.textContent &&
(h4.textContent.includes('TOVÁBBI E-MAIL ELÉRHETŐSÉGEK') ||
h4.textContent.includes('TOVÁBBI TELEFONSZÁMOK'))) {
row.classList.add('hidden-contact-info');
}
});
});
}
function init() {
hideLoadingScreen();
addBackButton();
hideAdditionalContactInfo();
hideCustomUserSettingsTab();
hideMainFooter2();
hideLakatImg();
async function init() {
try {
hideOriginalElements();
const observer = new MutationObserver(() => {
hideAdditionalContactInfo();
hideCustomUserSettingsTab();
hideMainFooter2();
hideLakatImg();
});
observer.observe(document.body, {
childList: true,
subtree: true
});
if (typeof window.LanguageManager !== 'undefined' && window.LanguageManager.init) {
await window.LanguageManager.init();
}
await createNavbar();
createProfilePage();
setupTabSwitching();
setupSecurityRedirect();
[profileData, addressData] = await Promise.all([
fetchProfileData(),
fetchAddressData()
]);
renderProfileData();
} catch (error) {
console.error('Hiba az inicializálás során:', error);
}
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', init);
} else {
init();
}
window.addEventListener('load', init);
setTimeout(hideLoadingScreen, 1000);
let attempts = 0;
const maxAttempts = 20;
const aggressiveHide = setInterval(() => {
attempts++;
hideLoadingScreen();
if (attempts >= maxAttempts) {
clearInterval(aggressiveHide);
}
}, 500);
if (typeof MutationObserver !== 'undefined') {
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
mutation.addedNodes.forEach((node) => {
if (node.nodeType === 1) {
if (node.id === 'KretaProgressBar' ||
node.className && (node.className.includes('loading') || node.className.includes('Loading'))) {
node.style.display = 'none !important';
node.style.visibility = 'hidden';
node.style.opacity = '0';
if (node.parentNode) {
node.parentNode.removeChild(node);
}
}
}
});
});
});
observer.observe(document.body, {
childList: true,
subtree: true
});
}
})();
})();

View File

@@ -593,29 +593,6 @@ h2 {
margin: 0;
}
.modal-close {
display: flex;
align-items: center;
justify-content: center;
width: 32px;
height: 32px;
border: none;
border-radius: 8px;
background: var(--button-secondaryFill);
color: var(--text-secondary);
cursor: pointer;
transition: all 0.2s ease;
}
.modal-close:hover {
background: var(--accent-15);
color: var(--accent-accent);
}
.modal-close .material-icons-round {
font-size: 20px;
}
.modal-body {
padding: 16px;
}
@@ -840,7 +817,6 @@ h2 {
width: 100%;
min-height: 80px;
padding: 12px;
border: 1px solid var(--text-teritary);
border-radius: 8px;
background: var(--button-secondaryFill);
color: var(--text-primary);
@@ -851,11 +827,6 @@ h2 {
transition: border-color 0.2s ease;
}
.share-code-wrapper textarea:focus,
#importCode:focus {
border-color: var(--accent-accent);
}
.copy-btn {
position: absolute;
top: 8px;
@@ -1150,3 +1121,256 @@ h2 {
opacity: 1;
transform: translateY(0);
}
.update-modal .modal-content {
max-width: 500px;
}
.update-version-info {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
margin-bottom: 20px;
padding: 16px;
background: var(--button-secondaryFill);
border-radius: 12px;
}
.version-badge {
display: flex;
flex-direction: column;
gap: 4px;
flex: 1;
}
.version-badge.current {
text-align: left;
}
.version-badge.latest {
text-align: right;
}
.version-label {
font-size: 11px;
color: var(--text-secondary);
font-weight: 500;
}
.version-number {
font-size: 16px;
font-weight: 700;
color: var(--text-primary);
font-family: monospace;
}
.version-badge.latest .version-number {
color: var(--accent-accent);
}
.version-arrow {
color: var(--accent-accent);
font-size: 24px;
flex-shrink: 0;
}
.update-changelog-section {
margin-top: 16px;
}
.update-changelog-section h4 {
font-size: 14px;
font-weight: 600;
color: var(--text-primary);
margin: 0 0 12px 0;
}
.update-changelog {
max-height: 300px;
overflow-y: auto;
padding: 12px;
background: var(--button-secondaryFill);
border-radius: 8px;
font-size: 13px;
line-height: 1.6;
color: var(--text-secondary);
}
.update-changelog p {
margin: 0 0 8px 0;
color: var(--text-primary);
}
.update-changelog p:last-child {
margin-bottom: 0;
}
.update-changelog h1,
.update-changelog h2,
.update-changelog h3 {
color: var(--text-primary);
margin: 12px 0 8px 0;
font-weight: 600;
}
.update-changelog h1 {
font-size: 18px;
}
.update-changelog h2 {
font-size: 16px;
}
.update-changelog h3 {
font-size: 14px;
}
.update-changelog ul,
.update-changelog ol {
margin: 8px 0;
padding-left: 24px;
color: var(--text-primary);
}
.update-changelog li {
margin: 4px 0;
}
.update-changelog code {
background: var(--accent-15);
color: var(--accent-accent);
padding: 2px 6px;
border-radius: 4px;
font-family: monospace;
font-size: 12px;
}
.update-changelog pre {
background: var(--background);
color: var(--text-primary);
padding: 12px;
border-radius: 6px;
overflow-x: auto;
margin: 8px 0;
}
.update-changelog pre code {
background: transparent;
padding: 0;
}
.update-changelog a {
color: var(--accent-accent);
text-decoration: none;
font-weight: 500;
}
.update-changelog a:hover {
text-decoration: underline;
}
.update-changelog blockquote {
border-left: 3px solid var(--accent-accent);
padding-left: 12px;
margin: 8px 0;
color: var(--text-secondary);
font-style: italic;
}
.update-changelog strong {
color: var(--text-primary);
font-weight: 600;
}
.update-changelog em {
font-style: italic;
color: var(--text-secondary);
}
.update-button {
display: flex;
align-items: center;
gap: 6px;
text-decoration: none;
justify-content: center;
border-radius: 8px;
padding: 12px 16px;
}
.update-button .material-icons-round {
font-size: 18px;
}
.folio-ad-card {
display: flex;
align-items: center;
justify-content: space-between;
background: linear-gradient(135deg, #00D2A9 0%, #00b896 100%);
border-radius: 16px;
padding: 14px 16px;
margin: 4px 16px 16px;
text-decoration: none;
cursor: pointer;
transition: transform 0.15s ease, box-shadow 0.15s ease;
box-shadow: 0 2px 12px rgba(0, 210, 169, 0.35);
}
.folio-ad-card:hover {
transform: translateY(-1px);
box-shadow: 0 4px 16px rgba(0, 210, 169, 0.5);
}
.folio-ad-card:active {
transform: translateY(0);
}
.folio-ad-left {
display: flex;
align-items: center;
gap: 12px;
}
.folio-ad-logo {
width: 40px;
height: 40px;
border-radius: 10px;
object-fit: cover;
}
.folio-ad-text {
display: flex;
flex-direction: column;
gap: 2px;
}
.folio-ad-title {
font-size: 15px;
font-weight: 700;
color: #fff;
}
.folio-ad-desc {
font-size: 11px;
color: rgba(255, 255, 255, 0.85);
}
.folio-ad-right {
display: flex;
align-items: center;
gap: 4px;
background: rgba(255, 255, 255, 0.2);
border-radius: 8px;
padding: 6px 10px;
}
.folio-ad-right .material-icons-round {
font-size: 16px;
color: #fff;
}
.folio-ad-cta {
font-size: 12px;
font-weight: 600;
color: #fff;
}

View File

@@ -103,6 +103,19 @@
</div>
</div>
</div>
<a href="https://folio.zan1456.dev" target="_blank" class="folio-ad-card">
<div class="folio-ad-left">
<img src="../images/folio.png" alt="Folio" class="folio-ad-logo">
<div class="folio-ad-text">
<span class="folio-ad-title">Folio</span>
<span class="folio-ad-desc">Material You KRÉTA app Androidra</span>
</div>
</div>
<div class="folio-ad-right">
<span class="material-icons-round">download</span>
<span class="folio-ad-cta">Letöltés</span>
</div>
</a>
</div>
<div class="tab-content" id="tab-settings">
@@ -188,13 +201,43 @@
</div>
<div class="modal-overlay" id="updateModal">
<div class="modal-content update-modal">
<div class="modal-header">
<h3 data-i18n="settings.update.title">Új verzió érhető el!</h3>
</div>
<div class="modal-body">
<div class="update-version-info">
<div class="version-badge current">
<span class="version-label" data-i18n="settings.update.current_version">Jelenlegi verzió:</span>
<span class="version-number" id="currentVersion">-</span>
</div>
<span class="material-icons-round version-arrow">arrow_forward</span>
<div class="version-badge latest">
<span class="version-label" data-i18n="settings.update.latest_version">Legújabb verzió:</span>
<span class="version-number" id="latestVersion">-</span>
</div>
</div>
<div class="update-changelog-section">
<h4 data-i18n="settings.update.whats_new">Újdonságok:</h4>
<div class="update-changelog" id="updateChangelog">
<p data-i18n="settings.update.loading">Betöltés...</p>
</div>
</div>
</div>
<div class="modal-footer">
<button class="btn-secondary" id="dismissUpdate" data-i18n="settings.update.dismiss">Bezárás</button>
<a class="btn-primary update-button" id="updateButton" href="#" target="_blank">
<span data-i18n="settings.update.download">Letöltés</span>
</a>
</div>
</div>
</div>
<div class="modal-overlay" id="themeEditorModal">
<div class="modal-content theme-editor-modal">
<div class="modal-header">
<h3 id="themeEditorTitle" data-i18n="settings.custom_themes.create">Új téma létrehozása</h3>
<button class="modal-close" id="closeThemeEditor">
<span class="material-icons-round">close</span>
</button>
</div>
<div class="modal-body">
<div class="theme-form">
@@ -265,9 +308,6 @@
<div class="modal-content share-modal">
<div class="modal-header">
<h3 data-i18n="settings.custom_themes.share">Téma megosztása</h3>
<button class="modal-close" id="closeShareModal">
<span class="material-icons-round">close</span>
</button>
</div>
<div class="modal-body">
<p data-i18n="settings.custom_themes.share_description">Másold ki a kódot és oszd meg másokkal:</p>
@@ -288,9 +328,6 @@
<div class="modal-content import-modal">
<div class="modal-header">
<h3 data-i18n="settings.custom_themes.import">Téma importálása</h3>
<button class="modal-close" id="closeImportModal">
<span class="material-icons-round">close</span>
</button>
</div>
<div class="modal-body">
<p data-i18n="settings.custom_themes.import_description">Illeszd be a téma kódot:</p>
@@ -304,8 +341,6 @@
</div>
</div>
<script src="../tools/sentry-browser.min.js"></script>
<script src="../tools/sentry.js"></script>
<script src="../tools/helper.js"></script>
<script src="../tools/storageManager.js"></script>
<script src="../global/language.js"></script>

View File

@@ -1048,6 +1048,7 @@ document.addEventListener("DOMContentLoaded", async () => {
await initTabs();
await initErrorReporting();
await checkForUpdates();
});
async function initErrorReporting() {
@@ -1067,3 +1068,101 @@ async function initErrorReporting() {
});
});
}
async function checkForUpdates() {
try {
const manifest = chrome.runtime.getManifest();
const currentVersion = manifest.version;
const response = await fetch('https://api.github.com/repos/QwIT-Development/firka-extension/releases/latest');
if (!response.ok) {
console.error('Failed to fetch latest release');
return;
}
const latestRelease = await response.json();
const latestVersion = latestRelease.tag_name.replace(/^v/, '');
if (compareVersions(latestVersion, currentVersion) > 0) {
showUpdateModal(currentVersion, latestVersion, latestRelease);
}
} catch (error) {
console.error('Error checking for updates:', error);
}
}
function compareVersions(v1, v2) {
const parts1 = v1.split('.').map(Number);
const parts2 = v2.split('.').map(Number);
for (let i = 0; i < Math.max(parts1.length, parts2.length); i++) {
const part1 = parts1[i] || 0;
const part2 = parts2[i] || 0;
if (part1 > part2) return 1;
if (part1 < part2) return -1;
}
return 0;
}
function parseMarkdown(markdown) {
let html = markdown;
html = html.replace(/^### (.*$)/gim, '<h3>$1</h3>');
html = html.replace(/^## (.*$)/gim, '<h2>$1</h2>');
html = html.replace(/^# (.*$)/gim, '<h1>$1</h1>');
html = html.replace(/\*\*\*(.+?)\*\*\*/g, '<strong><em>$1</em></strong>');
html = html.replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>');
html = html.replace(/\*(.+?)\*/g, '<em>$1</em>');
html = html.replace(/__(.+?)__/g, '<strong>$1</strong>');
html = html.replace(/_(.+?)_/g, '<em>$1</em>');
html = html.replace(/`([^`]+)`/g, '<code>$1</code>');
html = html.replace(/```([^```]+)```/g, '<pre><code>$1</code></pre>');
html = html.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2" target="_blank">$1</a>');
html = html.replace(/^> (.+)/gim, '<blockquote>$1</blockquote>');
html = html.replace(/^\* (.+)$/gim, '<li>$1</li>');
html = html.replace(/^- (.+)$/gim, '<li>$1</li>');
html = html.replace(/(<li>.*<\/li>)/s, '<ul>$1</ul>');
html = html.replace(/^\d+\. (.+)$/gim, '<li>$1</li>');
html = html.replace(/\n\n/g, '</p><p>');
html = html.replace(/^(?!<[hou]|<li|<pre|<blockquote)(.+)$/gim, '<p>$1</p>');
html = html.replace(/<p><\/p>/g, '');
html = html.replace(/<p>(<[hou])/g, '$1');
html = html.replace(/(<\/[hou]l?>)<\/p>/g, '$1');
return html;
}
function showUpdateModal(currentVersion, latestVersion, releaseData) {
const modal = document.getElementById('updateModal');
const currentVersionEl = document.getElementById('currentVersion');
const latestVersionEl = document.getElementById('latestVersion');
const changelogEl = document.getElementById('updateChangelog');
const updateButton = document.getElementById('updateButton');
currentVersionEl.textContent = `v${currentVersion}`;
latestVersionEl.textContent = `v${latestVersion}`;
const changelog = releaseData.body || 'Nincs elérhető változásnapló.';
changelogEl.innerHTML = parseMarkdown(changelog);
updateButton.href = releaseData.html_url;
modal.classList.add('active');
document.getElementById('dismissUpdate').addEventListener('click', closeUpdateModal);
}
function closeUpdateModal() {
const modal = document.getElementById('updateModal');
modal.classList.remove('active');
}

View File

@@ -152,8 +152,6 @@
</div>
</div>
<script src="../tools/sentry-browser.min.js"></script>
<script src="../tools/sentry.js"></script>
<script src="../tools/storageManager.js"></script>
<script src="../global/language.js"></script>
<script src="setup.js"></script>

View File

@@ -147,7 +147,8 @@ body {
transition:all 0.3s cubic-bezier(0.4,0,0.2,1);
transform:translateY(0);
}
.lesson-card:hover {
.lesson-card:hover,
.lesson-card.group-hover {
transform:translateY(-4px);
box-shadow:0 8px 12px var(--accent-shadow);
}
@@ -162,6 +163,28 @@ body {
opacity:0.5;
text-decoration:line-through;
}
.lesson-card.lesson-spans-multiple {
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
.lesson-card.lesson-continuation.continuation-middle {
border-radius: 0;
}
.lesson-card.lesson-continuation.continuation-end {
border-top-left-radius: 0;
border-top-right-radius: 0;
}
.lesson-slot.has-multi-start {
padding-bottom: 0;
}
.lesson-slot.has-continuation {
padding-top: 0;
}
.lesson-subject {
align-self:stretch;
color:var(--text-primary);

View File

@@ -160,7 +160,7 @@
}
function getLessonKey(lesson) {
return `${lesson.subject}_${lesson.startTime}_${lesson.day}`;
return `${lesson.subject}_${lesson.startTime}_${lesson.date}`;
}
async function updateHomeworkIconsFromCookie() {
@@ -313,7 +313,16 @@
}
}
async function loadTestDetailsFromAPI(testId) {
let cachedTestData = null;
let testDataTimestamp = 0;
const TEST_DATA_CACHE_DURATION = 60000;
async function loadAllTestDataFromAPI() {
const now = Date.now();
if (cachedTestData && (now - testDataTimestamp) < TEST_DATA_CACHE_DURATION) {
return cachedTestData;
}
try {
const timestamp = Date.now();
const apiUrl = `https://${window.location.hostname}/api/TanuloBejelentettSzamonkeresekApi/GetBejelentettSzamonkeresekGrid?sort=SzamonkeresDatuma-asc~Oraszam-asc&page=1&pageSize=1000&group=&filter=&data=%7B%22RegiSzamonkeresekElrejtese%22%3Afalse%7D&_=${timestamp}`;
@@ -327,15 +336,30 @@
});
if (!response.ok) {
throw new Error(
`Számonkérés API hiba: ${response.status}`,
);
throw new Error(`Számonkérés API hiba: ${response.status}`);
}
const data = await response.json();
const testData = data.Data || [];
cachedTestData = data.Data || [];
testDataTimestamp = now;
return cachedTestData;
} catch (error) {
console.error("Számonkérés adatok betöltési hiba:", error);
return [];
}
}
async function getTestTypeById(testId) {
const testData = await loadAllTestDataFromAPI();
const testDetail = testData.find(test => test.ID === testId.toString());
return testDetail ? testDetail.ErtekelesModNev : null;
}
async function loadTestDetailsFromAPI(testId) {
try {
const testData = await loadAllTestDataFromAPI();
const testDetail = testData.find(test => test.ID === testId.toString());
if (testDetail) {
return {
name: testDetail.SzamonkeresMegnevezes || 'Nincs megnevezés',
@@ -343,7 +367,7 @@
announceDate: testDetail.BejelentesDatuma ? new Date(testDetail.BejelentesDatuma).toLocaleDateString('hu-HU') : 'Nincs dátum'
};
}
return null;
} catch (error) {
console.error("Számonkérés adatok betöltési hiba:", error);
@@ -410,6 +434,7 @@
originalTeacher: "",
room: "",
day: dayIndex,
date: weekDates[dayIndex]?.fullDate || eventDate.toISOString().split('T')[0],
isSubstituted: false,
isCancelled: false,
hasHomework: false,
@@ -446,9 +471,9 @@
"Ismeretlen tantárgy";
if (startTimeStr && subject) {
const isCancelled = event.isElmaradt || event.Elmaradt || event.cancelled || event.isCancelled ||
const isCancelled = event.isElmaradt || event.Elmaradt || event.cancelled || event.isCancelled ||
event.oraType === 6 || (event.title && event.title.toLowerCase().includes('elmarad'));
const lesson = {
startTime: startTimeStr,
endTime: endTimeStr,
@@ -457,14 +482,15 @@
originalTeacher: event.helyettesitoId ? teacher : "",
room: room,
day: dayIndex,
date: weekDates[dayIndex]?.fullDate || eventDate.toISOString().split('T')[0],
isSubstituted: !!event.helyettesitoId,
isCancelled: isCancelled,
hasHomework: event.hasHaziFeladat || false,
testInfo: event.hasBejelentettSzamonkeres
? event.Tema || LanguageManager.t("timetable.test_indicator")
: "",
testId: event.hasBejelentettSzamonkeres && event.BejelentettSzamonkeresIdList && event.BejelentettSzamonkeresIdList.length > 0
? event.BejelentettSzamonkeresIdList[0]
testId: event.hasBejelentettSzamonkeres && event.BejelentettSzamonkeresIdList && event.BejelentettSzamonkeresIdList.length > 0
? event.BejelentettSzamonkeresIdList[0]
: null,
testDetails: "",
homeworkDetails: "",
@@ -497,6 +523,15 @@
}
}
const testTypeMap = {};
const lessonsWithTests = lessons.filter(l => l.testId);
if (lessonsWithTests.length > 0) {
await loadAllTestDataFromAPI();
for (const lesson of lessonsWithTests) {
testTypeMap[lesson.testId] = await getTestTypeById(lesson.testId);
}
}
const times = [...new Set(regularLessons.map((l) => l.startTime))].sort(
(a, b) => {
const timeA = helper.convertTimeToMinutes(a);
@@ -504,6 +539,26 @@
return timeA - timeB;
},
);
function getLessonTimeSlots(lesson, allTimes) {
const startMinutes = helper.convertTimeToMinutes(lesson.startTime);
const endMinutes = helper.convertTimeToMinutes(lesson.endTime);
const slots = [];
for (let i = 0; i < allTimes.length; i++) {
const slotMinutes = helper.convertTimeToMinutes(allTimes[i]);
if (slotMinutes >= startMinutes && slotMinutes < endMinutes) {
slots.push(i);
}
}
return slots.length > 0 ? slots : [allTimes.indexOf(lesson.startTime)];
}
const lessonSlotMap = new Map();
regularLessons.forEach(lesson => {
const slots = getLessonTimeSlots(lesson, times);
lessonSlotMap.set(lesson, slots);
});
const days = [
LanguageManager.t("timetable.monday"),
LanguageManager.t("timetable.tuesday"),
@@ -569,38 +624,84 @@
const dayLessons = regularLessons.filter(
(l) => l.startTime === time && l.day === dayIndex,
);
const continuingInSlot = regularLessons.filter(lesson => {
if (lesson.day !== dayIndex) return false;
const slots = lessonSlotMap.get(lesson);
return slots && slots.includes(timeIndex) && slots[0] !== timeIndex;
});
const hasMultiLesson = dayLessons.some(lesson => {
const slots = lessonSlotMap.get(lesson);
return slots && slots.length > 1;
});
const lastLessonTime = lastLessonTimes[dayIndex];
const isAfterLastLesson = lastLessonTime && helper.convertTimeToMinutes(time) > helper.convertTimeToMinutes(lastLessonTime);
if (dayLessons.length === 0 && isAfterLastLesson) {
if (dayLessons.length === 0 && continuingInSlot.length === 0 && isAfterLastLesson) {
return `<div class="lesson-slot"></div>`;
}
if (continuingInSlot.length > 0) {
return `
<div class="lesson-slot ${dayLessons.length === 0 ? 'empty-slot' : ''}">
${dayLessons.length === 0 ? '<div class="empty-lesson-placeholder"></div>' : ''}
${dayLessons
.map(
(lesson) => `
<div class="lesson-card ${lesson.isSubstituted ? "substituted" : ""}
<div class="lesson-slot has-continuation">
${continuingInSlot.map(lesson => {
const slots = lessonSlotMap.get(lesson);
const isLastSlot = slots[slots.length - 1] === timeIndex;
const lessonGroupId = `${lesson.subject}_${lesson.day}_${lesson.date}_${lesson.startTime}`;
return `
<div class="lesson-card ${lesson.isSubstituted ? "substituted" : ""}
${lesson.isCancelled ? "cancelled" : ""}
${lesson.hasHomework ? "has-homework" : ""}"
lesson-continuation ${isLastSlot ? 'continuation-end' : 'continuation-middle'}"
data-lesson='${JSON.stringify(lesson)}'
data-lesson-id='${lesson.lessonId || ""}'>
<div class="lesson-subject">${lesson.subject}</div>
<div class="lesson-teacher">${lesson.teacher}</div>
data-lesson-id='${lesson.lessonId || ""}'
data-lesson-group='${lessonGroupId}'>
<div class="lesson-bottom">
<div class="lesson-room">${lesson.room}</div>
<div class="lesson-time">${lesson.isCancelled ? LanguageManager.t("timetable.cancelled") : lesson.startTime}</div>
</div>
</div>
`}).join('')}
</div>
`;
}
return `
<div class="lesson-slot ${dayLessons.length === 0 ? 'empty-slot' : ''} ${hasMultiLesson ? 'has-multi-start' : ''}">
${dayLessons.length === 0 ? '<div class="empty-lesson-placeholder"></div>' : ''}
${dayLessons
.map(
(lesson) => {
const slots = lessonSlotMap.get(lesson);
const spansMultiple = slots && slots.length > 1;
const lessonGroupId = `${lesson.subject}_${lesson.day}_${lesson.date}_${lesson.startTime}`;
return `
<div class="lesson-card ${lesson.isSubstituted ? "substituted" : ""}
${lesson.isCancelled ? "cancelled" : ""}
${lesson.hasHomework ? "has-homework" : ""}
${spansMultiple ? "lesson-spans-multiple" : ""}"
data-lesson='${JSON.stringify(lesson)}'
data-lesson-id='${lesson.lessonId || ""}'
data-spans='${slots ? slots.length : 1}'
data-lesson-group='${lessonGroupId}'>
<div class="lesson-subject">${lesson.subject}</div>
<div class="lesson-teacher">${lesson.teacher}</div>
${!spansMultiple ? `<div class="lesson-bottom">
<div class="lesson-room">${lesson.room}</div>
<div class="lesson-time">${lesson.isCancelled ? LanguageManager.t("timetable.cancelled") : lesson.startTime}</div>
</div>` : ''}
${
(() => {
const lessonKey = `${lesson.subject}_${lesson.startTime}_${lesson.day}`;
const hasCustomHomework = customHomework[lessonKey] && customHomework[lessonKey].length > 0;
const hasCustomTests = customTests[lessonKey] && customTests[lessonKey].length > 0;
const lessonKey = `${lesson.subject}_${lesson.startTime}_${lesson.date}`;
const customHomeworkItems = customHomework[lessonKey] || [];
const customTestItems = customTests[lessonKey] || [];
const hasCustomHomework = customHomeworkItems.length > 0;
const hasCustomTests = customTestItems.length > 0;
const allCustomHomeworkCompleted = hasCustomHomework && customHomeworkItems.every(hw => hw.completed);
const allCustomTestsCompleted = hasCustomTests && customTestItems.every(test => test.completed);
const hasAnyIndicators = lesson.hasHomework || lesson.testInfo || hasCustomHomework || hasCustomTests;
return hasAnyIndicators ? `
<div class="lesson-indicators">
${
@@ -614,18 +715,40 @@
}
${
lesson.testInfo
? `
<span class="lesson-indicator test-indicator" title="${LanguageManager.t("timetable.test_indicator")}">
<img src="${chrome.runtime.getURL("icons/assigment.svg")}" alt="Teszt" style="width: 20px; height: 20px;">
? (() => {
const testType = lesson.testId ? testTypeMap[lesson.testId] : null;
const isKontaktOra = testType === "KONTAKT ÓRA";
const isProjektOra = testType === "PROJEKT ÓRA";
let indicatorClass = "test-indicator";
let iconPath = "icons/assigment.svg";
let titleText = LanguageManager.t("timetable.test_indicator");
let altText = "Teszt";
if (isKontaktOra) {
indicatorClass = "homework-indicator";
iconPath = "icons/contact.svg";
titleText = "Kontakt óra";
altText = "Kontakt óra";
} else if (isProjektOra) {
indicatorClass = "homework-indicator";
iconPath = "icons/project.svg";
titleText = "Projekt óra";
altText = "Projekt óra";
}
return `
<span class="lesson-indicator ${indicatorClass}" title="${titleText}">
<img src="${chrome.runtime.getURL(iconPath)}" alt="${altText}" style="width: 20px; height: 20px;">
</span>
`
`;
})()
: ""
}
${
hasCustomHomework
? `
<span class="lesson-indicator custom-homework-indicator" title="Saját házi feladat">
<img src="${chrome.runtime.getURL("icons/homework.svg")}" alt="Saját házi feladat" style="width: 20px; height: 20px; opacity: 0.7;">
<img src="${chrome.runtime.getURL(allCustomHomeworkCompleted ? "icons/pipa.svg" : "icons/homework.svg")}" alt="${allCustomHomeworkCompleted ? 'Megoldott saját házi feladat' : 'Saját házi feladat'}" style="width: 20px; height: 20px; opacity: 0.7;">
</span>
`
: ""
@@ -634,7 +757,7 @@
hasCustomTests
? `
<span class="lesson-indicator custom-test-indicator" title="Saját számonkérés">
<img src="${chrome.runtime.getURL("icons/assigment.svg")}" alt="Saját számonkérés" style="width: 20px; height: 20px; opacity: 0.7;">
<img src="${chrome.runtime.getURL(allCustomTestsCompleted ? "icons/pipa.svg" : "icons/assigment.svg")}" alt="${allCustomTestsCompleted ? 'Megoldott saját számonkérés' : 'Saját számonkérés'}" style="width: 20px; height: 20px; opacity: 0.7;">
</span>
`
: ""
@@ -644,8 +767,8 @@
})()
}
</div>
`,
)
`;
})
.join("")
}
</div>
@@ -1196,83 +1319,92 @@
}
if (lesson.testInfo) {
let testDetails = null;
if (lesson.testId) {
testDetails = await loadTestDetailsFromAPI(lesson.testId);
}
const isKontaktOra = testDetails && testDetails.type === "KONTAKT ÓRA";
const isProjektOra = testDetails && testDetails.type === "PROJEKT ÓRA";
const isSpecialType = isKontaktOra || isProjektOra;
const testSection = document.createElement('div');
testSection.className = 'modal-section test-section';
testSection.className = isSpecialType ? 'modal-section homework-section' : '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';
let iconPath = 'icons/assigment.svg';
let sectionTitle = LanguageManager.t('timetable.test_indicator');
let altText = 'Teszt';
if (isKontaktOra) {
iconPath = 'icons/contact.svg';
sectionTitle = 'Kontakt óra';
altText = 'Kontakt óra';
} else if (isProjektOra) {
iconPath = 'icons/project.svg';
sectionTitle = 'Projekt óra';
altText = 'Projekt óra';
}
testIcon.src = chrome.runtime.getURL(iconPath);
testIcon.alt = altText;
testIcon.style.width = '20px';
testIcon.style.height = '20px';
testH4.appendChild(testIcon);
testH4.appendChild(document.createTextNode(LanguageManager.t('timetable.test_indicator')));
testH4.appendChild(document.createTextNode(sectionTitle));
if (isSpecialType) {
testH4.style.color = 'var(--accent-accent)';
}
const testContent = document.createElement('div');
testContent.className = 'test-content';
if (lesson.testId) {
const loadingDiv = document.createElement('div');
loadingDiv.className = 'test-details-loading';
loadingDiv.textContent = 'Részletek betöltése...';
testContent.appendChild(loadingDiv);
if (testDetails) {
const detailsDiv = document.createElement('div');
detailsDiv.className = 'test-details';
loadTestDetailsFromAPI(lesson.testId).then(testDetails => {
loadingDiv.remove();
if (testDetails) {
const detailsDiv = document.createElement('div');
detailsDiv.className = 'test-details';
const nameP = document.createElement('p');
const nameStrong = document.createElement('strong');
nameStrong.textContent = 'Megnevezés: ';
nameP.appendChild(nameStrong);
nameP.appendChild(document.createTextNode(testDetails.name));
detailsDiv.appendChild(nameP);
const typeP = document.createElement('p');
const typeStrong = document.createElement('strong');
typeStrong.textContent = 'Típus: ';
typeP.appendChild(typeStrong);
typeP.appendChild(document.createTextNode(testDetails.type));
detailsDiv.appendChild(typeP);
const dateP = document.createElement('p');
const dateStrong = document.createElement('strong');
dateStrong.textContent = 'Bejelentés dátuma: ';
dateP.appendChild(dateStrong);
dateP.appendChild(document.createTextNode(testDetails.announceDate));
detailsDiv.appendChild(dateP);
testContent.appendChild(detailsDiv);
} else {
const errorP = document.createElement('p');
errorP.className = 'test-details-error';
errorP.textContent = 'Nem sikerült betölteni a számonkérés részleteit.';
testContent.appendChild(errorP);
}
}).catch(error => {
loadingDiv.remove();
const errorP = document.createElement('p');
errorP.className = 'test-details-error';
errorP.textContent = 'Hiba történt a számonkérés részletek betöltése során.';
testContent.appendChild(errorP);
});
const nameP = document.createElement('p');
const nameStrong = document.createElement('strong');
nameStrong.textContent = 'Megnevezés: ';
nameP.appendChild(nameStrong);
nameP.appendChild(document.createTextNode(testDetails.name));
detailsDiv.appendChild(nameP);
const typeP = document.createElement('p');
const typeStrong = document.createElement('strong');
typeStrong.textContent = 'Típus: ';
typeP.appendChild(typeStrong);
typeP.appendChild(document.createTextNode(testDetails.type));
detailsDiv.appendChild(typeP);
const dateP = document.createElement('p');
const dateStrong = document.createElement('strong');
dateStrong.textContent = 'Bejelentés dátuma: ';
dateP.appendChild(dateStrong);
dateP.appendChild(document.createTextNode(testDetails.announceDate));
detailsDiv.appendChild(dateP);
testContent.appendChild(detailsDiv);
} else if (lesson.testId) {
const errorP = document.createElement('p');
errorP.className = 'test-details-error';
errorP.textContent = 'Nem sikerült betölteni a számonkérés részleteit.';
testContent.appendChild(errorP);
}
const lessonKey = getLessonKey(lesson);
const customTests = await getCustomTests();
const customTestItems = customTests[lessonKey] || [];
if (customTestItems.length > 0) {
const customTestsDiv = document.createElement('div');
customTestsDiv.className = 'custom-tests-in-section';
customTestsDiv.style.marginTop = '1rem';
customTestsDiv.style.paddingTop = '1rem';
customTestsDiv.style.borderTop = '1px solid var(--background-0)';
const customTestsTitle = document.createElement('h5');
customTestsTitle.textContent = 'Saját számonkérések:';
customTestsTitle.style.fontSize = '14px';
@@ -1280,10 +1412,10 @@
customTestsTitle.style.color = 'var(--warning-accent)';
customTestsTitle.style.marginBottom = '0.5rem';
customTestsDiv.appendChild(customTestsTitle);
const customTestsList = document.createElement('div');
customTestsList.className = 'custom-tests-list-integrated';
customTestItems.forEach(test => {
const testItem = document.createElement('div');
testItem.className = `custom-test-item-integrated ${test.completed ? 'completed' : ''}`;
@@ -1295,7 +1427,7 @@
testItem.style.background = 'var(--background)';
testItem.style.borderRadius = '6px';
testItem.style.border = '1px solid var(--background-0)';
const testText = document.createElement('span');
testText.className = 'test-text-integrated';
testText.textContent = test.text;
@@ -1305,12 +1437,12 @@
testText.style.textDecoration = 'line-through';
testText.style.opacity = '0.6';
}
const testActions = document.createElement('div');
testActions.className = 'test-actions-integrated';
testActions.style.display = 'flex';
testActions.style.gap = '0.5rem';
const completeBtn = document.createElement('button');
completeBtn.className = 'test-complete-btn-integrated';
completeBtn.title = test.completed ? 'Megoldva - kattints a visszavonáshoz' : 'Megoldottként jelöl';
@@ -1322,7 +1454,7 @@
completeBtn.style.display = 'flex';
completeBtn.style.alignItems = 'center';
completeBtn.style.justifyContent = 'center';
const completeIcon = document.createElement('img');
completeIcon.src = chrome.runtime.getURL('icons/pipa.svg');
completeIcon.alt = 'Megoldva';
@@ -1335,7 +1467,7 @@
completeIcon.style.opacity = '0.5';
}
completeBtn.appendChild(completeIcon);
const deleteBtn = document.createElement('button');
deleteBtn.className = 'test-delete-btn-integrated';
deleteBtn.title = 'Törlés';
@@ -1347,7 +1479,7 @@
deleteBtn.style.display = 'flex';
deleteBtn.style.alignItems = 'center';
deleteBtn.style.justifyContent = 'center';
const deleteIcon = document.createElement('img');
deleteIcon.src = chrome.runtime.getURL('icons/delete.svg');
deleteIcon.alt = 'Törlés';
@@ -1355,7 +1487,7 @@
deleteIcon.style.height = '16px';
deleteIcon.style.opacity = '0.5';
deleteBtn.appendChild(deleteIcon);
completeBtn.addEventListener('click', async () => {
const newCompleted = await toggleCustomTestCompletion(lessonKey, test.id);
if (newCompleted) {
@@ -1372,30 +1504,30 @@
completeBtn.title = 'Megoldottként jelöl';
}
});
deleteBtn.addEventListener('click', async () => {
if (confirm('Biztosan törölni szeretnéd ezt a számonkérést?')) {
await removeCustomTest(lessonKey, test.id);
testItem.remove();
}
});
testActions.appendChild(completeBtn);
testActions.appendChild(deleteBtn);
testItem.appendChild(testText);
testItem.appendChild(testActions);
customTestsList.appendChild(testItem);
});
customTestsDiv.appendChild(customTestsList);
testContent.appendChild(customTestsDiv);
}
testSection.appendChild(testH4);
testSection.appendChild(testContent);
body.appendChild(testSection);
}
const lessonKey = getLessonKey(lesson);
const customHomework = await getCustomHomework();
@@ -1890,6 +2022,24 @@
const lessonData = JSON.parse(card.dataset.lesson);
await showLessonModal(lessonData);
});
card.addEventListener("mouseenter", () => {
const groupId = card.dataset.lessonGroup;
if (groupId) {
document.querySelectorAll(`[data-lesson-group="${groupId}"]`).forEach(relatedCard => {
relatedCard.classList.add('group-hover');
});
}
});
card.addEventListener("mouseleave", () => {
const groupId = card.dataset.lessonGroup;
if (groupId) {
document.querySelectorAll(`[data-lesson-group="${groupId}"]`).forEach(relatedCard => {
relatedCard.classList.remove('group-hover');
});
}
});
});
}

View File

@@ -1,24 +1,3 @@
const SENTRY_DSN = 'https://c7d88b71f550a276f973885a44b6536d@o4510511576055808.ingest.de.sentry.io/4510511935193168';
async function initSentry() {
try {
const result = await chrome.storage.sync.get('firka_errorReporting');
const enabled = result.firka_errorReporting !== false;
if (enabled) {
self.addEventListener('error', (event) => {
console.error('[Background Error]', event.error || event);
});
self.addEventListener('unhandledrejection', (event) => {
console.error('[Background Unhandled Rejection]', event.reason);
});
}
} catch (error) {
console.error('[Sentry] Nem sikerült inicializálni:', error);
}
}
chrome.runtime.onInstalled.addListener(async (details) => {
if (details.reason === 'install') {
const setupCompleted = await chrome.storage.sync.get('firka_setupCompleted');
@@ -29,8 +8,6 @@ chrome.runtime.onInstalled.addListener(async (details) => {
});
}
}
await initSentry();
});
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
@@ -57,6 +34,11 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
sendResponse({ success: true });
break;
case 'download_attachment':
const downloadResult = await handleDownloadAttachment(request.azonosito, request.fileName);
sendResponse(downloadResult);
break;
default:
console.warn('[Background] Unknown action:', request.action);
sendResponse({ success: false, error: 'Unknown action' });
@@ -102,7 +84,7 @@ async function handleStorageClear() {
try {
const allData = await chrome.storage.sync.get(null);
const firkaKeys = Object.keys(allData).filter(key => key.startsWith('firka_'));
if (firkaKeys.length > 0) {
await chrome.storage.sync.remove(firkaKeys);
}
@@ -112,6 +94,82 @@ async function handleStorageClear() {
}
}
async function handleDownloadAttachment(azonosito, fileName) {
try {
const apiUrl = `https://eugyintezes.e-kreta.hu/api/v1/dokumentumok/uzenetek/${azonosito}`;
const redirectResponse = await fetch(apiUrl, {
method: 'GET',
credentials: 'include',
headers: {
'Accept': 'application/json, text/plain, */*',
'x-csrf': '1',
'x-uzenet-json-formatum': 'CamelCase',
'x-uzenet-lokalizacio': 'hu-HU',
'x-uzenet-verzio-szam': '1.2.3'
},
redirect: 'manual'
});
let fileUrl;
if (redirectResponse.type === 'opaqueredirect' || redirectResponse.status === 0) {
const followResponse = await fetch(apiUrl, {
method: 'GET',
credentials: 'include',
headers: {
'Accept': 'application/json, text/plain, */*',
'x-csrf': '1',
'x-uzenet-json-formatum': 'CamelCase',
'x-uzenet-lokalizacio': 'hu-HU',
'x-uzenet-verzio-szam': '1.2.3'
},
redirect: 'follow'
});
if (followResponse.ok) {
const blob = await followResponse.blob();
const base64 = await blobToBase64(blob);
return { success: true, data: base64, fileName: fileName };
}
} else if (redirectResponse.status === 302 || redirectResponse.status === 301) {
fileUrl = redirectResponse.headers.get('location');
}
if (fileUrl) {
const fileResponse = await fetch(fileUrl, {
method: 'GET',
headers: {
'Accept': 'application/json, text/plain, */*',
'x-csrf': '1',
'x-uzenet-json-formatum': 'CamelCase',
'x-uzenet-lokalizacio': 'hu-HU',
'x-uzenet-verzio-szam': '1.2.3'
}
});
if (fileResponse.ok) {
const blob = await fileResponse.blob();
const base64 = await blobToBase64(blob);
return { success: true, data: base64, fileName: fileName };
}
}
return { success: false, error: 'Nem sikerült letölteni a mellékletet.' };
} catch (error) {
console.error('[Background] Attachment download error:', error);
return { success: false, error: error.message };
}
}
function blobToBase64(blob) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onloadend = () => resolve(reader.result);
reader.onerror = reject;
reader.readAsDataURL(blob);
});
}
chrome.storage.onChanged.addListener((changes, namespace) => {
if (namespace === 'sync') {
const firkaChanges = Object.keys(changes).filter(key => key.startsWith('firka_'));

File diff suppressed because one or more lines are too long

View File

@@ -1,127 +0,0 @@
(function() {
'use strict';
const SENTRY_DSN = 'https://c7d88b71f550a276f973885a44b6536d@o4510511576055808.ingest.de.sentry.io/4510511935193168';
let sentryInitialized = false;
async function isErrorReportingEnabled() {
try {
const result = await chrome.storage.sync.get('firka_errorReporting');
return result.firka_errorReporting !== false;
} catch (error) {
return true;
}
}
async function initSentry() {
if (sentryInitialized) {
return;
}
const enabled = await isErrorReportingEnabled();
if (!enabled) {
return;
}
setTimeout(() => {
configureSentry();
}, 100);
}
function configureSentry() {
try {
const SentrySDK = window.Sentry || (typeof Sentry !== 'undefined' ? Sentry : null);
if (!SentrySDK) {
setTimeout(configureSentry, 500);
return;
}
if (!SentrySDK.init) {
return;
}
const manifest = chrome.runtime.getManifest();
SentrySDK.init({
dsn: SENTRY_DSN,
release: `firka-extension@${manifest.version}`,
environment: 'production',
integrations: [],
beforeSend(event, hint) {
if (event.request) {
delete event.request.cookies;
delete event.request.headers;
}
return event;
},
});
sentryInitialized = true;
} catch (error) {
}
}
window.addEventListener('error', function(event) {
if (sentryInitialized) {
const SentrySDK = window.Sentry || (typeof Sentry !== 'undefined' ? Sentry : null);
if (SentrySDK && SentrySDK.captureException) {
SentrySDK.captureException(event.error || new Error(event.message));
} else {
console.warn('[Sentry] SDK not available for capturing');
}
} else {
console.warn('[Sentry] Not initialized yet, cannot capture error');
}
}, true);
window.addEventListener('unhandledrejection', function(event) {
if (sentryInitialized) {
const SentrySDK = window.Sentry || (typeof Sentry !== 'undefined' ? Sentry : null);
if (SentrySDK && SentrySDK.captureException) {
SentrySDK.captureException(event.reason);
}
}
}, true);
if (typeof chrome !== 'undefined' && chrome.storage) {
chrome.storage.onChanged.addListener(function(changes, namespace) {
if (namespace === 'sync' && changes.firka_errorReporting) {
const newValue = changes.firka_errorReporting.newValue;
if (newValue === false && sentryInitialized) {
if (typeof Sentry !== 'undefined' && Sentry.close) {
Sentry.close();
sentryInitialized = false;
}
} else if (newValue !== false && !sentryInitialized) {
initSentry();
}
}
});
}
window.FirkaSentry = {
init: initSentry,
isEnabled: isErrorReportingEnabled,
captureException: function(error) {
if (sentryInitialized) {
const SentrySDK = window.Sentry || (typeof Sentry !== 'undefined' ? Sentry : null);
if (SentrySDK && SentrySDK.captureException) {
SentrySDK.captureException(error);
}
}
},
captureMessage: function(message, level = 'info') {
if (sentryInitialized) {
const SentrySDK = window.Sentry || (typeof Sentry !== 'undefined' ? Sentry : null);
if (SentrySDK && SentrySDK.captureMessage) {
SentrySDK.captureMessage(message, level);
}
}
}
};
initSentry();
})();