mirror of
https://github.com/QwIT-Development/firka-extension.git
synced 2026-06-12 11:51:39 +02:00
Compare commits
41 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
42bfa0912f | ||
|
|
0322b31146 | ||
|
|
52fc99ca99 | ||
|
|
0a65ed3dda | ||
|
|
5a836947e1 | ||
|
|
ebb291ee87 | ||
|
|
56dcef30e0 | ||
|
|
cfe6e0fccf | ||
|
|
bacf77b506 | ||
|
|
3ee34b90e6 | ||
|
|
0e1f97eaaa | ||
|
|
699d2604c6 | ||
|
|
d8f1622b5b | ||
|
|
b69c9f3f6a | ||
|
|
ebf6aa8d61 | ||
|
|
0048ebb932 | ||
|
|
a55e40ecf2 | ||
|
|
ea5e01ce9c | ||
|
|
c0e738fd8b | ||
|
|
842588a0bb | ||
|
|
be2e7a192b | ||
|
|
60ad73ffae | ||
|
|
3a9bbbcb2a | ||
|
|
afb7a3d79b | ||
|
|
95d50e9297 | ||
|
|
e88566369a | ||
|
|
b9985ccf09 | ||
|
|
88706017f9 | ||
|
|
0aef3950e7 | ||
|
|
db74cb1a37 | ||
|
|
0d71510c7f | ||
| ee26b6d966 | |||
|
|
731511d28a | ||
|
|
79b09cb1ab | ||
|
|
1730c108df | ||
|
|
f990e2e899 | ||
|
|
2feef43ef2 | ||
|
|
dfc0c362c7 | ||
|
|
367547f67f | ||
|
|
003db8569e | ||
|
|
4eee8fa7e6 |
71
.github/workflows/build.yml
vendored
Normal file
71
.github/workflows/build.yml
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
name: Package and Release Extension
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- test
|
||||
|
||||
jobs:
|
||||
build-and-release:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Get current date
|
||||
id: date
|
||||
run: |
|
||||
echo "DATE=$(date +'%Y.%m.%d. %H:%M')" >> $GITHUB_ENV
|
||||
echo "DATE_FOR_ZIP=$(date +'%Y%m%d-%H%M')" >> $GITHUB_ENV
|
||||
|
||||
- name: Create ZIP file
|
||||
run: |
|
||||
zip -r "pre-firxa-${{ env.DATE_FOR_ZIP }}.zip" . -x "*.git*" "*.github*" "*.idea*"
|
||||
|
||||
- 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: Create new pre-release
|
||||
id: create_release
|
||||
uses: softprops/action-gh-release@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
tag_name: pre-release
|
||||
release_name: Fejlesztői build
|
||||
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 }}
|
||||
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
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -7,3 +7,5 @@ META-INF/cose.sig
|
||||
META-INF/manifest.mf
|
||||
META-INF/mozilla.sf
|
||||
dashboard/KRÉTA Iskolai Alaprendszer.html
|
||||
*.xml
|
||||
*.xml
|
||||
|
||||
9
.idea/Firkaextension.iml
generated
9
.idea/Firkaextension.iml
generated
@@ -1,9 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$" />
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
6
.idea/misc.xml
generated
6
.idea/misc.xml
generated
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
||||
8
.idea/modules.xml
generated
8
.idea/modules.xml
generated
@@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/Firkaextension.iml" filepath="$PROJECT_DIR$/.idea/Firkaextension.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
6
.idea/vcs.xml
generated
6
.idea/vcs.xml
generated
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
45
.idea/workspace.xml
generated
45
.idea/workspace.xml
generated
@@ -1,45 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="AutoImportSettings">
|
||||
<option name="autoReloadType" value="NONE" />
|
||||
</component>
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="2540850d-5586-4ef8-a1c0-838ec2731d44" name="Changes" comment="" />
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
||||
<option name="LAST_RESOLUTION" value="IGNORE" />
|
||||
</component>
|
||||
<component name="ClangdSettings">
|
||||
<option name="formatViaClangd" value="false" />
|
||||
</component>
|
||||
<component name="ProjectColorInfo"><![CDATA[{
|
||||
"associatedIndex": 0
|
||||
}]]></component>
|
||||
<component name="ProjectId" id="2uHD20KrXgQVbKPvZ8rqEw44Sjy" />
|
||||
<component name="ProjectViewState">
|
||||
<option name="hideEmptyMiddlePackages" value="true" />
|
||||
<option name="showLibraryContents" value="true" />
|
||||
</component>
|
||||
<component name="PropertiesComponent"><![CDATA[{
|
||||
"keyToString": {
|
||||
"RunOnceActivity.ShowReadmeOnStart": "true",
|
||||
"RunOnceActivity.cidr.known.project.marker": "true",
|
||||
"RunOnceActivity.readMode.enableVisualFormatting": "true",
|
||||
"cf.first.check.clang-format": "false",
|
||||
"cidr.known.project.marker": "true",
|
||||
"kotlin-language-version-configured": "true"
|
||||
}
|
||||
}]]></component>
|
||||
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
|
||||
<component name="TaskManager">
|
||||
<task active="true" id="Default" summary="Default task">
|
||||
<changelist id="2540850d-5586-4ef8-a1c0-838ec2731d44" name="Changes" comment="" />
|
||||
<created>1741896394934</created>
|
||||
<option name="number" value="Default" />
|
||||
<option name="presentableId" value="Default" />
|
||||
<updated>1741896394934</updated>
|
||||
</task>
|
||||
<servers />
|
||||
</component>
|
||||
</project>
|
||||
34
README.md
34
README.md
@@ -8,14 +8,14 @@
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/Zan1456/Firkaextension/releases">
|
||||
<img src="https://img.shields.io/github/downloads-pre/Zan1456/Firkaextension/latest/total?style=for-the-badge&logo=github&logoColor=EAF7CC&label=Let%C3%B6lt%C3%A9sek&labelColor=141905&color=A7DC22" alt="Downloads">
|
||||
<a href="https://github.com/QwIT-Development/firka-extension/releases">
|
||||
<img src="https://img.shields.io/github/downloads-pre/QwIT-Development/firka-extension/latest/total?style=for-the-badge&logo=github&logoColor=EAF7CC&label=Let%C3%B6lt%C3%A9sek&labelColor=141905&color=A7DC22" alt="Downloads">
|
||||
</a>
|
||||
<a href="https://discord.gg/6DvjyPAw2T">
|
||||
<img src="https://img.shields.io/discord/1111649116020285532?style=for-the-badge&logo=discord&logoColor=EAF7CC&label=Discord&labelColor=0D1202&color=A7DC22" alt="Discord">
|
||||
</a>
|
||||
<a href="https://github.com/Zan1456/Firkaextension/blob/main/LICENSE">
|
||||
<img src="https://img.shields.io/github/license/Zan1456/Firkaextension?style=for-the-badge&logo=discord&logoColor=EAF7CC&label=Discord&labelColor=0D1202&color=A7DC22" alt="License">
|
||||
<a href="https://github.com/QwIT-Development/firka-extension/blob/main/LICENSE">
|
||||
<img src="https://img.shields.io/github/license/QwIT-Development/firka-extension?style=for-the-badge&logo=discord&logoColor=EAF7CC&label=Discord&labelColor=0D1202&color=A7DC22" alt="License">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
@@ -34,13 +34,19 @@
|
||||
|
||||
## 🚀 Telepítés
|
||||
|
||||
1. Töltsd le a legfrissebb verziót a [Releases](https://github.com/Zan1456/Firkaextension/releases) oldalról
|
||||
2. Csomagold ki a letöltött fájlt
|
||||
3. Chrome böngészőben navigálj a `chrome://extensions` oldalra
|
||||
4. Kapcsold be a "Fejlesztői mód"-ot a jobb felső sarokban
|
||||
5. Kattints a "Kicsomagolt bővítmény betöltése" gombra
|
||||
6. Válaszd ki a kicsomagolt mappát
|
||||
7. Kész! A bővítmény automatikusan működésbe lép, amikor megnyitod az e-KRÉTA oldalt
|
||||
1. Töltsd le a legfrissebb verziót a [Releases](https://github.com/QwIT-Development/firka-extension/releases/) oldalról
|
||||
### Chromium alapú böngészők esetén
|
||||
2. Navigálj a `chrome://extensions` oldalra
|
||||
3. Kapcsold be a "Fejlesztői mód"-ot a jobb felső sarokban
|
||||
4. Keresd meg a letöltött zip fájlt
|
||||
5. Húzd a letöltött zip fájlt a böngészőbe
|
||||
### Firefox alapú böngészők esetén
|
||||
2. Navigálj az `about:addons` oldalra
|
||||
3. Kattints rá a fogaskerék ikonra (⚙️) a jobb felső sarokban
|
||||
4. Ebben a menüben válaszd a(z) "Kiegészítő telepítése fájlból..."/"Install Add-on From File..."
|
||||
5. Válaszd ki a `.zip` fájlt amit letöltöttél
|
||||
### Kész!
|
||||
6. A bővítmény automatikusan működésbe lép, amikor megnyitod az e-KRÉTA oldalt
|
||||
|
||||
## ⚙️ Beállítások
|
||||
|
||||
@@ -65,8 +71,8 @@ A bővítmény jelenleg az alábbi e-KRÉTA oldalakat támogatja:
|
||||
## 👥 Csapat
|
||||
|
||||
- **[Zan1456](https://github.com/Zan1456)** - Vezető Fejlesztő
|
||||
- **[BalazsManus](https://github.com/BalazsManus)** - Fejlesztő
|
||||
- **[Xou](https://github.com/Xou)** - Designer
|
||||
- **[BalazsManus](https://github.com/olajcsere)** - Fejlesztő
|
||||
- **[Xou](https://yoursit.ee/xou)** - Designer
|
||||
|
||||
## 🤝 Közreműködés
|
||||
|
||||
@@ -80,7 +86,7 @@ A bővítmény jelenleg az alábbi e-KRÉTA oldalakat támogatja:
|
||||
|
||||
## 📝 Licensz
|
||||
|
||||
A projekt [GNU General Public License v3.0](LICENSE) alatt jelent meg. További információért lásd a LICENSE fájlt.
|
||||
A projekt [GNU Affero General Public License v3.0](LICENSE) alatt jelent meg. További információért lásd a LICENSE fájlt.
|
||||
|
||||
## 💬 Kapcsolat
|
||||
|
||||
|
||||
@@ -42,10 +42,10 @@ body {
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.kreta-header {
|
||||
grid-template-columns: 1fr auto;
|
||||
grid-template-columns: 1fr auto auto;
|
||||
grid-template-areas:
|
||||
"school user"
|
||||
"nav nav";
|
||||
"school toggle user"
|
||||
"nav nav nav";
|
||||
padding: 1rem;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
@@ -110,77 +110,6 @@ body {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.kreta-nav {
|
||||
padding: 0 clamp(0.5rem, 3vw, 1.5rem);
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 100;
|
||||
overflow-x: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
scrollbar-width: none;
|
||||
-ms-overflow-style: none;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.kreta-nav {
|
||||
grid-area: nav;
|
||||
padding: 0;
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.nav-links {
|
||||
display: flex;
|
||||
gap: clamp(0.5rem, 2vw, 1rem);
|
||||
padding: 0.25rem;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.nav-links {
|
||||
justify-content: flex-start;
|
||||
width: 100%;
|
||||
gap: 0.25rem;
|
||||
}
|
||||
}
|
||||
|
||||
.nav-links a {
|
||||
color: var(--text-secondary);
|
||||
text-decoration: none;
|
||||
padding: clamp(0.5rem, 1.5vw, 1rem) 0.5rem;
|
||||
font-weight: 500;
|
||||
white-space: nowrap;
|
||||
transition: all 0.2s ease;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.nav-links a {
|
||||
padding: 0.5rem;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.nav-links a .material-icons-round {
|
||||
font-size: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.nav-links a:hover {
|
||||
color: var(--text-primary);
|
||||
background-color: var(--card-card);
|
||||
}
|
||||
|
||||
.nav-links a.active {
|
||||
color: var(--accent-accent);
|
||||
}
|
||||
|
||||
|
||||
.user-profile {
|
||||
position: relative;
|
||||
justify-self: flex-end;
|
||||
@@ -212,19 +141,6 @@ body {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.user-name {
|
||||
display: block;
|
||||
color: var(--text-primary);
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.user-time {
|
||||
display: block;
|
||||
color: var(--text-secondary);
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.user-dropdown {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
|
||||
@@ -1,65 +1,14 @@
|
||||
function getCookie(name) {
|
||||
const cookieName = `${name}=`;
|
||||
const decodedCookie = decodeURIComponent(document.cookie);
|
||||
const cookieArray = decodedCookie.split(';');
|
||||
|
||||
for(let i = 0; i < cookieArray.length; i++) {
|
||||
let cookie = cookieArray[i];
|
||||
while (cookie.charAt(0) === ' ') {
|
||||
cookie = cookie.substring(1);
|
||||
}
|
||||
if (cookie.indexOf(cookieName) === 0) {
|
||||
return cookie.substring(cookieName.length, cookie.length);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function shortenSchoolName(name, maxLength = 50) {
|
||||
if (!name) return '';
|
||||
if (name.length <= maxLength) return name;
|
||||
|
||||
const parts = name.split(' - ');
|
||||
if (parts.length === 2) {
|
||||
const [code, fullName] = parts;
|
||||
if (fullName.length > maxLength - code.length - 3) {
|
||||
return `${code} - ${fullName.substring(0, maxLength - code.length - 6)}...`;
|
||||
}
|
||||
}
|
||||
return name.substring(0, maxLength - 3) + '...';
|
||||
}
|
||||
|
||||
async function waitForElement(selector) {
|
||||
return new Promise(resolve => {
|
||||
if (document.querySelector(selector)) {
|
||||
return resolve(document.querySelector(selector));
|
||||
}
|
||||
|
||||
const observer = new MutationObserver(mutations => {
|
||||
if (document.querySelector(selector)) {
|
||||
observer.disconnect();
|
||||
resolve(document.querySelector(selector));
|
||||
}
|
||||
});
|
||||
|
||||
observer.observe(document.body, {
|
||||
childList: true,
|
||||
subtree: true
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function collectAbsencesData() {
|
||||
await waitForElement('#HianyzasGrid');
|
||||
await helper.waitForElement('#HianyzasGrid');
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
|
||||
const basicData = {
|
||||
schoolInfo: {
|
||||
name: getCookie('schoolName') || 'Iskola',
|
||||
id: getCookie('schoolCode') || ''
|
||||
name: cookieManager.get('schoolName') || 'Iskola',
|
||||
id: cookieManager.get('schoolCode') || ''
|
||||
},
|
||||
userData: {
|
||||
name: getCookie('userName') || 'Felhasználó',
|
||||
name: cookieManager.get('userName') || 'Felhasználó',
|
||||
time: document.querySelector('.usermenu_timer')?.textContent?.trim() || '45:00'
|
||||
}
|
||||
};
|
||||
@@ -95,98 +44,12 @@ async function collectAbsencesData() {
|
||||
return { basicData, absences, groupedAbsences };
|
||||
}
|
||||
|
||||
function showLoadingScreen() {
|
||||
const loadingHTML = `
|
||||
<div class="loading-overlay">
|
||||
<div class="loading-container">
|
||||
<img src="https://i.imgur.com/JE3LzRc.gif" alt="Firka" class="loading-logo"><!--logó csere-->
|
||||
<div class="loading-text">Betöltés alatt...</div>
|
||||
<p class="loading-text2">Kis türelmet</p>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
document.body.insertAdjacentHTML('beforeend', loadingHTML);
|
||||
}
|
||||
|
||||
function hideLoadingScreen() {
|
||||
const loadingOverlay = document.querySelector('.loading-overlay');
|
||||
if (loadingOverlay) {
|
||||
loadingOverlay.style.opacity = '0';
|
||||
loadingOverlay.style.transition = 'opacity 0.3s ease';
|
||||
setTimeout(() => loadingOverlay.remove(), 300);
|
||||
}
|
||||
}
|
||||
|
||||
async function transformAbsencesPage() {
|
||||
showLoadingScreen();
|
||||
const { basicData, absences, groupedAbsences } = await collectAbsencesData();
|
||||
|
||||
|
||||
const schoolNameFull = `${basicData.schoolInfo.id} - ${basicData.schoolInfo.name}`;
|
||||
const shortenedSchoolName = shortenSchoolName(schoolNameFull);
|
||||
|
||||
document.body.innerHTML = `
|
||||
<div class="kreta-container">
|
||||
<header class="kreta-header">
|
||||
<div class="school-info">
|
||||
<p class="logo-text">
|
||||
<img src="${chrome.runtime.getURL('images/firka_logo.png')}" alt="Firka" class="logo">
|
||||
Firka
|
||||
</p>
|
||||
<div class="school-details" title="${schoolNameFull}">
|
||||
${shortenedSchoolName}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<nav class="kreta-nav">
|
||||
<div class="nav-links">
|
||||
<a href="/Intezmeny/Faliujsag" data-page="dashboard" class="nav-item">
|
||||
<img src="${chrome.runtime.getURL('icons/dashboard-inactive.svg')}" alt="Kezdőlap">
|
||||
Kezdőlap
|
||||
</a>
|
||||
<a href="/TanuloErtekeles/Osztalyzatok" data-page="grades" class="nav-item">
|
||||
<img src="${chrome.runtime.getURL('icons/grades-inactive.svg')}" alt="Jegyek">
|
||||
Jegyek
|
||||
</a>
|
||||
<a href="/Orarend/InformaciokOrarend" data-page="timetable" class="nav-item">
|
||||
<img src="${chrome.runtime.getURL('icons/timetable-inactive.svg')}" alt="Órarend">
|
||||
Órarend
|
||||
</a>
|
||||
<a href="/Hianyzas/Hianyzasok" data-page="absences" class="nav-item active">
|
||||
<img src="${chrome.runtime.getURL('icons/absences-active.svg')}" alt="Mulasztások">
|
||||
Mulasztások
|
||||
</a>
|
||||
<a href="/Tanulo/TanuloHaziFeladat" data-page="other" class="nav-item">
|
||||
<img src="${chrome.runtime.getURL('icons/others.svg')}" alt="Egyéb">
|
||||
Egyéb
|
||||
</a>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="user-profile">
|
||||
<button class="user-dropdown-btn">
|
||||
<div class="user-info">
|
||||
<span class="user-name">${basicData.userData.name}</span>
|
||||
<span class="nav-logout-timer" id="logoutTimer">${basicData.userData.time}</span>
|
||||
</div>
|
||||
</button>
|
||||
<div class="user-dropdown">
|
||||
<a href="/Adminisztracio/Profil" data-page="profile" class="dropdown-item">
|
||||
<img src="${chrome.runtime.getURL('icons/profile.svg')}" alt="Profil">
|
||||
Profil
|
||||
</a>
|
||||
<a href="#" class="dropdown-item" id="settingsBtn">
|
||||
<img src="${chrome.runtime.getURL('icons/settings.svg')}" alt="Beállítások">
|
||||
Beállítások
|
||||
</a>
|
||||
<a href="/Home/Logout" data-page="logout" class="dropdown-item">
|
||||
<img src="${chrome.runtime.getURL('icons/logout.svg')}" alt="Kijelentkezés">
|
||||
Kijelentkezés
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
${createTemplate.header()}
|
||||
|
||||
<main class="kreta-main">
|
||||
<div class="filter-card">
|
||||
@@ -266,69 +129,17 @@ async function transformAbsencesPage() {
|
||||
</div>
|
||||
`;
|
||||
|
||||
|
||||
const links = [
|
||||
{ rel: 'preconnect', href: 'https://fonts.googleapis.com' },
|
||||
{ rel: 'preconnect', href: 'https://fonts.gstatic.com', crossorigin: true },
|
||||
{ rel: 'stylesheet', href: 'https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap' },
|
||||
{ rel: 'stylesheet', href: 'https://fonts.googleapis.com/icon?family=Material+Icons+Round' }
|
||||
];
|
||||
|
||||
links.forEach(link => {
|
||||
const linkElement = document.createElement('link');
|
||||
Object.entries(link).forEach(([key, value]) => {
|
||||
linkElement[key] = value;
|
||||
});
|
||||
document.head.appendChild(linkElement);
|
||||
});
|
||||
createTemplate.importFonts();
|
||||
setupUserDropdown();
|
||||
setupMobileNavigation();
|
||||
|
||||
setupEventListeners();
|
||||
setupFilters();
|
||||
|
||||
hideLoadingScreen();
|
||||
loadingScreen.hide();
|
||||
}
|
||||
|
||||
function setupEventListeners(data) {
|
||||
const userBtn = document.querySelector('.user-dropdown-btn');
|
||||
const userDropdown = document.querySelector('.user-dropdown');
|
||||
|
||||
userBtn?.addEventListener('click', (e) => {
|
||||
e.stopPropagation();
|
||||
userDropdown.classList.toggle('show');
|
||||
});
|
||||
|
||||
document.addEventListener('click', () => {
|
||||
userDropdown?.classList.remove('show');
|
||||
});
|
||||
|
||||
const timerEl = document.getElementById('logoutTimer');
|
||||
if (timerEl) {
|
||||
const startTime = parseInt(timerEl.textContent?.match(/\d+/)?.[0] || "30");
|
||||
let timeLeft = startTime * 60;
|
||||
|
||||
const updateTimer = () => {
|
||||
const minutes = Math.floor(timeLeft / 60);
|
||||
const seconds = timeLeft % 60;
|
||||
timerEl.textContent = `${minutes}:${seconds.toString().padStart(2, '0')}`;
|
||||
|
||||
if (timeLeft <= 0) {
|
||||
window.location.href = '/Home/Logout';
|
||||
} else {
|
||||
timeLeft--;
|
||||
}
|
||||
};
|
||||
|
||||
updateTimer();
|
||||
setInterval(updateTimer, 1000);
|
||||
}
|
||||
|
||||
|
||||
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');
|
||||
});
|
||||
function setupEventListeners() {
|
||||
}
|
||||
|
||||
function setupFilters() {
|
||||
@@ -386,16 +197,6 @@ function setupFilters() {
|
||||
|
||||
let showGroup = true;
|
||||
|
||||
|
||||
// if (selectedDate && dateFilterValue) {
|
||||
// // Compare year, month, and day to ignore time
|
||||
// showGroup = groupDate.getFullYear() === selectedDate.getFullYear() &&
|
||||
// groupDate.getMonth() === selectedDate.getMonth() &&
|
||||
// groupDate.getDate() === selectedDate.getDate();
|
||||
//
|
||||
// console.log(`Comparing dates: ${groupDate.toDateString()} vs ${selectedDate.toDateString()}, match: ${showGroup}`);
|
||||
// }
|
||||
|
||||
const absenceItems = group.querySelectorAll('.absence-item');
|
||||
let visibleItems = 0;
|
||||
|
||||
@@ -422,15 +223,9 @@ function setupFilters() {
|
||||
};
|
||||
|
||||
|
||||
// if (!filters.dateFilter.value) {
|
||||
// const today = new Date();
|
||||
// filters.dateFilter.value = today.toISOString().split('T')[0]; // Set date to today by default
|
||||
// }
|
||||
|
||||
|
||||
Object.values(filters).forEach(filter => {
|
||||
try {
|
||||
if (filter && filter !== filters.dateFilter) { // Don't add event listener to dateFilter
|
||||
if (filter && filter !== filters.dateFilter) {
|
||||
filter.addEventListener('change', filterAbsences);
|
||||
}
|
||||
} catch (err) {
|
||||
|
||||
@@ -120,6 +120,7 @@ body {
|
||||
.grade-3 {color: var(--grades-3); background-color: var(--grades-background-3);}
|
||||
.grade-4 {color: var(--grades-4); background-color: var(--grades-background-4);}
|
||||
.grade-5 {color: var(--grades-5); background-color: var(--grades-background-5);}
|
||||
.grade-Sz {color: var(--grades-3); background-color: var(--grades-background-3);}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
|
||||
@@ -1,19 +1,10 @@
|
||||
const utils = {
|
||||
shortenSchoolName(name, maxLength = 50) {
|
||||
if (!name || name.length <= maxLength) return name || '';
|
||||
|
||||
const [code, fullName] = name.split(' - ');
|
||||
if (fullName) {
|
||||
const maxFullNameLength = maxLength - code.length - 3;
|
||||
if (fullName.length > maxFullNameLength) {
|
||||
return `${code} - ${fullName.substring(0, maxFullNameLength)}...`;
|
||||
}
|
||||
}
|
||||
return `${name.substring(0, maxLength - 3)}...`;
|
||||
},
|
||||
|
||||
formatGradeValue(value) {
|
||||
return value?.trim() || '';
|
||||
const trimmedValue = value?.trim() || '';
|
||||
if (trimmedValue.toLowerCase() === 'szöveges') {
|
||||
return 'Sz';
|
||||
}
|
||||
return trimmedValue;
|
||||
},
|
||||
|
||||
parseDate(dateStr) {
|
||||
@@ -26,11 +17,9 @@ const utils = {
|
||||
const dateParts = dateStr.trim().split('.');
|
||||
if (dateParts.length < 3) return dateStr;
|
||||
|
||||
|
||||
const month = parseInt(dateParts[1], 10);
|
||||
const day = parseInt(dateParts[2], 10);
|
||||
|
||||
|
||||
if (isNaN(month) || month < 1 || month > 12) return dateStr;
|
||||
|
||||
const hungarianMonths = [
|
||||
@@ -38,7 +27,6 @@ const utils = {
|
||||
'július', 'augusztus', 'szeptember', 'október', 'november', 'december'
|
||||
];
|
||||
|
||||
|
||||
return `${hungarianMonths[month - 1]} ${day}.`;
|
||||
}
|
||||
};
|
||||
@@ -192,82 +180,18 @@ class DashboardUI {
|
||||
this.data = {
|
||||
...data,
|
||||
schoolInfo: {
|
||||
name: cookies.getCookie(COOKIE_KEYS.SCHOOL_NAME) || DEFAULT_VALUES.SCHOOL,
|
||||
id: cookies.getCookie(COOKIE_KEYS.SCHOOL_CODE) || ''
|
||||
name: cookieManager.get(COOKIE_KEYS.SCHOOL_NAME) || DEFAULT_VALUES.SCHOOL,
|
||||
id: cookieManager.get(COOKIE_KEYS.SCHOOL_CODE) || ''
|
||||
},
|
||||
userData: {
|
||||
name: cookies.getCookie(COOKIE_KEYS.USER_NAME) || DEFAULT_VALUES.USER,
|
||||
name: cookieManager.get(COOKIE_KEYS.USER_NAME) || DEFAULT_VALUES.USER,
|
||||
time: document.querySelector('.usermenu_timer')?.textContent?.trim() || DEFAULT_VALUES.TIMER
|
||||
}
|
||||
};
|
||||
this.schoolNameFull = `${this.data.schoolInfo.id} - ${this.data.schoolInfo.name}`;
|
||||
this.shortenedSchoolName = utils.shortenSchoolName(this.schoolNameFull);
|
||||
this.shortenedSchoolName = helper.shortenSchoolName(this.schoolNameFull);
|
||||
}
|
||||
|
||||
|
||||
static generateHeaderHTML(data, schoolNameFull, shortenedSchoolName) {
|
||||
return `
|
||||
<header class="kreta-header">
|
||||
<div class="school-info">
|
||||
<p class="logo-text">
|
||||
<img src="${chrome.runtime.getURL('images/firka_logo.png')}" alt="Firka" class="logo">
|
||||
Firka
|
||||
</p>
|
||||
<div class="school-details" title="${schoolNameFull}">
|
||||
${shortenedSchoolName}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<nav class="kreta-nav">
|
||||
<div class="nav-links">
|
||||
<a href="/Intezmeny/Faliujsag" data-page="dashboard" class="nav-item active">
|
||||
<img src="${chrome.runtime.getURL('icons/dashboard-active.svg')}" alt="Kezdőlap">
|
||||
Kezdőlap
|
||||
</a>
|
||||
<a href="/TanuloErtekeles/Osztalyzatok" data-page="grades" class="nav-item">
|
||||
<img src="${chrome.runtime.getURL('icons/grades-inactive.svg')}" alt="Jegyek">
|
||||
Jegyek
|
||||
</a>
|
||||
<a href="/Orarend/InformaciokOrarend" data-page="timetable" class="nav-item">
|
||||
<img src="${chrome.runtime.getURL('icons/timetable-inactive.svg')}" alt="Órarend">
|
||||
Órarend
|
||||
</a>
|
||||
<a href="/Hianyzas/Hianyzasok" data-page="absences" class="nav-item">
|
||||
<img src="${chrome.runtime.getURL('icons/absences-inactive.svg')}" alt="Mulasztások">
|
||||
Mulasztások
|
||||
</a>
|
||||
<a href="/Tanulo/TanuloHaziFeladat" data-page="other" class="nav-item">
|
||||
<img src="${chrome.runtime.getURL('icons/others.svg')}" alt="Egyéb">
|
||||
Egyéb
|
||||
</a>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="user-profile">
|
||||
<button class="user-dropdown-btn">
|
||||
<div class="user-info">
|
||||
<span class="user-name">${data.userData.name}</span>
|
||||
<span class="nav-logout-timer" id="logoutTimer">${data.userData.time}</span>
|
||||
</div>
|
||||
</button>
|
||||
<div class="user-dropdown">
|
||||
<a href="/Adminisztracio/Profil" data-page="profile" class="dropdown-item">
|
||||
<img src="${chrome.runtime.getURL('icons/profile.svg')}" alt="Profil">
|
||||
Profil
|
||||
</a>
|
||||
<a href="#" class="dropdown-item" id="settingsBtn">
|
||||
<img src="${chrome.runtime.getURL('icons/settings.svg')}" alt="Beállítások">
|
||||
Beállítások
|
||||
</a>
|
||||
<a href="/Home/Logout" data-page="logout" class="dropdown-item">
|
||||
<img src="${chrome.runtime.getURL('icons/logout.svg')}" alt="Kijelentkezés">
|
||||
Kijelentkezés
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
`;
|
||||
}
|
||||
generateMainContentHTML() {
|
||||
return `
|
||||
<main class="kreta-main">
|
||||
@@ -369,59 +293,14 @@ class DashboardUI {
|
||||
render() {
|
||||
document.body.innerHTML = `
|
||||
<div class="kreta-container">
|
||||
${DashboardUI.generateHeaderHTML(this.data, this.schoolNameFull, this.shortenedSchoolName)}
|
||||
${createTemplate.header()}
|
||||
${this.generateMainContentHTML()}
|
||||
</div>
|
||||
`;
|
||||
setupUserDropdown();
|
||||
setupLogoutTimer();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function setupLogoutTimer() {
|
||||
const timerElement = document.querySelector('.nav-logout-timer');
|
||||
if (!timerElement) return;
|
||||
|
||||
const timeString = timerElement.textContent;
|
||||
const startTime = parseInt(timeString?.match(/\d+/)?.[0] || "45");
|
||||
let timeLeft = startTime * 60;
|
||||
|
||||
const updateTimer = () => {
|
||||
const minutes = Math.floor(timeLeft / 60);
|
||||
const seconds = timeLeft % 60;
|
||||
timerElement.textContent = `${minutes}:${seconds.toString().padStart(2, '0')}`;
|
||||
|
||||
if (timeLeft <= 0) {
|
||||
window.location.href = '/Home/Logout';
|
||||
}
|
||||
timeLeft--;
|
||||
};
|
||||
|
||||
updateTimer();
|
||||
setInterval(updateTimer, 1000);
|
||||
}
|
||||
|
||||
class FontLoader {
|
||||
static loadFonts() {
|
||||
const links = [
|
||||
{ rel: 'preconnect', href: 'https://fonts.googleapis.com' },
|
||||
{ rel: 'preconnect', href: 'https://fonts.gstatic.com', crossorigin: true },
|
||||
{ rel: 'stylesheet', href: 'https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap' },
|
||||
{ rel: 'stylesheet', href: 'https://fonts.googleapis.com/icon?family=Material+Icons+Round' }
|
||||
];
|
||||
|
||||
links.forEach(link => {
|
||||
const linkElement = document.createElement('link');
|
||||
Object.entries(link).forEach(([key, value]) => {
|
||||
linkElement[key] = value;
|
||||
});
|
||||
document.head.appendChild(linkElement);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class DashboardApp {
|
||||
constructor() {
|
||||
this.initialize();
|
||||
@@ -433,7 +312,7 @@ class DashboardApp {
|
||||
try {
|
||||
const dataExtractor = new DashboardDataExtractor();
|
||||
const dashboardData = dataExtractor.extractAll();
|
||||
FontLoader.loadFonts();
|
||||
createTemplate.importFonts();
|
||||
const ui = new DashboardUI(dashboardData);
|
||||
ui.render();
|
||||
} catch (error) {
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
(() => {
|
||||
const transformForgotPasswordPage = () => {
|
||||
|
||||
const isDarkMode = localStorage.getItem('darkMode') === 'true';
|
||||
document.documentElement.setAttribute('data-theme', isDarkMode ? 'dark' : 'light');
|
||||
|
||||
|
||||
chrome.runtime.onMessage.addListener((message) => {
|
||||
if (message.action === 'toggleTheme') {
|
||||
@@ -11,7 +9,6 @@
|
||||
localStorage.setItem('darkMode', message.darkMode);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
document.body.innerHTML = `
|
||||
<div class="forgot-container">
|
||||
@@ -103,7 +100,6 @@
|
||||
const form = event.target;
|
||||
const inputs = form.querySelectorAll('.form-control[required]');
|
||||
let isValid = true;
|
||||
|
||||
|
||||
inputs.forEach(input => {
|
||||
if (!validateInput(input, true)) {
|
||||
@@ -144,7 +140,6 @@
|
||||
submitButton.disabled = false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
if (window.location.href.includes('/Adminisztracio/ElfelejtettJelszo')) {
|
||||
transformForgotPasswordPage();
|
||||
|
||||
@@ -191,16 +191,42 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* Hamburger menu styles */
|
||||
.nav-toggle {
|
||||
display: none;
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
padding: 0.5rem;
|
||||
border-radius: 8px;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.nav-toggle:hover {
|
||||
background: var(--hover);
|
||||
}
|
||||
|
||||
.nav-toggle svg {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
fill: var(--text-primary);
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.kreta-header {
|
||||
grid-template-columns: 1fr auto;
|
||||
grid-template-columns: 1fr auto auto;
|
||||
grid-template-areas:
|
||||
"school user"
|
||||
"nav nav";
|
||||
"school toggle user"
|
||||
"nav nav nav";
|
||||
padding: 1rem;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.nav-toggle {
|
||||
display: block;
|
||||
grid-area: toggle;
|
||||
}
|
||||
|
||||
.school-info {
|
||||
grid-area: school;
|
||||
max-width: none;
|
||||
@@ -211,21 +237,24 @@
|
||||
|
||||
.logo-text {
|
||||
margin: 0;
|
||||
font-size: 20px;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.school-details {
|
||||
font-size: 12px;
|
||||
font-size: 11px;
|
||||
max-width: 200px;
|
||||
}
|
||||
|
||||
.kreta-nav {
|
||||
grid-area: nav;
|
||||
padding: 0;
|
||||
margin-top: 0.5rem;
|
||||
overflow-x: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
scrollbar-width: none;
|
||||
-ms-overflow-style: none;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.kreta-nav.show {
|
||||
display: flex;
|
||||
animation: slideDown 0.3s ease;
|
||||
}
|
||||
|
||||
.kreta-nav::-webkit-scrollbar {
|
||||
@@ -233,25 +262,140 @@
|
||||
}
|
||||
|
||||
.nav-links {
|
||||
justify-content: flex-start;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
gap: 0.25rem;
|
||||
gap: 0.5rem;
|
||||
background: var(--card-card);
|
||||
border-radius: 12px;
|
||||
padding: 1rem;
|
||||
box-shadow: 0px 1px var(--shadow-blur) 0px var(--accent-shadow);
|
||||
}
|
||||
|
||||
.nav-item {
|
||||
padding: 0.5rem;
|
||||
font-size: 13px;
|
||||
width: 100%;
|
||||
justify-content: flex-start;
|
||||
padding: 0.75rem;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.user-profile {
|
||||
grid-area: user;
|
||||
}
|
||||
|
||||
.user-info {
|
||||
text-align: right;
|
||||
max-width: 120px;
|
||||
}
|
||||
|
||||
.user-name {
|
||||
font-size: 14px;
|
||||
font-size: 13px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.nav-logout-timer {
|
||||
font-size: 11px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.kreta-header {
|
||||
grid-template-columns: 1fr auto auto;
|
||||
grid-template-areas:
|
||||
"school toggle user"
|
||||
"nav nav nav";
|
||||
padding: 0.75rem;
|
||||
gap: 0.25rem;
|
||||
}
|
||||
|
||||
.school-info {
|
||||
min-width: 0;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.logo-text {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.school-details {
|
||||
font-size: 10px;
|
||||
max-width: 150px;
|
||||
}
|
||||
|
||||
.kreta-nav {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.kreta-nav.show {
|
||||
display: flex;
|
||||
animation: slideDown 0.3s ease;
|
||||
}
|
||||
|
||||
.nav-links {
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
gap: 0.5rem;
|
||||
background: var(--card-card);
|
||||
border-radius: 12px;
|
||||
padding: 1rem;
|
||||
box-shadow: 0px 1px var(--shadow-blur) 0px var(--accent-shadow);
|
||||
}
|
||||
|
||||
.nav-item {
|
||||
width: 100%;
|
||||
justify-content: flex-start;
|
||||
padding: 0.75rem;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.user-info {
|
||||
max-width: 100px;
|
||||
}
|
||||
|
||||
.user-name {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.nav-logout-timer {
|
||||
font-size: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 360px) {
|
||||
.kreta-header {
|
||||
padding: 0.5rem;
|
||||
}
|
||||
|
||||
.logo-text {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.school-details {
|
||||
font-size: 9px;
|
||||
max-width: 120px;
|
||||
}
|
||||
|
||||
.user-info {
|
||||
max-width: 80px;
|
||||
}
|
||||
|
||||
.user-name {
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.nav-logout-timer {
|
||||
font-size: 9px;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slideDown {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-10px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
@@ -11,26 +11,15 @@ const DEFAULT_VALUES = {
|
||||
TIMER: '45:00'
|
||||
};
|
||||
|
||||
const cookies = {
|
||||
getCookie(name) {
|
||||
const value = `; ${document.cookie}`;
|
||||
const parts = value.split(`; ${name}=`);
|
||||
return parts.length === 2 ? parts.pop().split(';').shift() : null;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
function updateHeaderInfo() {
|
||||
const schoolName = document.querySelector('.nav-school-name');
|
||||
const userName = document.querySelector('.nav-user-name');
|
||||
const logoutTimer = document.querySelector('.nav-logout-timer');
|
||||
|
||||
const userData = {
|
||||
schoolName: cookies.getCookie(COOKIE_KEYS.SCHOOL_NAME) || DEFAULT_VALUES.SCHOOL,
|
||||
schoolId: cookies.getCookie(COOKIE_KEYS.SCHOOL_CODE) || '',
|
||||
name: cookies.getCookie(COOKIE_KEYS.USER_NAME) || DEFAULT_VALUES.USER,
|
||||
schoolName: cookieManager.get(COOKIE_KEYS.SCHOOL_NAME) || DEFAULT_VALUES.SCHOOL,
|
||||
schoolId: cookieManager.get(COOKIE_KEYS.SCHOOL_CODE) || '',
|
||||
name: cookieManager.get(COOKIE_KEYS.USER_NAME) || DEFAULT_VALUES.USER,
|
||||
time: document.querySelector('.usermenu_timer')?.textContent?.trim() || DEFAULT_VALUES.TIMER
|
||||
};
|
||||
|
||||
@@ -95,9 +84,39 @@ function setupSettingsButton() {
|
||||
});
|
||||
}
|
||||
|
||||
function setupMobileNavigation() {
|
||||
setTimeout(() => {
|
||||
const navToggle = document.querySelector('.nav-toggle');
|
||||
const nav = document.querySelector('.kreta-nav');
|
||||
|
||||
if (!navToggle || !nav) {
|
||||
return;
|
||||
}
|
||||
|
||||
navToggle.addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
nav.classList.toggle('show');
|
||||
});
|
||||
|
||||
document.addEventListener('click', (e) => {
|
||||
if (!nav.contains(e.target) && !navToggle.contains(e.target)) {
|
||||
nav.classList.remove('show');
|
||||
}
|
||||
});
|
||||
|
||||
const navItems = document.querySelectorAll('.nav-item');
|
||||
navItems.forEach(item => {
|
||||
item.addEventListener('click', () => {
|
||||
nav.classList.remove('show');
|
||||
});
|
||||
});
|
||||
}, 100);
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
updateHeaderInfo();
|
||||
setupUserDropdown();
|
||||
setupSettingsButton();
|
||||
setupMobileNavigation();
|
||||
});
|
||||
|
||||
111
global/theme.js
111
global/theme.js
@@ -1,87 +1,69 @@
|
||||
(() => {
|
||||
|
||||
function setCookie(name, value, days = 365) {
|
||||
const date = new Date();
|
||||
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
|
||||
const expires = `expires=${date.toUTCString()}`;
|
||||
document.cookie = `${name}=${value}; ${expires}; path=/; domain=.e-kreta.hu`;
|
||||
}
|
||||
|
||||
function getCookie(name) {
|
||||
const cookieName = `${name}=`;
|
||||
const decodedCookie = decodeURIComponent(document.cookie);
|
||||
const cookieArray = decodedCookie.split(';');
|
||||
|
||||
for(let i = 0; i < cookieArray.length; i++) {
|
||||
let cookie = cookieArray[i];
|
||||
while (cookie.charAt(0) === ' ') {
|
||||
cookie = cookie.substring(1);
|
||||
}
|
||||
if (cookie.indexOf(cookieName) === 0) {
|
||||
return cookie.substring(cookieName.length, cookie.length);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
function setTheme(theme) {
|
||||
try {
|
||||
|
||||
const actualTheme = theme === 'default' ? 'light-blue' : theme;
|
||||
|
||||
document.documentElement.setAttribute('data-theme', actualTheme);
|
||||
setCookie('themePreference', actualTheme);
|
||||
cookieManager.set('themePreference', actualTheme);
|
||||
localStorage.setItem('themePreference', actualTheme);
|
||||
|
||||
|
||||
chrome.runtime.sendMessage({
|
||||
action: 'themeChanged',
|
||||
theme: actualTheme
|
||||
}).catch(() => {
|
||||
|
||||
console.log('Extension context not available for theme sync');
|
||||
|
||||
});
|
||||
|
||||
console.log('Theme set to:', actualTheme);
|
||||
} catch (error) {
|
||||
console.error('Error setting theme:', error);
|
||||
}
|
||||
}
|
||||
|
||||
function setPageTitleAndFavicon() {
|
||||
try {
|
||||
document.title = 'Firka - KRÉTA';
|
||||
|
||||
const existingFavicons = document.querySelectorAll('link[rel="icon"], link[rel="shortcut icon"]');
|
||||
existingFavicons.forEach(link => link.remove());
|
||||
|
||||
if (typeof chrome !== 'undefined' && chrome.runtime && chrome.runtime.getURL) {
|
||||
const favicon = document.createElement('link');
|
||||
favicon.rel = 'icon';
|
||||
favicon.type = 'image/png';
|
||||
favicon.href = chrome.runtime.getURL('images/firka_logo_128.png');
|
||||
document.head.appendChild(favicon);
|
||||
|
||||
const shortcutIcon = document.createElement('link');
|
||||
shortcutIcon.rel = 'shortcut icon';
|
||||
shortcutIcon.type = 'image/png';
|
||||
shortcutIcon.href = chrome.runtime.getURL('images/firka_logo_128.png');
|
||||
document.head.appendChild(shortcutIcon);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error setting page title and favicon:', error);
|
||||
}
|
||||
}
|
||||
|
||||
function initializeTheme() {
|
||||
|
||||
const cookieTheme = getCookie('themePreference');
|
||||
const cookieTheme = cookieManager.get('themePreference');
|
||||
const localStorageTheme = localStorage.getItem('themePreference');
|
||||
|
||||
|
||||
const theme = cookieTheme || localStorageTheme || 'light-blue';
|
||||
|
||||
const theme = cookieTheme || localStorageTheme || 'light-green';
|
||||
|
||||
setTheme(theme);
|
||||
|
||||
setPageTitleAndFavicon();
|
||||
|
||||
if (cookieTheme !== localStorageTheme) {
|
||||
if (cookieTheme) {
|
||||
localStorage.setItem('themePreference', cookieTheme);
|
||||
} else if (localStorageTheme) {
|
||||
setCookie('themePreference', localStorageTheme);
|
||||
cookieManager.set('themePreference', localStorageTheme);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
initializeTheme();
|
||||
});
|
||||
|
||||
|
||||
initializeTheme();
|
||||
document.addEventListener('DOMContentLoaded', initializeTheme);
|
||||
} else {
|
||||
|
||||
initializeTheme();
|
||||
}
|
||||
|
||||
@@ -93,35 +75,58 @@
|
||||
}
|
||||
|
||||
if (message.action === 'getTheme') {
|
||||
const currentTheme = document.documentElement.getAttribute('data-theme') || 'light-blue';
|
||||
const currentTheme = document.documentElement.getAttribute('data-theme') || 'light-green';
|
||||
sendResponse({ theme: currentTheme });
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
|
||||
let titleCheckTimeout;
|
||||
|
||||
const observer = new MutationObserver((mutations) => {
|
||||
const currentTheme = document.documentElement.getAttribute('data-theme');
|
||||
const savedTheme = getCookie('themePreference') || localStorage.getItem('themePreference');
|
||||
const savedTheme = cookieManager.get('themePreference') || localStorage.getItem('themePreference');
|
||||
|
||||
if ((!currentTheme && savedTheme) || (currentTheme !== savedTheme && savedTheme)) {
|
||||
setTheme(savedTheme);
|
||||
}
|
||||
|
||||
const titleChanged = mutations.some(mutation =>
|
||||
mutation.type === 'childList' &&
|
||||
mutation.target === document.head &&
|
||||
Array.from(mutation.addedNodes).some(node => node.tagName === 'TITLE')
|
||||
);
|
||||
|
||||
if (titleChanged || document.title !== 'Firka - KRÉTA') {
|
||||
clearTimeout(titleCheckTimeout);
|
||||
titleCheckTimeout = setTimeout(() => {
|
||||
if (document.title !== 'Firka - KRÉTA') {
|
||||
setPageTitleAndFavicon();
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
observer.observe(document.documentElement, {
|
||||
attributes: true,
|
||||
attributeFilter: ['data-theme']
|
||||
});
|
||||
observer.observe(document.head, {
|
||||
childList: true,
|
||||
subtree: true
|
||||
});
|
||||
});
|
||||
} else {
|
||||
observer.observe(document.documentElement, {
|
||||
attributes: true,
|
||||
attributeFilter: ['data-theme']
|
||||
});
|
||||
observer.observe(document.head, {
|
||||
childList: true,
|
||||
subtree: true
|
||||
});
|
||||
}
|
||||
})();
|
||||
File diff suppressed because it is too large
Load Diff
784
grades/grades.js
784
grades/grades.js
@@ -1,201 +1,144 @@
|
||||
(() => {
|
||||
function getCookie(name) {
|
||||
const cookieName = `${name}=`;
|
||||
const decodedCookie = decodeURIComponent(document.cookie);
|
||||
const cookieArray = decodedCookie.split(';');
|
||||
|
||||
for(let i = 0; i < cookieArray.length; i++) {
|
||||
let cookie = cookieArray[i];
|
||||
while (cookie.charAt(0) === ' ') {
|
||||
cookie = cookie.substring(1);
|
||||
}
|
||||
if (cookie.indexOf(cookieName) === 0) {
|
||||
return cookie.substring(cookieName.length, cookie.length);
|
||||
}
|
||||
async function transformGradesPage() {
|
||||
try {
|
||||
await helper.waitForElement('#Osztalyzatok_7895TanuloErtekelesByTanuloGrid');
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
|
||||
const gradesData = extractGradesData();
|
||||
const studentAverage = calculateOverallAverage(gradesData.subjects);
|
||||
const classAverage = calculateOverallClassAverage(gradesData.subjects);
|
||||
|
||||
document.body.innerHTML = generatePageHTML(gradesData, studentAverage, classAverage);
|
||||
|
||||
createTemplate.importFonts();
|
||||
setupUserDropdown();
|
||||
setupMobileNavigation();
|
||||
|
||||
const script = document.createElement('script');
|
||||
script.src = chrome.runtime.getURL('grades/chart.js');
|
||||
document.head.appendChild(script);
|
||||
|
||||
script.onload = () => {
|
||||
setupGradesChart(gradesData.subjects);
|
||||
};
|
||||
|
||||
setupEventListeners();
|
||||
loadingScreen.hide();
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error transforming grades page:', error);
|
||||
loadingScreen.hide();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function showLoadingScreen() {
|
||||
const existingLoadingScreen = document.querySelector('.loading-screen');
|
||||
if (existingLoadingScreen) return;
|
||||
|
||||
const loadingScreen = document.createElement('div');
|
||||
loadingScreen.className = 'loading-screen';
|
||||
loadingScreen.innerHTML = `
|
||||
<div class="loading-content">
|
||||
<img src="${chrome.runtime.getURL('images/firka_logo.png')}" alt="Firka" class="loading-logo">
|
||||
<div class="loading-text">Betöltés alatt...</div>
|
||||
<div class="loading-text2">Kis türelmet!</div>
|
||||
</div>
|
||||
`;
|
||||
document.body.appendChild(loadingScreen);
|
||||
}
|
||||
|
||||
function hideLoadingScreen() {
|
||||
const loadingScreen = document.querySelector('.loading-screen');
|
||||
if (loadingScreen) {
|
||||
loadingScreen.style.opacity = '0';
|
||||
loadingScreen.addEventListener('transitionend', () => {
|
||||
loadingScreen.remove();
|
||||
});
|
||||
}
|
||||
}
|
||||
function extractGradesData() {
|
||||
const subjects = [];
|
||||
const rows = document.querySelectorAll('#Osztalyzatok_7895TanuloErtekelesByTanuloGrid tbody tr');
|
||||
|
||||
async function transformGradesPage() {
|
||||
try {
|
||||
showLoadingScreen();
|
||||
rows.forEach(row => {
|
||||
const cells = row.querySelectorAll('td');
|
||||
if (cells.length >= 17) {
|
||||
const subjectName = cells[2].textContent.trim();
|
||||
if (subjectName && subjectName !== 'Magatartás/Szorgalom') {
|
||||
const grades = [];
|
||||
const months = ['Szeptember', 'Oktober', 'November', 'December', 'JanuarI', 'JanuarII', 'Februar', 'Marcius', 'Aprilis', 'Majus', 'JuniusI', 'JuniusII'];
|
||||
|
||||
await waitForElement('#Osztalyzatok_7895TanuloErtekelesByTanuloGrid');
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
months.forEach((month, index) => {
|
||||
const gradeElements = cells[index + 3].querySelectorAll('span[data-tanuloertekelesid]');
|
||||
gradeElements.forEach(element => {
|
||||
const gradeText = element.textContent.trim();
|
||||
if (gradeText && gradeText !== '-') {
|
||||
grades.push({
|
||||
value: gradeText,
|
||||
date: element.getAttribute('data-datum'),
|
||||
type: element.getAttribute('data-tipusmod'),
|
||||
theme: element.getAttribute('data-ertekelestema').replace('Téma: ', ''),
|
||||
weight: element.getAttribute('data-suly'),
|
||||
teacher: element.getAttribute('data-ertekelonyomtatasinev'),
|
||||
isSemesterGrade: (element.getAttribute('data-tipusmod') || '').toLowerCase().includes('félévi') ||
|
||||
(element.getAttribute('data-ertekelestema') || '').toLowerCase().includes('félévi') ||
|
||||
(element.getAttribute('data-tipus') || '').toLowerCase().includes('félévi')
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
const gradesData = extractGradesData();
|
||||
const studentAverage = calculateOverallAverage(gradesData.subjects);
|
||||
const classAverage = calculateOverallClassAverage(gradesData.subjects);
|
||||
|
||||
document.body.innerHTML = generatePageHTML(gradesData, studentAverage, classAverage);
|
||||
const avgText = cells[16].textContent.trim();
|
||||
const classAvgText = cells[17].textContent.trim();
|
||||
|
||||
const links = [
|
||||
{ rel: 'preconnect', href: 'https://fonts.googleapis.com' },
|
||||
{ rel: 'preconnect', href: 'https://fonts.gstatic.com', crossorigin: true },
|
||||
{ rel: 'stylesheet', href: 'https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap' },
|
||||
{ rel: 'stylesheet', href: 'https://fonts.googleapis.com/icon?family=Material+Icons+Round' }
|
||||
];
|
||||
const average = avgText !== '-' ? parseFloat(avgText.replace(',', '.')) : 0;
|
||||
const classAvg = classAvgText !== '-' ? parseFloat(classAvgText.replace(',', '.')) : 0;
|
||||
|
||||
|
||||
const script = document.createElement('script');
|
||||
script.src = chrome.runtime.getURL('grades/chart.js');
|
||||
document.head.appendChild(script);
|
||||
if (grades.length > 0) {
|
||||
|
||||
links.forEach(link => {
|
||||
const linkElement = document.createElement('link');
|
||||
Object.entries(link).forEach(([key, value]) => {
|
||||
linkElement[key] = value;
|
||||
});
|
||||
document.head.appendChild(linkElement);
|
||||
subjects.push({
|
||||
name: subjectName,
|
||||
grades: grades,
|
||||
average: average || 0,
|
||||
classAverage: classAvg || 0
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
script.onload = () => {
|
||||
setupGradesChart(gradesData.subjects);
|
||||
return {
|
||||
schoolInfo: {
|
||||
id: cookieManager.get('schoolCode') || '',
|
||||
name: cookieManager.get('schoolName') || 'Iskola'
|
||||
},
|
||||
userData: {
|
||||
name: cookieManager.get('userName') || 'Felhasználó',
|
||||
time: document.querySelector('.usermenu_timer')?.textContent?.trim() || '45:00'
|
||||
},
|
||||
subjects: subjects
|
||||
};
|
||||
|
||||
setupEventListeners();
|
||||
hideLoadingScreen();
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error transforming grades page:', error);
|
||||
hideLoadingScreen();
|
||||
}
|
||||
}
|
||||
|
||||
function extractGradesData() {
|
||||
const subjects = [];
|
||||
const rows = document.querySelectorAll('#Osztalyzatok_7895TanuloErtekelesByTanuloGrid tbody tr');
|
||||
|
||||
rows.forEach(row => {
|
||||
const cells = row.querySelectorAll('td');
|
||||
if (cells.length >= 17) {
|
||||
const subjectName = cells[2].textContent.trim();
|
||||
if (subjectName && subjectName !== 'Magatartás/Szorgalom') {
|
||||
const grades = [];
|
||||
const months = ['Szeptember', 'Oktober', 'November', 'December', 'JanuarI', 'JanuarII', 'Februar', 'Marcius', 'Aprilis', 'Majus', 'JuniusI', 'JuniusII'];
|
||||
|
||||
months.forEach((month, index) => {
|
||||
const gradeElements = cells[index + 3].querySelectorAll('span[data-tanuloertekelesid]');
|
||||
gradeElements.forEach(element => {
|
||||
const gradeText = element.textContent.trim();
|
||||
if (gradeText && gradeText !== '-') {
|
||||
grades.push({
|
||||
value: gradeText,
|
||||
date: element.getAttribute('data-datum'),
|
||||
type: element.getAttribute('data-tipusmod'),
|
||||
theme: element.getAttribute('data-ertekelestema').replace('Téma: ', ''),
|
||||
weight: element.getAttribute('data-suly'),
|
||||
teacher: element.getAttribute('data-ertekelonyomtatasinev'),
|
||||
isSemesterGrade: (element.getAttribute('data-tipusmod') || '').toLowerCase().includes('félévi') ||
|
||||
(element.getAttribute('data-ertekelestema') || '').toLowerCase().includes('félévi') ||
|
||||
(element.getAttribute('data-tipus') || '').toLowerCase().includes('félévi')
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
function calculateOverallAverage(subjects) {
|
||||
const validSubjects = subjects.filter(s => s.average > 0);
|
||||
if (validSubjects.length === 0) return 0;
|
||||
|
||||
|
||||
const avgText = cells[16].textContent.trim();
|
||||
const classAvgText = cells[17].textContent.trim();
|
||||
|
||||
const average = avgText !== '-' ? parseFloat(avgText.replace(',', '.')) : 0;
|
||||
const classAvg = classAvgText !== '-' ? parseFloat(classAvgText.replace(',', '.')) : 0;
|
||||
|
||||
if (grades.length > 0) {
|
||||
const weightedSum = validSubjects.reduce((sum, subject) => {
|
||||
const validGrades = subject.grades.filter(grade => !isNaN(parseInt(grade.value)));
|
||||
const subjectWeightedSum = validGrades.reduce((gradeSum, grade) => {
|
||||
const value = parseInt(grade.value);
|
||||
const weight = parseInt(grade.weight?.match(/\d+/)?.[0] || '100') / 100;
|
||||
return gradeSum + (value * weight);
|
||||
}, 0);
|
||||
|
||||
subjects.push({
|
||||
name: subjectName,
|
||||
grades: grades,
|
||||
average: average || 0,
|
||||
classAverage: classAvg || 0
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
const totalWeight = validGrades.reduce((weightSum, grade) => {
|
||||
const weight = parseInt(grade.weight?.match(/\d+/)?.[0] || '100') / 100;
|
||||
return weightSum + weight;
|
||||
}, 0);
|
||||
|
||||
return {
|
||||
schoolInfo: {
|
||||
id: getCookie('schoolCode') || '',
|
||||
name: getCookie('schoolName') || 'Iskola'
|
||||
},
|
||||
userData: {
|
||||
name: getCookie('userName') || 'Felhasználó',
|
||||
time: document.querySelector('.usermenu_timer')?.textContent?.trim() || '45:00'
|
||||
},
|
||||
subjects: subjects
|
||||
};
|
||||
}
|
||||
return sum + (subjectWeightedSum / totalWeight);
|
||||
}, 0);
|
||||
|
||||
function calculateOverallAverage(subjects) {
|
||||
const validSubjects = subjects.filter(s => s.average > 0);
|
||||
if (validSubjects.length === 0) return 0;
|
||||
|
||||
|
||||
const weightedSum = validSubjects.reduce((sum, subject) => {
|
||||
const validGrades = subject.grades.filter(grade => !isNaN(parseInt(grade.value)));
|
||||
const subjectWeightedSum = validGrades.reduce((gradeSum, grade) => {
|
||||
const value = parseInt(grade.value);
|
||||
const weight = parseInt(grade.weight?.match(/\d+/)?.[0] || '100') / 100;
|
||||
return gradeSum + (value * weight);
|
||||
}, 0);
|
||||
|
||||
const totalWeight = validGrades.reduce((weightSum, grade) => {
|
||||
const weight = parseInt(grade.weight?.match(/\d+/)?.[0] || '100') / 100;
|
||||
return weightSum + weight;
|
||||
}, 0);
|
||||
|
||||
return sum + (subjectWeightedSum / totalWeight);
|
||||
}, 0);
|
||||
|
||||
return weightedSum / validSubjects.length;
|
||||
}
|
||||
return weightedSum / validSubjects.length;
|
||||
}
|
||||
|
||||
function calculateOverallClassAverage(subjects) {
|
||||
const validSubjects = subjects.filter(s => s.classAverage > 0);
|
||||
if (validSubjects.length === 0) return 0;
|
||||
return validSubjects.reduce((sum, s) => sum + s.classAverage, 0) / validSubjects.length;
|
||||
}
|
||||
function calculateOverallClassAverage(subjects) {
|
||||
const validSubjects = subjects.filter(s => s.classAverage > 0);
|
||||
if (validSubjects.length === 0) return 0;
|
||||
return validSubjects.reduce((sum, s) => sum + s.classAverage, 0) / validSubjects.length;
|
||||
}
|
||||
|
||||
function shortenEvaluationName(name, maxLength = 30) {
|
||||
if (!name) return '';
|
||||
if (name.length <= maxLength) return name;
|
||||
return name.substring(0, maxLength - 3) + '...';
|
||||
}
|
||||
function shortenEvaluationName(name, maxLength = 30) {
|
||||
if (!name) return '';
|
||||
if (name.length <= maxLength) return name;
|
||||
return name.substring(0, maxLength - 3) + '...';
|
||||
}
|
||||
|
||||
function generateGradeItem(grade) {
|
||||
const semesterClass = grade.isSemesterGrade ? 'semester-grade' : '';
|
||||
const dateObj = new Date(grade.date);
|
||||
const monthNames = ['Január', 'Február', 'Március', 'Április', 'Május', 'Június', 'Július', 'Augusztus', 'Szeptember', 'Október', 'November', 'December'];
|
||||
const formattedDate = `${monthNames[dateObj.getMonth()]} ${dateObj.getDate()}`;
|
||||
const shortenedTheme = shortenEvaluationName(grade.theme);
|
||||
return `
|
||||
function generateGradeItem(grade) {
|
||||
const semesterClass = grade.isSemesterGrade ? 'semester-grade' : '';
|
||||
const dateObj = new Date(grade.date);
|
||||
const monthNames = ['Január', 'Február', 'Március', 'Április', 'Május', 'Június', 'Július', 'Augusztus', 'Szeptember', 'Október', 'November', 'December'];
|
||||
const formattedDate = `${monthNames[dateObj.getMonth()]} ${dateObj.getDate()}`;
|
||||
const shortenedTheme = shortenEvaluationName(grade.theme);
|
||||
return `
|
||||
<div class="grade-item grade-${grade.value} ${semesterClass}">
|
||||
<div class="grade-value">${grade.value}</div>
|
||||
<div class="grade-details">
|
||||
@@ -205,89 +148,35 @@
|
||||
<div class="grade-date">${formattedDate}</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
function calculateGradeDistribution(subjects) {
|
||||
const distribution = {1: 0, 2: 0, 3: 0, 4: 0, 5: 0};
|
||||
subjects.forEach(subject => {
|
||||
subject.grades.forEach(grade => {
|
||||
const value = parseInt(grade.value);
|
||||
if (value >= 1 && value <= 5) {
|
||||
distribution[value]++;
|
||||
}
|
||||
function calculateGradeDistribution(subjects) {
|
||||
const distribution = {1: 0, 2: 0, 3: 0, 4: 0, 5: 0};
|
||||
subjects.forEach(subject => {
|
||||
subject.grades.forEach(grade => {
|
||||
const value = parseInt(grade.value);
|
||||
if (value >= 1 && value <= 5) {
|
||||
distribution[value]++;
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
return distribution;
|
||||
}
|
||||
return distribution;
|
||||
}
|
||||
|
||||
function generatePageHTML(data, studentAverage, classAverage) {
|
||||
const totalGrades = data.subjects.reduce((sum, subject) => sum + subject.grades.length, 0);
|
||||
const gradeDistribution = calculateGradeDistribution(data.subjects);
|
||||
const semesterGrades = extractSemesterGrades(data.subjects);
|
||||
|
||||
|
||||
const studentGradeLevel = Math.floor(studentAverage) || 0;
|
||||
const classGradeLevel = Math.floor(classAverage) || 0;
|
||||
function generatePageHTML(data, studentAverage, classAverage) {
|
||||
const totalGrades = data.subjects.reduce((sum, subject) => sum + subject.grades.length, 0);
|
||||
const gradeDistribution = calculateGradeDistribution(data.subjects);
|
||||
const semesterGrades = extractSemesterGrades(data.subjects);
|
||||
|
||||
return `
|
||||
const studentGradeLevel = Math.floor(studentAverage) || 0;
|
||||
const classGradeLevel = Math.floor(classAverage) || 0;
|
||||
|
||||
schoolNameFull = `${data.schoolInfo.id} - ${data.schoolInfo.name}`;
|
||||
shortenedSchoolName = helper.shortenSchoolName(schoolNameFull);
|
||||
|
||||
return `
|
||||
<div class="kreta-container">
|
||||
<header class="kreta-header">
|
||||
<div class="school-info">
|
||||
<p class="logo-text">
|
||||
<img src="${chrome.runtime.getURL('images/firka_logo.png')}" alt="Firka" class="logo">
|
||||
Firka
|
||||
</p>
|
||||
<div class="school-details">
|
||||
<span>${data.schoolInfo.id} - ${data.schoolInfo.name}</span>
|
||||
</div>
|
||||
</div>
|
||||
<nav class="kreta-nav">
|
||||
<div class="nav-links">
|
||||
<a href="/Intezmeny/Faliujsag" data-page="dashboard" class="nav-item">
|
||||
<img src="${chrome.runtime.getURL('icons/dashboard-inactive.svg')}" alt="Kezdőlap">
|
||||
Kezdőlap
|
||||
</a>
|
||||
<a href="/TanuloErtekeles/Osztalyzatok" data-page="grades" class="nav-item active">
|
||||
<img src="${chrome.runtime.getURL('icons/grades-active.svg')}" alt="Jegyek">
|
||||
Jegyek
|
||||
</a>
|
||||
<a href="/Orarend/InformaciokOrarend" data-page="timetable" class="nav-item">
|
||||
<img src="${chrome.runtime.getURL('icons/timetable-inactive.svg')}" alt="Órarend">
|
||||
Órarend
|
||||
</a>
|
||||
<a href="/Hianyzas/Hianyzasok" data-page="absences" class="nav-item">
|
||||
<img src="${chrome.runtime.getURL('icons/absences-inactive.svg')}" alt="Mulasztások">
|
||||
Mulasztások
|
||||
</a>
|
||||
<a href="/Tanulo/TanuloHaziFeladat" data-page="other" class="nav-item">
|
||||
<img src="${chrome.runtime.getURL('icons/others.svg')}" alt="Egyéb">
|
||||
Egyéb
|
||||
</a>
|
||||
</div>
|
||||
</nav>
|
||||
<div class="user-profile">
|
||||
<button class="user-dropdown-btn">
|
||||
<div class="user-info">
|
||||
<span class="user-name">${data.userData.name}</span>
|
||||
<span class="nav-logout-timer" id="logoutTimer">${data.userData.time}</span>
|
||||
</div>
|
||||
</button>
|
||||
<div class="user-dropdown">
|
||||
<a href="/Adminisztracio/Profil" data-page="profile" class="dropdown-item">
|
||||
<img src="${chrome.runtime.getURL('icons/profile.svg')}" alt="Profil">
|
||||
Profil
|
||||
</a>
|
||||
<a href="#" class="dropdown-item" id="settingsBtn">
|
||||
<img src="${chrome.runtime.getURL('icons/settings.svg')}" alt="Beállítások">
|
||||
Beállítások
|
||||
</a>
|
||||
<a href="/Home/Logout" data-page="logout" class="dropdown-item">
|
||||
<img src="${chrome.runtime.getURL('icons/logout.svg')}" alt="Kijelentkezés">
|
||||
Kijelentkezés
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
${createTemplate.header()}
|
||||
|
||||
<main class="kreta-main">
|
||||
<div class="grades-overview">
|
||||
@@ -338,166 +227,168 @@ function generatePageHTML(data, studentAverage, classAverage) {
|
||||
</main>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
function extractSemesterGrades(subjects) {
|
||||
const semesterGrades = [];
|
||||
subjects.forEach(subject => {
|
||||
const semesterGrade = subject.grades.find(grade => grade.isSemesterGrade);
|
||||
if (semesterGrade) {
|
||||
semesterGrades.push({
|
||||
subject: subject.name,
|
||||
value: semesterGrade.value,
|
||||
date: semesterGrade.date
|
||||
});
|
||||
}
|
||||
});
|
||||
return semesterGrades;
|
||||
}
|
||||
function extractSemesterGrades(subjects) {
|
||||
const semesterGrades = [];
|
||||
subjects.forEach(subject => {
|
||||
const semesterGrade = subject.grades.find(grade => grade.isSemesterGrade);
|
||||
if (semesterGrade) {
|
||||
semesterGrades.push({
|
||||
subject: subject.name,
|
||||
value: semesterGrade.value,
|
||||
date: semesterGrade.date
|
||||
});
|
||||
}
|
||||
});
|
||||
return semesterGrades;
|
||||
}
|
||||
|
||||
function calculateGradePoints(subjects) {
|
||||
const allGrades = [];
|
||||
|
||||
subjects.forEach(subject => {
|
||||
subject.grades.forEach(grade => {
|
||||
const date = new Date(grade.date);
|
||||
const value = parseInt(grade.value);
|
||||
const weight = parseInt(grade.weight?.match(/\d+/)?.[0] || '100') / 100;
|
||||
allGrades.push({
|
||||
date,
|
||||
value,
|
||||
weight
|
||||
});
|
||||
});
|
||||
});
|
||||
function calculateGradePoints(subjects) {
|
||||
const allGrades = [];
|
||||
|
||||
|
||||
allGrades.sort((a, b) => a.date - b.date);
|
||||
subjects.forEach(subject => {
|
||||
subject.grades.forEach(grade => {
|
||||
const date = new Date(grade.date);
|
||||
const value = parseInt(grade.value);
|
||||
const weight = parseInt(grade.weight?.match(/\d+/)?.[0] || '100') / 100;
|
||||
if (date && value && weight) {
|
||||
allGrades.push({
|
||||
date,
|
||||
value,
|
||||
weight
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
let totalWeight = 0;
|
||||
let weightedSum = 0;
|
||||
return allGrades.map(grade => {
|
||||
totalWeight += grade.weight;
|
||||
weightedSum += grade.value * grade.weight;
|
||||
return {
|
||||
date: grade.date.toISOString(),
|
||||
grade: grade.value,
|
||||
average: weightedSum / totalWeight
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function setupGradesChart(subjects) {
|
||||
const ctx = document.getElementById('gradesChart');
|
||||
if (!ctx) return;
|
||||
allGrades.sort((a, b) => a.date - b.date);
|
||||
|
||||
const gradePoints = calculateGradePoints(subjects);
|
||||
|
||||
new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: gradePoints.map((_, index) => ''),
|
||||
datasets: [{
|
||||
label: 'Átlag',
|
||||
data: gradePoints.map(p => p.average),
|
||||
borderWidth: 5,
|
||||
tension: 0.5,
|
||||
segment: {
|
||||
borderColor: ctx => {
|
||||
const curr = ctx.p1.parsed.y;
|
||||
if (!curr) return 'transparent';
|
||||
const color = getComputedStyle(document.documentElement).getPropertyValue(
|
||||
curr < 2 ? '--grades-1' :
|
||||
curr < 2.5 ? '--grades-2' :
|
||||
curr < 3.5 ? '--grades-3' :
|
||||
curr < 4.5 ? '--grades-4' : '--grades-5'
|
||||
).trim() + '80';
|
||||
return color;
|
||||
}
|
||||
},
|
||||
fill: true,
|
||||
backgroundColor: function(context) {
|
||||
const chart = context.chart;
|
||||
const {ctx, chartArea} = chart;
|
||||
if (!chartArea) return null;
|
||||
|
||||
const gradientBg = ctx.createLinearGradient(0, chartArea.bottom, 0, chartArea.top);
|
||||
|
||||
|
||||
gradientBg.addColorStop(0, getComputedStyle(document.documentElement).getPropertyValue('--grades-1').trim() + '30');
|
||||
gradientBg.addColorStop(0.2, getComputedStyle(document.documentElement).getPropertyValue('--grades-2').trim() + '30');
|
||||
gradientBg.addColorStop(0.4, getComputedStyle(document.documentElement).getPropertyValue('--grades-3').trim() + '30');
|
||||
gradientBg.addColorStop(0.6, getComputedStyle(document.documentElement).getPropertyValue('--grades-4').trim() + '30');
|
||||
gradientBg.addColorStop(0.8, getComputedStyle(document.documentElement).getPropertyValue('--grades-5').trim() + '30');
|
||||
|
||||
return gradientBg;
|
||||
},
|
||||
pointBackgroundColor: context => {
|
||||
const value = context.raw;
|
||||
return getComputedStyle(document.documentElement).getPropertyValue(
|
||||
value < 2 ? '--grades-1' :
|
||||
value < 2.5 ? '--grades-2' :
|
||||
value < 3.5 ? '--grades-3' :
|
||||
value < 4.5 ? '--grades-4' : '--grades-5'
|
||||
).trim();
|
||||
},
|
||||
pointRadius: 0,
|
||||
pointHoverRadius: 0
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
scales: {
|
||||
y: {
|
||||
min: 1,
|
||||
max: 5,
|
||||
ticks: {
|
||||
stepSize: 1,
|
||||
color: getComputedStyle(document.documentElement).getPropertyValue('--text-secondary')
|
||||
},
|
||||
grid: {
|
||||
color: getComputedStyle(document.documentElement).getPropertyValue('--text-teritary') + '20',
|
||||
lineWidth: 1,
|
||||
borderDash: [5, 5]
|
||||
}
|
||||
},
|
||||
x: {
|
||||
display: false
|
||||
}
|
||||
},
|
||||
plugins: {
|
||||
legend: {
|
||||
display: false
|
||||
},
|
||||
tooltip: {
|
||||
backgroundColor: getComputedStyle(document.documentElement).getPropertyValue('--card-card'),
|
||||
titleColor: getComputedStyle(document.documentElement).getPropertyValue('--text-primary'),
|
||||
bodyColor: getComputedStyle(document.documentElement).getPropertyValue('--text-primary'),
|
||||
borderColor: getComputedStyle(document.documentElement).getPropertyValue('--text-teritary') + '20',
|
||||
borderWidth: 1,
|
||||
padding: 12,
|
||||
displayColors: false,
|
||||
callbacks: {
|
||||
title: () => '',
|
||||
label: context => `Átlag: ${context.raw.toFixed(2)}`
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function generateSubjectCards(subjects) {
|
||||
const sortedSubjects = [...subjects].sort((a, b) => a.grades.length - b.grades.length);
|
||||
let totalWeight = 0;
|
||||
let weightedSum = 0;
|
||||
return allGrades.map(grade => {
|
||||
totalWeight += grade.weight;
|
||||
weightedSum += grade.value * grade.weight;
|
||||
return {
|
||||
date: grade.date.toISOString(),
|
||||
grade: grade.value,
|
||||
average: weightedSum / totalWeight
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
return sortedSubjects.map(subject => {
|
||||
const regularGrades = subject.grades.filter(grade => !grade.isSemesterGrade);
|
||||
const myGrade = Math.floor(subject.average) || 0;
|
||||
const classGrade = Math.floor(subject.classAverage) || 0;
|
||||
|
||||
return `
|
||||
function setupGradesChart(subjects) {
|
||||
const ctx = document.getElementById('gradesChart');
|
||||
if (!ctx) return;
|
||||
|
||||
const gradePoints = calculateGradePoints(subjects);
|
||||
|
||||
new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: gradePoints.map((_, index) => ''),
|
||||
datasets: [{
|
||||
label: 'Átlag',
|
||||
data: gradePoints.map(p => p.average),
|
||||
borderWidth: 5,
|
||||
tension: 0.5,
|
||||
segment: {
|
||||
borderColor: ctx => {
|
||||
const curr = ctx.p1.parsed.y;
|
||||
if (!curr) return 'transparent';
|
||||
const color = getComputedStyle(document.documentElement).getPropertyValue(
|
||||
curr < 2 ? '--grades-1' :
|
||||
curr < 2.5 ? '--grades-2' :
|
||||
curr < 3.5 ? '--grades-3' :
|
||||
curr < 4.5 ? '--grades-4' : '--grades-5'
|
||||
).trim() + '80';
|
||||
return color;
|
||||
}
|
||||
},
|
||||
fill: true,
|
||||
backgroundColor: function(context) {
|
||||
const chart = context.chart;
|
||||
const {ctx, chartArea} = chart;
|
||||
if (!chartArea) return null;
|
||||
|
||||
const gradientBg = ctx.createLinearGradient(0, chartArea.bottom, 0, chartArea.top);
|
||||
|
||||
|
||||
gradientBg.addColorStop(0, getComputedStyle(document.documentElement).getPropertyValue('--grades-1').trim() + '30');
|
||||
gradientBg.addColorStop(0.2, getComputedStyle(document.documentElement).getPropertyValue('--grades-2').trim() + '30');
|
||||
gradientBg.addColorStop(0.4, getComputedStyle(document.documentElement).getPropertyValue('--grades-3').trim() + '30');
|
||||
gradientBg.addColorStop(0.6, getComputedStyle(document.documentElement).getPropertyValue('--grades-4').trim() + '30');
|
||||
gradientBg.addColorStop(0.8, getComputedStyle(document.documentElement).getPropertyValue('--grades-5').trim() + '30');
|
||||
|
||||
return gradientBg;
|
||||
},
|
||||
pointBackgroundColor: context => {
|
||||
const value = context.raw;
|
||||
return getComputedStyle(document.documentElement).getPropertyValue(
|
||||
value < 2 ? '--grades-1' :
|
||||
value < 2.5 ? '--grades-2' :
|
||||
value < 3.5 ? '--grades-3' :
|
||||
value < 4.5 ? '--grades-4' : '--grades-5'
|
||||
).trim();
|
||||
},
|
||||
pointRadius: 0,
|
||||
pointHoverRadius: 0
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
scales: {
|
||||
y: {
|
||||
min: 1,
|
||||
max: 5,
|
||||
ticks: {
|
||||
stepSize: 1,
|
||||
color: getComputedStyle(document.documentElement).getPropertyValue('--text-secondary')
|
||||
},
|
||||
grid: {
|
||||
color: getComputedStyle(document.documentElement).getPropertyValue('--text-teritary') + '20',
|
||||
lineWidth: 1,
|
||||
borderDash: [5, 5]
|
||||
}
|
||||
},
|
||||
x: {
|
||||
display: false
|
||||
}
|
||||
},
|
||||
plugins: {
|
||||
legend: {
|
||||
display: false
|
||||
},
|
||||
tooltip: {
|
||||
backgroundColor: getComputedStyle(document.documentElement).getPropertyValue('--card-card'),
|
||||
titleColor: getComputedStyle(document.documentElement).getPropertyValue('--text-primary'),
|
||||
bodyColor: getComputedStyle(document.documentElement).getPropertyValue('--text-primary'),
|
||||
borderColor: getComputedStyle(document.documentElement).getPropertyValue('--text-teritary') + '20',
|
||||
borderWidth: 1,
|
||||
padding: 12,
|
||||
displayColors: false,
|
||||
callbacks: {
|
||||
title: () => '',
|
||||
label: context => `Átlag: ${context.raw.toFixed(2)}`
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function generateSubjectCards(subjects) {
|
||||
const sortedSubjects = [...subjects].sort((a, b) => a.grades.length - b.grades.length);
|
||||
|
||||
return sortedSubjects.map(subject => {
|
||||
const regularGrades = subject.grades.filter(grade => !grade.isSemesterGrade);
|
||||
const myGrade = Math.floor(subject.average) || 0;
|
||||
const classGrade = Math.floor(subject.classAverage) || 0;
|
||||
|
||||
return `
|
||||
<div class="subject-card card">
|
||||
<div class="subject-header">
|
||||
<div class="subject-title">
|
||||
@@ -519,68 +410,33 @@ function generateSubjectCards(subjects) {
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}).join('');
|
||||
}
|
||||
|
||||
function setupEventListeners() {
|
||||
|
||||
const userBtn = document.querySelector('.user-dropdown-btn');
|
||||
const userDropdown = document.querySelector('.user-dropdown');
|
||||
|
||||
userBtn?.addEventListener('click', (e) => {
|
||||
e.stopPropagation();
|
||||
userDropdown.classList.toggle('show');
|
||||
});
|
||||
|
||||
document.addEventListener('click', () => {
|
||||
userDropdown?.classList.remove('show');
|
||||
});
|
||||
|
||||
|
||||
const timerEl = document.getElementById('logoutTimer');
|
||||
if (timerEl) {
|
||||
const startTime = parseInt(timerEl.textContent?.match(/\d+/)?.[0] || "45");
|
||||
let timeLeft = startTime * 60;
|
||||
|
||||
const updateTimer = () => {
|
||||
const minutes = Math.floor(timeLeft / 60);
|
||||
const seconds = timeLeft % 60;
|
||||
timerEl.textContent = `${minutes}:${seconds.toString().padStart(2, '0')}`;
|
||||
|
||||
if (timeLeft <= 0) {
|
||||
window.location.href = '/Home/Logout';
|
||||
} else {
|
||||
timeLeft--;
|
||||
}
|
||||
};
|
||||
|
||||
updateTimer();
|
||||
setInterval(updateTimer, 1000);
|
||||
}).join('');
|
||||
}
|
||||
}
|
||||
|
||||
function waitForElement(selector) {
|
||||
return new Promise(resolve => {
|
||||
if (document.querySelector(selector)) {
|
||||
return resolve(document.querySelector(selector));
|
||||
}
|
||||
function setupEventListeners() {
|
||||
const timerEl = document.getElementById('logoutTimer');
|
||||
if (timerEl) {
|
||||
const startTime = parseInt(timerEl.textContent?.match(/\d+/)?.[0] || "45");
|
||||
let timeLeft = startTime * 60;
|
||||
|
||||
const observer = new MutationObserver(mutations => {
|
||||
if (document.querySelector(selector)) {
|
||||
observer.disconnect();
|
||||
resolve(document.querySelector(selector));
|
||||
const updateTimer = () => {
|
||||
const minutes = Math.floor(timeLeft / 60);
|
||||
const seconds = timeLeft % 60;
|
||||
timerEl.textContent = `${minutes}:${seconds.toString().padStart(2, '0')}`;
|
||||
|
||||
if (timeLeft <= 0) {
|
||||
window.location.href = '/Home/Logout';
|
||||
} else {
|
||||
timeLeft--;
|
||||
}
|
||||
};
|
||||
|
||||
updateTimer();
|
||||
setInterval(updateTimer, 1000);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
observer.observe(document.body, {
|
||||
childList: true,
|
||||
subtree: true
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
if (window.location.href.includes('/TanuloErtekeles/Osztalyzatok')) {
|
||||
transformGradesPage();
|
||||
}
|
||||
if (window.location.href.includes('/TanuloErtekeles/Osztalyzatok')) {
|
||||
transformGradesPage();
|
||||
}
|
||||
})();
|
||||
@@ -67,10 +67,10 @@ body {
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.kreta-header {
|
||||
grid-template-columns: 1fr auto;
|
||||
grid-template-columns: 1fr auto auto;
|
||||
grid-template-areas:
|
||||
"school user"
|
||||
"nav nav";
|
||||
"school toggle user"
|
||||
"nav nav nav";
|
||||
padding: 1rem;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
@@ -135,77 +135,6 @@ body {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.kreta-nav {
|
||||
padding: 0 clamp(0.5rem, 3vw, 1.5rem);
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 100;
|
||||
overflow-x: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
scrollbar-width: none;
|
||||
-ms-overflow-style: none;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.kreta-nav {
|
||||
grid-area: nav;
|
||||
padding: 0;
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.nav-links {
|
||||
display: flex;
|
||||
gap: clamp(0.5rem, 2vw, 1rem);
|
||||
padding: 0.25rem;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.nav-links {
|
||||
justify-content: flex-start;
|
||||
width: 100%;
|
||||
gap: 0.25rem;
|
||||
}
|
||||
}
|
||||
|
||||
.nav-links a {
|
||||
color: var(--text-secondary);
|
||||
text-decoration: none;
|
||||
padding: clamp(0.5rem, 1.5vw, 1rem) 0.5rem;
|
||||
font-weight: 500;
|
||||
white-space: nowrap;
|
||||
transition: all 0.2s ease;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.nav-links a {
|
||||
padding: 0.5rem;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.nav-links a .material-icons-round {
|
||||
font-size: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.nav-links a:hover {
|
||||
color: var(--text-primary);
|
||||
background-color: var(--card-card);
|
||||
}
|
||||
|
||||
.nav-links a.active {
|
||||
color: var(--accent-accent);
|
||||
}
|
||||
|
||||
|
||||
.user-profile {
|
||||
position: relative;
|
||||
justify-self: flex-end;
|
||||
@@ -235,31 +164,22 @@ body {
|
||||
gap: 0.25rem;
|
||||
}
|
||||
|
||||
.user-name {
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.nav-logout-timer {
|
||||
font-size: 12px;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.user-dropdown {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
right: 0;
|
||||
margin-top: 0.5rem;
|
||||
background: var(--card-card);
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
||||
min-width: 200px;
|
||||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
|
||||
width: 200px;
|
||||
display: none;
|
||||
z-index: 1000;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.user-dropdown.show {
|
||||
display: block;
|
||||
animation: dropdownShow 0.2s ease;
|
||||
}
|
||||
|
||||
.dropdown-item {
|
||||
@@ -524,4 +444,15 @@ body {
|
||||
flex-direction: column;
|
||||
gap: 0.25rem;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes dropdownShow {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-10px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
@@ -1,65 +1,14 @@
|
||||
function getCookie(name) {
|
||||
const cookieName = `${name}=`;
|
||||
const decodedCookie = decodeURIComponent(document.cookie);
|
||||
const cookieArray = decodedCookie.split(';');
|
||||
|
||||
for(let i = 0; i < cookieArray.length; i++) {
|
||||
let cookie = cookieArray[i];
|
||||
while (cookie.charAt(0) === ' ') {
|
||||
cookie = cookie.substring(1);
|
||||
}
|
||||
if (cookie.indexOf(cookieName) === 0) {
|
||||
return cookie.substring(cookieName.length, cookie.length);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function shortenSchoolName(name, maxLength = 50) {
|
||||
if (!name) return '';
|
||||
if (name.length <= maxLength) return name;
|
||||
|
||||
const parts = name.split(' - ');
|
||||
if (parts.length === 2) {
|
||||
const [code, fullName] = parts;
|
||||
if (fullName.length > maxLength - code.length - 3) {
|
||||
return `${code} - ${fullName.substring(0, maxLength - code.length - 6)}...`;
|
||||
}
|
||||
}
|
||||
return name.substring(0, maxLength - 3) + '...';
|
||||
}
|
||||
|
||||
async function waitForElement(selector) {
|
||||
return new Promise(resolve => {
|
||||
if (document.querySelector(selector)) {
|
||||
return resolve(document.querySelector(selector));
|
||||
}
|
||||
|
||||
const observer = new MutationObserver(mutations => {
|
||||
if (document.querySelector(selector)) {
|
||||
observer.disconnect();
|
||||
resolve(document.querySelector(selector));
|
||||
}
|
||||
});
|
||||
|
||||
observer.observe(document.body, {
|
||||
childList: true,
|
||||
subtree: true
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function collectHomeworkData() {
|
||||
await waitForElement('#TanulotHaziFeladatkGrid');
|
||||
await helper.waitForElement('#TanulotHaziFeladatkGrid');
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
|
||||
const basicData = {
|
||||
schoolInfo: {
|
||||
name: getCookie('schoolName') || 'Iskola',
|
||||
id: getCookie('schoolCode') || ''
|
||||
name: cookieManager.get('schoolName') || 'Iskola',
|
||||
id: cookieManager.get('schoolCode') || ''
|
||||
},
|
||||
userData: {
|
||||
name: getCookie('userName') || 'Felhasználó',
|
||||
name: cookieManager.get('userName') || 'Felhasználó',
|
||||
time: document.querySelector('.usermenu_timer')?.textContent?.trim() || '45:00'
|
||||
}
|
||||
};
|
||||
@@ -93,29 +42,6 @@ async function collectHomeworkData() {
|
||||
return { basicData, homeworkItems, groupedHomework };
|
||||
}
|
||||
|
||||
function showLoadingScreen() {
|
||||
const loadingHTML = `
|
||||
<div class="loading-overlay">
|
||||
<div class="loading-container">
|
||||
<img src="${chrome.runtime.getURL('images/firka_logo.png')}" alt="Firka" class="loading-logo">
|
||||
<div class="loading-text">Betöltés alatt...</div>
|
||||
<p class="loading-text2">Kis türelmet</p>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
document.body.insertAdjacentHTML('beforeend', loadingHTML);
|
||||
}
|
||||
|
||||
function hideLoadingScreen() {
|
||||
const loadingOverlay = document.querySelector('.loading-overlay');
|
||||
if (loadingOverlay) {
|
||||
loadingOverlay.style.opacity = '0';
|
||||
loadingOverlay.style.transition = 'opacity 0.3s ease';
|
||||
setTimeout(() => loadingOverlay.remove(), 300);
|
||||
}
|
||||
}
|
||||
|
||||
function isTomorrow(dateStr) {
|
||||
if (!dateStr) return false;
|
||||
|
||||
@@ -124,7 +50,7 @@ function isTomorrow(dateStr) {
|
||||
if (parts.length < 3) return false;
|
||||
|
||||
const year = parseInt(parts[0].trim());
|
||||
const month = parseInt(parts[1].trim()) - 1; // JS months are 0-indexed
|
||||
const month = parseInt(parts[1].trim()) - 1;
|
||||
const day = parseInt(parts[2].trim());
|
||||
|
||||
const homeworkDate = new Date(year, month, day);
|
||||
@@ -143,74 +69,11 @@ function isTomorrow(dateStr) {
|
||||
}
|
||||
|
||||
async function transformHomeworkPage() {
|
||||
showLoadingScreen();
|
||||
const { basicData, homeworkItems, groupedHomework } = await collectHomeworkData();
|
||||
|
||||
|
||||
const schoolNameFull = `${basicData.schoolInfo.id} - ${basicData.schoolInfo.name}`;
|
||||
const shortenedSchoolName = shortenSchoolName(schoolNameFull);
|
||||
|
||||
document.body.innerHTML = `
|
||||
<div class="kreta-container">
|
||||
<header class="kreta-header">
|
||||
<div class="school-info">
|
||||
<p class="logo-text">
|
||||
<img src="${chrome.runtime.getURL('images/firka_logo.png')}" alt="Firka" class="logo">
|
||||
Firka
|
||||
</p>
|
||||
<div class="school-details" title="${schoolNameFull}">
|
||||
${shortenedSchoolName}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<nav class="kreta-nav">
|
||||
<div class="nav-links">
|
||||
<a href="/Intezmeny/Faliujsag" data-page="dashboard" class="nav-item">
|
||||
<img src="${chrome.runtime.getURL('icons/dashboard-inactive.svg')}" alt="Kezdőlap">
|
||||
Kezdőlap
|
||||
</a>
|
||||
<a href="/TanuloErtekeles/Osztalyzatok" data-page="grades" class="nav-item">
|
||||
<img src="${chrome.runtime.getURL('icons/grades-inactive.svg')}" alt="Jegyek">
|
||||
Jegyek
|
||||
</a>
|
||||
<a href="/Orarend/InformaciokOrarend" data-page="timetable" class="nav-item">
|
||||
<img src="${chrome.runtime.getURL('icons/timetable-inactive.svg')}" alt="Órarend">
|
||||
Órarend
|
||||
</a>
|
||||
<a href="/Hianyzas/Hianyzasok" data-page="absences" class="nav-item">
|
||||
<img src="${chrome.runtime.getURL('icons/absences-inactive.svg')}" alt="Mulasztások">
|
||||
Mulasztások
|
||||
</a>
|
||||
<a href="/Tanulo/TanuloHaziFeladat" data-page="other" class="nav-item active">
|
||||
<img src="${chrome.runtime.getURL('icons/others.svg')}" alt="Egyéb">
|
||||
Egyéb
|
||||
</a>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="user-profile">
|
||||
<button class="user-dropdown-btn">
|
||||
<div class="user-info">
|
||||
<span class="user-name">${basicData.userData.name}</span>
|
||||
<span class="nav-logout-timer" id="logoutTimer">${basicData.userData.time}</span>
|
||||
</div>
|
||||
</button>
|
||||
<div class="user-dropdown">
|
||||
<a href="/Adminisztracio/Profil" data-page="profile" class="dropdown-item">
|
||||
<img src="${chrome.runtime.getURL('icons/profile.svg')}" alt="Profil">
|
||||
Profil
|
||||
</a>
|
||||
<a href="#" class="dropdown-item" id="settingsBtn">
|
||||
<img src="${chrome.runtime.getURL('icons/settings.svg')}" alt="Beállítások">
|
||||
Beállítások
|
||||
</a>
|
||||
<a href="/Home/Logout" data-page="logout" class="dropdown-item">
|
||||
<img src="${chrome.runtime.getURL('icons/logout.svg')}" alt="Kijelentkezés">
|
||||
Kijelentkezés
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
${createTemplate.header()}
|
||||
|
||||
<main class="kreta-main">
|
||||
<div class="filter-card">
|
||||
@@ -268,8 +131,8 @@ async function transformHomeworkPage() {
|
||||
|
||||
setupFilters(homeworkItems, groupedHomework);
|
||||
setupUserDropdown();
|
||||
setupLogoutTimer();
|
||||
hideLoadingScreen();
|
||||
setupMobileNavigation();
|
||||
loadingScreen.hide();
|
||||
}
|
||||
|
||||
function renderHomeworkList(groupedHomework) {
|
||||
@@ -437,11 +300,11 @@ function setupFilters(homeworkItems, groupedHomework) {
|
||||
|
||||
|
||||
const startOfWeek = new Date(today);
|
||||
const dayOfWeek = today.getDay() || 7; // Convert Sunday from 0 to 7
|
||||
startOfWeek.setDate(today.getDate() - dayOfWeek + 1); // Monday
|
||||
const dayOfWeek = today.getDay() || 7;
|
||||
startOfWeek.setDate(today.getDate() - dayOfWeek + 1);
|
||||
|
||||
const endOfWeek = new Date(startOfWeek);
|
||||
endOfWeek.setDate(startOfWeek.getDate() + 6); // Sunday
|
||||
endOfWeek.setDate(startOfWeek.getDate() + 6);
|
||||
|
||||
|
||||
const startOfNextWeek = new Date(endOfWeek);
|
||||
@@ -519,50 +382,6 @@ function setupFilters(homeworkItems, groupedHomework) {
|
||||
deadlineFilter.addEventListener('change', applyFilters);
|
||||
}
|
||||
|
||||
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');
|
||||
});
|
||||
|
||||
document.addEventListener('click', () => {
|
||||
userDropdown?.classList.remove('show');
|
||||
});
|
||||
|
||||
|
||||
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');
|
||||
});
|
||||
}
|
||||
|
||||
function setupLogoutTimer() {
|
||||
const timerElement = document.querySelector('.nav-logout-timer');
|
||||
if (!timerElement) return;
|
||||
|
||||
const timeString = timerElement.textContent;
|
||||
const startTime = parseInt(timeString?.match(/\d+/)?.[0] || "45");
|
||||
let timeLeft = startTime * 60;
|
||||
|
||||
const updateTimer = () => {
|
||||
const minutes = Math.floor(timeLeft / 60);
|
||||
const seconds = timeLeft % 60;
|
||||
timerElement.textContent = `${minutes}:${seconds.toString().padStart(2, '0')}`;
|
||||
|
||||
if (timeLeft <= 0) {
|
||||
window.location.href = '/Home/Logout';
|
||||
}
|
||||
timeLeft--;
|
||||
};
|
||||
|
||||
updateTimer();
|
||||
setInterval(updateTimer, 1000);
|
||||
}
|
||||
|
||||
|
||||
if (window.location.href.includes('/Tanulo/TanuloHaziFeladat')) {
|
||||
|
||||
@@ -1,21 +1,20 @@
|
||||
async function transformLoginPage() {
|
||||
try {
|
||||
|
||||
if (document.readyState !== 'complete') {
|
||||
await new Promise(resolve => {
|
||||
window.addEventListener('load', resolve);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
const existingForm = document.querySelector('form');
|
||||
const formData = {
|
||||
action: existingForm?.getAttribute('action') || '',
|
||||
returnUrl: document.querySelector('#ReturnUrl')?.value || '',
|
||||
instituteCode: document.querySelector('#instituteCode')?.value || '',
|
||||
requestToken: document.querySelector('input[name="__RequestVerificationToken"]')?.value || ''
|
||||
requestToken: document.querySelector('input[name="__RequestVerificationToken"]')?.value || '',
|
||||
userName: document.querySelector('#UserName')?.value || '',
|
||||
password: document.querySelector('#Password')?.value || ''
|
||||
};
|
||||
|
||||
|
||||
const titleElement = document.querySelector('.page-title');
|
||||
const schoolInfo = {
|
||||
@@ -23,7 +22,6 @@ async function transformLoginPage() {
|
||||
kretaId: '',
|
||||
omCode: ''
|
||||
};
|
||||
|
||||
|
||||
const spanElement = titleElement?.querySelector('span');
|
||||
if (spanElement) {
|
||||
@@ -31,11 +29,9 @@ async function transformLoginPage() {
|
||||
schoolInfo.kretaId = lines[0] || '';
|
||||
schoolInfo.omCode = (lines[1] || '').replace('KRÉTA azonosító: ', '');
|
||||
}
|
||||
|
||||
|
||||
const rawSystemMessage = document.querySelector('.alert-primary')?.textContent?.trim() || '';
|
||||
const systemMessage = rawSystemMessage.replace('Rendszerértesítés', '').trim();
|
||||
|
||||
|
||||
const newHTML = `
|
||||
<div class="login-container">
|
||||
@@ -61,13 +57,13 @@ async function transformLoginPage() {
|
||||
|
||||
<div class="form-group">
|
||||
<input class="form-control" type="text" id="UserName" name="UserName"
|
||||
placeholder="Felhasználónév" maxlength="256" autocomplete="username" required>
|
||||
placeholder="Felhasználónév" maxlength="256" autocomplete="username" required value="${formData.userName}">
|
||||
<div class="error-message">Kérjük, add meg a felhasználóneved.</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group password-group">
|
||||
<input class="form-control" type="password" id="Password" name="Password"
|
||||
placeholder="Jelszó" maxlength="256" autocomplete="current-password" required>
|
||||
placeholder="Jelszó" maxlength="256" autocomplete="current-password" required value="${formData.password}">
|
||||
<button type="button" class="show-password" aria-label="Jelszó mutatása">
|
||||
<img src="${chrome.runtime.getURL('icons/eye-off.svg')}" alt="Show password" class="icon-eye">
|
||||
</button>
|
||||
@@ -100,10 +96,8 @@ async function transformLoginPage() {
|
||||
</footer>
|
||||
</div>
|
||||
`;
|
||||
|
||||
|
||||
document.body.innerHTML = newHTML;
|
||||
|
||||
|
||||
setupEventListeners();
|
||||
|
||||
@@ -117,7 +111,6 @@ function setupEventListeners() {
|
||||
const passwordInput = document.getElementById('Password');
|
||||
const togglePasswordBtn = document.querySelector('.show-password');
|
||||
const formInputs = document.querySelectorAll('.form-control');
|
||||
|
||||
|
||||
if (togglePasswordBtn && passwordInput) {
|
||||
togglePasswordBtn.addEventListener('click', () => {
|
||||
@@ -175,11 +168,6 @@ function handleSubmit(event) {
|
||||
isValid = false;
|
||||
}
|
||||
});
|
||||
|
||||
if (!isValid) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
const submitButton = form.querySelector('.btn-login');
|
||||
const spinner = submitButton.querySelector('.spinner');
|
||||
|
||||
326
login/twofactor.css
Normal file
326
login/twofactor.css
Normal file
@@ -0,0 +1,326 @@
|
||||
@font-face {
|
||||
font-family: 'Montserrat';
|
||||
src: url('chrome-extension://__MSG_@@extension_id__/fonts/Montserrat-Regular.woff2') format('woff2');
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Montserrat';
|
||||
src: url('chrome-extension://__MSG_@@extension_id__/fonts/Montserrat-Medium.woff2') format('woff2');
|
||||
font-weight: 500;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Montserrat';
|
||||
src: url('chrome-extension://__MSG_@@extension_id__/fonts/Montserrat-SemiBold.woff2') format('woff2');
|
||||
font-weight: 600;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Figtree';
|
||||
src: url('chrome-extension://__MSG_@@extension_id__/fonts/Figtree-Regular.woff2') format('woff2');
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
:root {
|
||||
--icon-invert: 0.1;
|
||||
--icon-sepia: 0.1;
|
||||
--icon-saturate: 0.1;
|
||||
--icon-hue-rotate: 0deg;
|
||||
--icon-brightness: 0.1;
|
||||
}
|
||||
|
||||
:root[data-theme="light-green"] {
|
||||
--icon-invert: 0.1;
|
||||
--icon-sepia: 0.1;
|
||||
--icon-saturate: 0.1;
|
||||
--icon-hue-rotate: 0deg;
|
||||
--icon-brightness: 0.1;
|
||||
}
|
||||
|
||||
:root[data-theme="dark-blue"] {
|
||||
--icon-invert: 0.9;
|
||||
--icon-sepia: 0.1;
|
||||
--icon-saturate: 0.1;
|
||||
--icon-hue-rotate: 0deg;
|
||||
--icon-brightness: 1;
|
||||
}
|
||||
|
||||
:root[data-theme="dark-green"] {
|
||||
--icon-invert: 0.9;
|
||||
--icon-sepia: 0.1;
|
||||
--icon-saturate: 0.1;
|
||||
--icon-hue-rotate: 0deg;
|
||||
--icon-brightness: 1;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
color: var(--text-primary);
|
||||
background-color: var(--background) !important;
|
||||
font-family: "Montserrat", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif !important;
|
||||
min-height: 100vh;
|
||||
font-size: 16px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.login-container {
|
||||
width: 90%;
|
||||
max-width: 500px;
|
||||
padding: 20px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.login-card {
|
||||
background: var(--card-card);
|
||||
padding: 24px;
|
||||
margin-bottom: 16px;
|
||||
border-radius: 24px;
|
||||
box-shadow: 0px 1px var(--shadow-blur) 0px var(--accent-shadow);
|
||||
}
|
||||
|
||||
.card-header {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
margin: 16px 0;
|
||||
background: var(--card-card) !important;
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0) !important;
|
||||
}
|
||||
|
||||
.logo-text {
|
||||
color: var(--text-primary);
|
||||
text-align: center;
|
||||
font-family: Montserrat;
|
||||
font-size: 20px;
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
.logo {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.twofactor-title {
|
||||
color: var(--text-primary);
|
||||
text-align: center;
|
||||
font-family: Montserrat;
|
||||
font-size: 24px;
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
line-height: 130%;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.twofactor-form {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.form-control {
|
||||
display: flex;
|
||||
height: 48px;
|
||||
padding: 0px 14px;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
align-self: stretch;
|
||||
border-radius: 12px;
|
||||
background: var(--accent-15) !important;
|
||||
border: 0px solid var(--accent-15) !important;
|
||||
color: var(--text-primary) !important;
|
||||
}
|
||||
|
||||
.form-control:focus {
|
||||
outline: none;
|
||||
border-color: var(--accent-accent) !important;
|
||||
}
|
||||
|
||||
.form-control::placeholder {
|
||||
color: var(--text-secondary) !important;
|
||||
}
|
||||
|
||||
.password-group {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.show-password {
|
||||
position: absolute;
|
||||
right: 12px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
background: none;
|
||||
border: none;
|
||||
padding: 4px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.icon-eye {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
opacity: 0.6;
|
||||
transition: opacity 0.2s ease;
|
||||
filter: invert(var(--icon-invert)) sepia(var(--icon-sepia)) saturate(var(--icon-saturate)) hue-rotate(var(--icon-hue-rotate)) brightness(var(--icon-brightness));
|
||||
}
|
||||
|
||||
.show-password:hover .icon-eye {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.form-check {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-top: 16px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.form-check-input {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
margin-right: 8px;
|
||||
border-radius: 6px;
|
||||
border: 2px solid var(--accent-accent);
|
||||
background-color: var(--card-card);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.form-check-input:checked {
|
||||
background-color: var(--accent-accent);
|
||||
border-color: var(--accent-accent);
|
||||
}
|
||||
|
||||
.form-check-label {
|
||||
color: var(--text-primary);
|
||||
font-family: Figtree;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 130%;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.btn-kreta {
|
||||
display: flex;
|
||||
height: 48px;
|
||||
padding: 0px 24px;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
border-radius: 12px;
|
||||
background: var(--accent-accent);
|
||||
color: white;
|
||||
font-family: Montserrat;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
line-height: normal;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s ease;
|
||||
}
|
||||
|
||||
.btn-kreta:hover {
|
||||
background-color: var(--accent-secondary);
|
||||
}
|
||||
|
||||
.btn-link {
|
||||
background: none;
|
||||
border: none;
|
||||
color: var(--accent-accent);
|
||||
font-family: Figtree;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 130%;
|
||||
text-decoration: underline;
|
||||
cursor: pointer;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.btn-link:hover {
|
||||
color: var(--accent-secondary);
|
||||
}
|
||||
|
||||
.subtext {
|
||||
color: var(--text-primary);
|
||||
font-family: Figtree;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 130%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.login-footer {
|
||||
margin-top: 24px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.privacy-link {
|
||||
color: var(--text-secondary);
|
||||
font-family: Figtree;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 130%;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.privacy-link:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.error-message {
|
||||
display: none;
|
||||
color: var(--error-text);
|
||||
font-family: Figtree;
|
||||
font-size: 12px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 130%;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.error-message.show {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.form-control.error {
|
||||
border: 1px solid var(--error-accent) !important;
|
||||
}
|
||||
|
||||
/* Hide original elements */
|
||||
header, main > .container-fluid, footer {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Responsive adjustments */
|
||||
@media (max-width: 576px) {
|
||||
.login-container {
|
||||
width: 100%;
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.login-card {
|
||||
padding: 16px;
|
||||
}
|
||||
}
|
||||
171
login/twofactor.js
Normal file
171
login/twofactor.js
Normal file
@@ -0,0 +1,171 @@
|
||||
async function transformTwoFactorPage() {
|
||||
try {
|
||||
if (document.readyState !== 'complete') {
|
||||
await new Promise(resolve => {
|
||||
window.addEventListener('load', resolve);
|
||||
});
|
||||
}
|
||||
|
||||
if (typeof loadingScreen !== 'undefined') {
|
||||
loadingScreen.show();
|
||||
}
|
||||
|
||||
const existingForm = document.querySelector('form');
|
||||
const formData = {
|
||||
action: existingForm?.getAttribute('action') || '',
|
||||
clientId: document.querySelector('#ClientId')?.value || '',
|
||||
rememberLogin: document.querySelector('#RememberLogin')?.value || 'False',
|
||||
returnUrl: document.querySelector('#ReturnUrl')?.value || '',
|
||||
isRecoveryCode: document.querySelector('#IsRecoveryCode')?.value || 'False',
|
||||
requestToken: document.querySelector('input[name="__RequestVerificationToken"]')?.value || '',
|
||||
trustDeviceValue: document.querySelector('input[name="TrustDevice"][type="hidden"]')?.value || 'false'
|
||||
};
|
||||
|
||||
const newHTML = `
|
||||
<div class="login-container">
|
||||
<div class="login-card">
|
||||
<div class="card-header">
|
||||
<p class="logo-text">
|
||||
<img src=${chrome.runtime.getURL('images/firka_logo.png')} alt="Firka" class="logo">
|
||||
Firka
|
||||
</p>
|
||||
<h1 class="twofactor-title">Kétfaktoros azonosítás</h1>
|
||||
</div>
|
||||
|
||||
<form class="twofactor-form" action="${formData.action}" method="post" id="twoFactorForm">
|
||||
<input type="hidden" id="ClientId" name="ClientId" value="${formData.clientId}">
|
||||
<input type="hidden" id="RememberLogin" name="RememberLogin" value="${formData.rememberLogin}">
|
||||
<input type="hidden" id="ReturnUrl" name="ReturnUrl" value="${formData.returnUrl}">
|
||||
<input type="hidden" id="IsRecoveryCode" name="IsRecoveryCode" value="${formData.isRecoveryCode}">
|
||||
<input name="__RequestVerificationToken" type="hidden" value="${formData.requestToken}">
|
||||
|
||||
<div class="form-group password-group">
|
||||
<input class="form-control" type="password" id="VerificationCode" name="VerificationCode"
|
||||
placeholder="Egyszeri jelszó" maxlength="256" autocomplete="off" required autofocus>
|
||||
<button type="button" class="show-password" aria-label="Jelszó mutatása">
|
||||
<img src="${chrome.runtime.getURL('icons/eye-off.svg')}" alt="Show password" class="icon-eye">
|
||||
</button>
|
||||
<div class="error-message">Kérjük, add meg az egyszeri jelszót.</div>
|
||||
</div>
|
||||
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" id="trustDevice" name="TrustDevice" value="true">
|
||||
<label class="form-check-label" for="trustDevice">
|
||||
Eszköz megjelölése biztonságosként
|
||||
</label>
|
||||
<input name="TrustDevice" type="hidden" value="false">
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-center mb-3 mt-4">
|
||||
<button type="submit" class="btn-kreta">Kód ellenőrzése</button>
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-center mt-3">
|
||||
<span class="subtext">
|
||||
Nem fér hozzá eszközéhez? Lépjen be
|
||||
<button type="submit" class="btn-link" formaction="/account/loginwithrecoverycode">
|
||||
helyreállító kóddal.
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<footer class="login-footer">
|
||||
<a href="https://tudasbazis.ekreta.hu/pages/viewpage.action?pageId=4064926"
|
||||
target="_blank" class="privacy-link">Adatkezelési tájékoztató</a>
|
||||
</footer>
|
||||
</div>
|
||||
`;
|
||||
|
||||
document.body.innerHTML = newHTML;
|
||||
applyTheme();
|
||||
setupEventListeners();
|
||||
if (typeof loadingScreen !== 'undefined') {
|
||||
loadingScreen.hide();
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error transforming two-factor page:', error);
|
||||
if (typeof loadingScreen !== 'undefined') {
|
||||
loadingScreen.hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function applyTheme() {
|
||||
try {
|
||||
if (typeof getCookie === 'function') {
|
||||
const theme = getCookie('theme') || 'light-blue';
|
||||
document.documentElement.setAttribute('data-theme', theme);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error applying theme:', error);
|
||||
}
|
||||
}
|
||||
|
||||
function setupEventListeners() {
|
||||
const twoFactorForm = document.getElementById('twoFactorForm');
|
||||
const verificationInput = document.getElementById('VerificationCode');
|
||||
const togglePasswordBtn = document.querySelector('.show-password');
|
||||
const formInputs = document.querySelectorAll('.form-control');
|
||||
|
||||
if (togglePasswordBtn && verificationInput) {
|
||||
togglePasswordBtn.addEventListener('click', () => {
|
||||
const isPassword = verificationInput.type === 'password';
|
||||
verificationInput.type = isPassword ? 'text' : 'password';
|
||||
const icon = togglePasswordBtn.querySelector('.icon-eye');
|
||||
icon.src = chrome.runtime.getURL(`icons/${isPassword ? 'eye-on' : 'eye-off'}.svg`);
|
||||
});
|
||||
}
|
||||
formInputs.forEach(input => {
|
||||
input.addEventListener('input', () => {
|
||||
validateInput(input);
|
||||
});
|
||||
|
||||
input.addEventListener('blur', () => {
|
||||
validateInput(input, true);
|
||||
});
|
||||
});
|
||||
if (twoFactorForm) {
|
||||
twoFactorForm.addEventListener('submit', handleSubmit);
|
||||
}
|
||||
}
|
||||
|
||||
function validateInput(input, showError = false) {
|
||||
const isValid = input.value.trim().length > 0;
|
||||
const errorElement = input.nextElementSibling?.nextElementSibling;
|
||||
|
||||
if (!isValid && showError) {
|
||||
input.classList.add('error');
|
||||
errorElement?.classList.add('show');
|
||||
} else {
|
||||
input.classList.remove('error');
|
||||
errorElement?.classList.remove('show');
|
||||
}
|
||||
|
||||
return isValid;
|
||||
}
|
||||
|
||||
function handleSubmit(event) {
|
||||
event.preventDefault();
|
||||
|
||||
const form = event.target;
|
||||
const inputs = form.querySelectorAll('.form-control[required]');
|
||||
let isValid = true;
|
||||
inputs.forEach(input => {
|
||||
if (!validateInput(input, true)) {
|
||||
isValid = false;
|
||||
}
|
||||
});
|
||||
if (isValid) {
|
||||
const submitButton = form.querySelector('.btn-kreta');
|
||||
if (submitButton) {
|
||||
submitButton.disabled = true;
|
||||
submitButton.innerHTML = '<span class="spinner"></span><span class="btn-text">Ellenőrzés...</span>';
|
||||
}
|
||||
|
||||
form.submit();
|
||||
}
|
||||
}
|
||||
transformTwoFactorPage();
|
||||
@@ -1,21 +1,4 @@
|
||||
(() => {
|
||||
function getCookie(name) {
|
||||
const cookieName = `${name}=`;
|
||||
const decodedCookie = decodeURIComponent(document.cookie);
|
||||
const cookieArray = decodedCookie.split(';');
|
||||
|
||||
for(let i = 0; i < cookieArray.length; i++) {
|
||||
let cookie = cookieArray[i];
|
||||
while (cookie.charAt(0) === ' ') {
|
||||
cookie = cookie.substring(1);
|
||||
}
|
||||
if (cookie.indexOf(cookieName) === 0) {
|
||||
return cookie.substring(cookieName.length, cookie.length);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function loadFonts() {
|
||||
// Create a new style element
|
||||
const style = document.createElement('style');
|
||||
@@ -27,8 +10,8 @@
|
||||
}
|
||||
function transformLogoutPage() {
|
||||
// Get current theme and school ID from cookies
|
||||
const theme = getCookie('themePreference') || localStorage.getItem('themePreference') || 'light-blue';
|
||||
const instituteCode = getCookie('schoolSubdomain');
|
||||
const theme = cookieManager.get('themePreference') || localStorage.getItem('themePreference') || 'light-green';
|
||||
const instituteCode = cookieManager.get('schoolSubdomain');
|
||||
document.documentElement.setAttribute('data-theme', theme);
|
||||
|
||||
// Create new HTML structure
|
||||
|
||||
@@ -20,15 +20,16 @@
|
||||
"icons/*.svg",
|
||||
"grades/chart.js"
|
||||
],
|
||||
"matches": ["https://*.e-kreta.hu/*"]
|
||||
"matches": ["https://*.e-kreta.hu/*", "https://idp.e-kreta.hu/*"]
|
||||
}],
|
||||
"content_scripts": [
|
||||
{
|
||||
"matches": [
|
||||
"https://*.e-kreta.hu/*"
|
||||
],
|
||||
"js": ["global/maintenance.js", "global/theme.js", "global/navigation.js"],
|
||||
"css": ["global/theme.css", "global/navigation.css"],
|
||||
"js": ["tools/cookieManager.js", "tools/helper.js", "tools/loadingScreen.js", "tools/createTemplate.js",
|
||||
"global/maintenance.js", "global/theme.js", "global/navigation.js"],
|
||||
"css": ["tools/loadingScreen.css", "global/theme.css", "global/navigation.css"],
|
||||
"run_at": "document_start"
|
||||
},
|
||||
{
|
||||
@@ -43,6 +44,11 @@
|
||||
"js": ["login/login.js"],
|
||||
"css": ["login/login.css"]
|
||||
},
|
||||
{
|
||||
"matches": ["https://idp.e-kreta.hu/account/loginwithtwofactor*"],
|
||||
"js": ["login/twofactor.js"],
|
||||
"css": ["login/twofactor.css"]
|
||||
},
|
||||
{
|
||||
"matches": [
|
||||
"https://*.e-kreta.hu/Hianyzas/Hianyzasok*"
|
||||
@@ -114,6 +120,14 @@
|
||||
"js": ["homework/homework.js"],
|
||||
"css": ["homework/homework.css"],
|
||||
"run_at": "document_end"
|
||||
},
|
||||
{
|
||||
"matches": [
|
||||
"https://intezmenykereso.e-kreta.hu/"
|
||||
],
|
||||
"js": ["search/search.js"],
|
||||
"css": ["search/search.css"],
|
||||
"run_at": "document_end"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -59,37 +59,6 @@ body {
|
||||
max-width: 300px;
|
||||
}
|
||||
|
||||
|
||||
.nav-links {
|
||||
display: flex;
|
||||
gap: clamp(0.5rem, 2vw, 1rem);
|
||||
padding: 0.25rem;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.nav-links a {
|
||||
color: var(--text-secondary);
|
||||
text-decoration: none;
|
||||
padding: clamp(0.5rem, 1.5vw, 1rem) 0.5rem;
|
||||
font-weight: 500;
|
||||
white-space: nowrap;
|
||||
transition: all 0.2s ease;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.nav-links a:hover {
|
||||
color: var(--text-primary);
|
||||
background-color: var(--card-card);
|
||||
}
|
||||
|
||||
.nav-links a.active {
|
||||
color: var(--accent-accent);
|
||||
}
|
||||
|
||||
|
||||
.user-profile {
|
||||
position: relative;
|
||||
justify-self: flex-end;
|
||||
@@ -115,19 +84,6 @@ body {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.user-name {
|
||||
display: block;
|
||||
color: var(--text-primary);
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.user-time {
|
||||
display: block;
|
||||
color: var(--text-secondary);
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.user-dropdown {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
@@ -426,10 +382,10 @@ body {
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.kreta-header {
|
||||
grid-template-columns: 1fr auto;
|
||||
grid-template-columns: 1fr auto auto;
|
||||
grid-template-areas:
|
||||
"school user"
|
||||
"nav nav";
|
||||
"school toggle user"
|
||||
"nav nav nav";
|
||||
padding: 1rem;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
@@ -438,12 +394,6 @@ body {
|
||||
grid-area: school;
|
||||
}
|
||||
|
||||
.nav-links {
|
||||
grid-area: nav;
|
||||
margin-top: 0.5rem;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.user-profile {
|
||||
grid-area: user;
|
||||
}
|
||||
|
||||
@@ -1,34 +1,4 @@
|
||||
(() => {
|
||||
function getCookie(name) {
|
||||
const cookieName = `${name}=`;
|
||||
const decodedCookie = decodeURIComponent(document.cookie);
|
||||
const cookieArray = decodedCookie.split(';');
|
||||
|
||||
for(let i = 0; i < cookieArray.length; i++) {
|
||||
let cookie = cookieArray[i];
|
||||
while (cookie.charAt(0) === ' ') {
|
||||
cookie = cookie.substring(1);
|
||||
}
|
||||
if (cookie.indexOf(cookieName) === 0) {
|
||||
return cookie.substring(cookieName.length, cookie.length);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function shortenSchoolName(name) {
|
||||
if (!name) return '';
|
||||
const maxLength = 30;
|
||||
if (name.length <= maxLength) return name;
|
||||
|
||||
const parts = name.split(' - ');
|
||||
if (parts.length === 2) {
|
||||
const [code, fullName] = parts;
|
||||
return `${code} - ${fullName.substring(0, maxLength - code.length - 5)}...`;
|
||||
}
|
||||
return name.substring(0, maxLength - 3) + '...';
|
||||
}
|
||||
|
||||
(() => {
|
||||
function createSecurityTab() {
|
||||
return `
|
||||
<div class="security-content">
|
||||
@@ -196,8 +166,8 @@
|
||||
const saveButton = form.querySelector('#saveContacts');
|
||||
|
||||
|
||||
emailInput.value = getCookie('userEmail') || '';
|
||||
phoneInput.value = getCookie('userPhone') || '';
|
||||
emailInput.value = cookieManager.get('userEmail') || '';
|
||||
phoneInput.value = cookieManager.get('userPhone') || '';
|
||||
|
||||
saveButton?.addEventListener('click', async () => {
|
||||
const email = emailInput.value.trim();
|
||||
@@ -371,67 +341,10 @@
|
||||
}
|
||||
}
|
||||
|
||||
function createProfileHTML(data) {
|
||||
const schoolNameFull = `${data.schoolInfo.id} - ${data.schoolInfo.name}`;
|
||||
const shortenedSchoolName = shortenSchoolName(schoolNameFull);
|
||||
|
||||
function createProfileHTML() {
|
||||
return `
|
||||
<div class="kreta-container">
|
||||
<header class="kreta-header">
|
||||
<div class="school-info">
|
||||
<p class="logo-text">
|
||||
<img src=${chrome.runtime.getURL('images/firka_logo.png')} alt="Firka" class="logo">
|
||||
Firka
|
||||
</p>
|
||||
<div class="school-details" title="${schoolNameFull}">
|
||||
${shortenedSchoolName}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<nav class="kreta-nav">
|
||||
<div class="nav-links">
|
||||
<a href="/Intezmeny/Faliujsag">
|
||||
<span class="material-icons-round">calendar_today</span>
|
||||
Kezdőlap
|
||||
</a>
|
||||
<a href="/TanuloErtekeles/Osztalyzatok">
|
||||
<span class="material-icons-round">bookmark_border</span>
|
||||
Jegyek
|
||||
</a>
|
||||
<a href="/Orarend/InformaciokOrarend">
|
||||
<span class="material-icons-round">home</span>
|
||||
Órarend
|
||||
</a>
|
||||
<a href="/Hianyzas/Hianyzasok">
|
||||
<span class="material-icons-round">schedule</span>
|
||||
Hiányok
|
||||
</a>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="user-profile">
|
||||
<button class="user-dropdown-btn">
|
||||
<div class="user-info">
|
||||
<span class="user-name">${data.userData.name}</span>
|
||||
<span class="user-time" id="logoutTimer">${data.userData.time}</span>
|
||||
</div>
|
||||
</button>
|
||||
<div class="user-dropdown">
|
||||
<a href="/Adminisztracio/Profil" class="dropdown-item">
|
||||
<span class="material-icons-round">person</span>
|
||||
Profil
|
||||
</a>
|
||||
<a href="#" class="dropdown-item" id="settingsBtn">
|
||||
<span class="material-icons-round">settings</span>
|
||||
Beállítások
|
||||
</a>
|
||||
<a href="/Home/Logout" class="dropdown-item">
|
||||
<span class="material-icons-round">logout</span>
|
||||
Kijelentkezés
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
${createTemplate.header()}
|
||||
|
||||
<main class="kreta-main">
|
||||
<div class="card">
|
||||
@@ -469,34 +382,11 @@
|
||||
async function init() {
|
||||
if (window.location.pathname.includes('/Adminisztracio/Profil')) {
|
||||
|
||||
const links = [
|
||||
{ rel: 'preconnect', href: 'https://fonts.googleapis.com' },
|
||||
{ rel: 'preconnect', href: 'https://fonts.gstatic.com', crossorigin: true },
|
||||
{ rel: 'stylesheet', href: 'https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap' },
|
||||
{ rel: 'stylesheet', href: 'https://fonts.googleapis.com/icon?family=Material+Icons+Round' }
|
||||
];
|
||||
createTemplate.importFonts();
|
||||
|
||||
links.forEach(link => {
|
||||
const linkElement = document.createElement('link');
|
||||
Object.entries(link).forEach(([key, value]) => {
|
||||
linkElement[key] = value;
|
||||
});
|
||||
document.head.appendChild(linkElement);
|
||||
});
|
||||
|
||||
const userData = {
|
||||
schoolInfo: {
|
||||
name: getCookie('schoolName') || 'Iskola',
|
||||
id: getCookie('schoolCode') || ''
|
||||
},
|
||||
userData: {
|
||||
name: getCookie('userName') || 'Felhasználó',
|
||||
time: document.querySelector('.usermenu_timer')?.textContent?.trim() || '45:00',
|
||||
email: getCookie('userEmail') || ''
|
||||
}
|
||||
};
|
||||
|
||||
document.body.innerHTML = createProfileHTML(userData);
|
||||
document.body.innerHTML = createProfileHTML();
|
||||
setupUserDropdown();
|
||||
setupMobileNavigation();
|
||||
setupEventListeners();
|
||||
setupContactForm();
|
||||
}
|
||||
|
||||
@@ -1,11 +1,4 @@
|
||||
(() => {
|
||||
|
||||
const setCookie = (name, value, days = 365) => {
|
||||
const date = new Date();
|
||||
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
|
||||
document.cookie = `${name}=${value}; expires=${date.toUTCString()}; path=/; domain=.e-kreta.hu`;
|
||||
};
|
||||
|
||||
const startLogoutTimer = () => {
|
||||
let timeLeft = 45 * 60;
|
||||
const timerElement = document.getElementById('logoutTimer');
|
||||
@@ -124,30 +117,18 @@
|
||||
|
||||
|
||||
if (schoolCode && fullSchoolName) {
|
||||
setCookie('schoolCode', schoolCode);
|
||||
setCookie('schoolName', fullSchoolName);
|
||||
setCookie('schoolSubdomain', schoolSubdomain);
|
||||
cookieManager.set('schoolCode', schoolCode);
|
||||
cookieManager.set('schoolName', fullSchoolName);
|
||||
cookieManager.set('schoolSubdomain', schoolSubdomain);
|
||||
}
|
||||
if (userName) {
|
||||
setCookie('userName', userName);
|
||||
cookieManager.set('userName', userName);
|
||||
}
|
||||
|
||||
|
||||
document.body.innerHTML = createHTML(schoolCode, fullSchoolName, userName);
|
||||
|
||||
|
||||
const links = [
|
||||
{ rel: 'preconnect', href: 'https://fonts.googleapis.com' },
|
||||
{ rel: 'preconnect', href: 'https://fonts.gstatic.com', crossorigin: true },
|
||||
{ href: 'https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&family=Figtree:wght@300..900&display=swap', rel: 'stylesheet' }
|
||||
];
|
||||
|
||||
links.forEach(link => {
|
||||
const linkElement = document.createElement('link');
|
||||
Object.entries(link).forEach(([key, value]) => linkElement[key] = value);
|
||||
document.head.appendChild(linkElement);
|
||||
});
|
||||
|
||||
createTemplate.importFonts();
|
||||
|
||||
const timerInterval = startLogoutTimer();
|
||||
|
||||
|
||||
247
search/search.css
Normal file
247
search/search.css
Normal file
@@ -0,0 +1,247 @@
|
||||
@font-face {
|
||||
font-family: 'Montserrat';
|
||||
src: url('chrome-extension://__MSG_@@extension_id__/fonts/Montserrat-Regular.woff2') format('woff2');
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Montserrat';
|
||||
src: url('chrome-extension://__MSG_@@extension_id__/fonts/Montserrat-Medium.woff2') format('woff2');
|
||||
font-weight: 500;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Montserrat';
|
||||
src: url('chrome-extension://__MSG_@@extension_id__/fonts/Montserrat-SemiBold.woff2') format('woff2');
|
||||
font-weight: 600;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Figtree';
|
||||
src: url('chrome-extension://__MSG_@@extension_id__/fonts/Figtree-Regular.woff2') format('woff2');
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
/* Hide original elements */
|
||||
header, footer, .page-title, .card-kreta {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
color: var(--text-primary);
|
||||
background-color: var(--background) !important;
|
||||
font-family: "Montserrat", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif !important;
|
||||
min-height: 100vh;
|
||||
font-size: 16px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
/* Firka search page styling */
|
||||
.firka-search-wrapper {
|
||||
width: 90%;
|
||||
max-width: 500px;
|
||||
padding: 0;
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
/* Firka header styling */
|
||||
.firka-header {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
margin: 0;
|
||||
background: var(--card-card) !important;
|
||||
padding: 24px;
|
||||
border-radius: 24px 24px 0 0;
|
||||
width: 100%;
|
||||
box-shadow: 0px 1px var(--shadow-blur) 0px var(--accent-shadow);
|
||||
}
|
||||
|
||||
.logo-text {
|
||||
color: var(--text-primary);
|
||||
text-align: center;
|
||||
font-family: Montserrat;
|
||||
font-size: 20px;
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
line-height: normal;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.logo {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
.search-title {
|
||||
color: var(--text-primary);
|
||||
text-align: center;
|
||||
font-family: Montserrat;
|
||||
font-size: 24px;
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
line-height: normal;
|
||||
margin: 8px 0;
|
||||
}
|
||||
|
||||
/* Form container styling */
|
||||
.firka-form-container {
|
||||
background: var(--card-card);
|
||||
padding: 0 24px 24px 24px;
|
||||
border-radius: 0 0 24px 24px;
|
||||
width: 100%;
|
||||
box-shadow: 0px 1px var(--shadow-blur) 0px var(--accent-shadow);
|
||||
}
|
||||
|
||||
/* Form styling */
|
||||
form {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.form-control {
|
||||
background-color: var(--button-secondaryFill) !important;
|
||||
border: 1px solid var(--accent-15) !important;
|
||||
border-radius: 12px !important;
|
||||
color: var(--text-primary) !important;
|
||||
padding: 12px 16px !important;
|
||||
font-family: Montserrat !important;
|
||||
font-size: 16px !important;
|
||||
font-weight: 400 !important;
|
||||
height: auto !important;
|
||||
transition: border-color 0.2s ease-in-out, box-shadow 0.2s ease-in-out;
|
||||
}
|
||||
|
||||
.form-control:focus {
|
||||
border-color: var(--accent-accent) !important;
|
||||
box-shadow: 0 0 0 2px var(--accent-15) !important;
|
||||
outline: none !important;
|
||||
}
|
||||
|
||||
.form-control::placeholder {
|
||||
color: var(--text-teritary) !important;
|
||||
}
|
||||
|
||||
/* Autocomplete dropdown styling */
|
||||
.dropdown-menu {
|
||||
background-color: var(--card-card) !important;
|
||||
border: 1px solid var(--accent-15) !important;
|
||||
border-radius: 12px !important;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1) !important;
|
||||
padding: 8px !important;
|
||||
max-height: 300px !important;
|
||||
overflow-y: auto !important;
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
.dropdown-item {
|
||||
color: var(--text-primary) !important;
|
||||
padding: 10px 16px !important;
|
||||
border-radius: 8px !important;
|
||||
margin-bottom: 4px !important;
|
||||
font-family: Montserrat !important;
|
||||
font-size: 14px !important;
|
||||
transition: background-color 0.2s ease-in-out !important;
|
||||
}
|
||||
|
||||
li.dropdown-item:hover, li.dropdown-item:focus {
|
||||
background-color: var(--accent-15) !important;
|
||||
color: var(--text-primary) !important;
|
||||
}
|
||||
|
||||
a.dropdown-item:hover, a.dropdown-item:focus {
|
||||
background-color: #00000000 !important;
|
||||
}
|
||||
|
||||
.dropdown-item.active {
|
||||
background-color: var(--accent-accent) !important;
|
||||
color: white !important;
|
||||
}
|
||||
|
||||
/* Button styling */
|
||||
.btn-kreta {
|
||||
background-color: var(--accent-accent) !important;
|
||||
color: white !important;
|
||||
border: none !important;
|
||||
border-radius: 12px !important;
|
||||
padding: 12px 24px !important;
|
||||
font-family: Montserrat !important;
|
||||
font-size: 16px !important;
|
||||
font-weight: 600 !important;
|
||||
cursor: pointer !important;
|
||||
transition: background-color 0.2s ease-in-out, transform 0.1s ease-in-out !important;
|
||||
display: inline-flex !important;
|
||||
align-items: center !important;
|
||||
justify-content: center !important;
|
||||
}
|
||||
|
||||
.btn-kreta:hover {
|
||||
background-color: var(--accent-secondary) !important;
|
||||
transform: translateY(-1px) !important;
|
||||
}
|
||||
|
||||
.btn-kreta:active {
|
||||
transform: translateY(1px) !important;
|
||||
}
|
||||
|
||||
.btn-kreta:disabled {
|
||||
background-color: var(--text-teritary) !important;
|
||||
cursor: not-allowed !important;
|
||||
transform: none !important;
|
||||
}
|
||||
|
||||
/* Footer styling */
|
||||
.firka-footer {
|
||||
margin-top: 16px;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.privacy-link {
|
||||
color: var(--text-secondary);
|
||||
font-family: Montserrat;
|
||||
font-size: 14px;
|
||||
text-decoration: none;
|
||||
transition: color 0.2s ease-in-out;
|
||||
}
|
||||
|
||||
.privacy-link:hover {
|
||||
color: var(--accent-accent);
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/* Responsive adjustments */
|
||||
@media (max-width: 576px) {
|
||||
.firka-search-wrapper {
|
||||
width: 95%;
|
||||
}
|
||||
|
||||
.search-title {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.btn-kreta {
|
||||
padding: 10px 20px !important;
|
||||
font-size: 14px !important;
|
||||
}
|
||||
}
|
||||
124
search/search.js
Normal file
124
search/search.js
Normal file
@@ -0,0 +1,124 @@
|
||||
function initializeTransformation() {
|
||||
const form = document.querySelector('form');
|
||||
const autocomplete = document.querySelector('.autocomplete');
|
||||
|
||||
if (form && autocomplete) {
|
||||
applyFirkaStyling();
|
||||
} else {
|
||||
setTimeout(initializeTransformation, 500);
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
setTimeout(initializeTransformation, 1000);
|
||||
});
|
||||
|
||||
if (document.readyState === 'complete' || document.readyState === 'interactive') {
|
||||
setTimeout(initializeTransformation, 1000);
|
||||
}
|
||||
|
||||
function applyFirkaStyling() {
|
||||
try {
|
||||
const theme = cookieManager.get('themePreference') || localStorage.getItem('themePreference') || 'light-green';
|
||||
document.documentElement.setAttribute('data-theme', theme);
|
||||
if (typeof loadingScreen !== 'undefined') {
|
||||
loadingScreen.hide();
|
||||
}
|
||||
const originalForm = document.querySelector('form');
|
||||
const instituteInput = document.querySelector('.autocomplete');
|
||||
const redirectButton = document.getElementById('redirectToInstitute');
|
||||
const instituteCodeInput = document.querySelector('.autocomplete-value');
|
||||
const requestToken = document.querySelector('input[name="__RequestVerificationToken"]');
|
||||
const searchWrapper = document.createElement('div');
|
||||
searchWrapper.className = 'firka-search-wrapper';
|
||||
const firkaHeader = document.createElement('div');
|
||||
firkaHeader.className = 'firka-header';
|
||||
firkaHeader.innerHTML = `
|
||||
<p class="logo-text">
|
||||
<img src="${chrome.runtime.getURL('images/firka_logo.png')}" alt="Firka" class="logo">
|
||||
Firka
|
||||
</p>
|
||||
<h1 class="search-title">Válassz iskolát</h1>
|
||||
`;
|
||||
const formContainer = document.createElement('div');
|
||||
formContainer.className = 'firka-form-container';
|
||||
const firkaFooter = document.createElement('div');
|
||||
firkaFooter.className = 'firka-footer';
|
||||
firkaFooter.innerHTML = `
|
||||
<a href="https://tudasbazis.ekreta.hu/pages/viewpage.action?pageId=4064926"
|
||||
target="_blank" class="privacy-link">Adatkezelési tájékoztató</a>
|
||||
`;
|
||||
const existingWrapper = document.querySelector('.firka-search-wrapper');
|
||||
if (existingWrapper) {
|
||||
existingWrapper.remove();
|
||||
}
|
||||
searchWrapper.appendChild(firkaHeader);
|
||||
if (originalForm) {
|
||||
formContainer.appendChild(originalForm);
|
||||
searchWrapper.appendChild(formContainer);
|
||||
}
|
||||
searchWrapper.appendChild(firkaFooter);
|
||||
document.body.appendChild(searchWrapper);
|
||||
setupAutocompleteListeners();
|
||||
if (redirectButton) {
|
||||
redirectButton.addEventListener('click', function(event) {
|
||||
if (!instituteCodeInput.value) {
|
||||
event.preventDefault();
|
||||
alert('Kérjük, válasszon egy intézményt a folytatáshoz!');
|
||||
}
|
||||
});
|
||||
}
|
||||
observeAutocompleteValue(instituteCodeInput, redirectButton);
|
||||
} catch (error) {
|
||||
console.error('Error applying Firka styling:', error);
|
||||
}
|
||||
}
|
||||
|
||||
function setupAutocompleteListeners() {
|
||||
const autocompleteInput = document.querySelector('.autocomplete');
|
||||
const autocompleteValue = document.querySelector('.autocomplete-value');
|
||||
const redirectButton = document.getElementById('redirectToInstitute');
|
||||
|
||||
if (autocompleteInput && autocompleteValue) {
|
||||
const observer = new MutationObserver((mutations) => {
|
||||
const dropdown = document.querySelector('.autocomplete-dropdown');
|
||||
if (dropdown) {
|
||||
dropdown.classList.add('dropdown-menu');
|
||||
const items = dropdown.querySelectorAll('li');
|
||||
items.forEach(item => {
|
||||
item.classList.add('dropdown-item');
|
||||
item.addEventListener('click', () => {
|
||||
if (redirectButton) {
|
||||
redirectButton.disabled = false;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
observer.observe(document.body, {
|
||||
childList: true,
|
||||
subtree: true
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function observeAutocompleteValue(valueInput, button) {
|
||||
if (!valueInput || !button) return;
|
||||
|
||||
const observer = new MutationObserver((mutations) => {
|
||||
button.disabled = !valueInput.value;
|
||||
});
|
||||
|
||||
observer.observe(valueInput, {
|
||||
attributes: true,
|
||||
attributeFilter: ['value']
|
||||
});
|
||||
|
||||
const checkInterval = setInterval(() => {
|
||||
if (valueInput.value) {
|
||||
button.disabled = false;
|
||||
clearInterval(checkInterval);
|
||||
}
|
||||
}, 500);
|
||||
}
|
||||
@@ -3,7 +3,9 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Firxa Beállítások</title>
|
||||
<title>Firxa - Beállítások</title>
|
||||
<link rel="icon" type="image/png" href="../images/firka_logo_128.png">
|
||||
<link rel="shortcut icon" type="image/png" href="../images/firka_logo_128.png">
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap" rel="stylesheet">
|
||||
|
||||
@@ -1,5 +1,26 @@
|
||||
document.addEventListener('DOMContentLoaded', async () => {
|
||||
|
||||
function isThemeDisabled(theme) {
|
||||
const blueThemesUnlocked = localStorage.getItem('blueThemesUnlocked') === 'true';
|
||||
return (theme === 'default' || theme === 'light-blue' || theme === 'dark-blue') && !blueThemesUnlocked;
|
||||
}
|
||||
|
||||
function updateThemeAvailability() {
|
||||
const blueThemesUnlocked = localStorage.getItem('blueThemesUnlocked') === 'true';
|
||||
document.querySelectorAll('.theme-option').forEach(button => {
|
||||
const theme = button.dataset.theme;
|
||||
if (theme === 'default' || theme === 'light-blue' || theme === 'dark-blue') {
|
||||
if (blueThemesUnlocked) {
|
||||
button.style.display = 'block';
|
||||
button.classList.remove('disabled');
|
||||
button.removeAttribute('disabled');
|
||||
} else {
|
||||
button.style.display = 'none';
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function getCookie(name) {
|
||||
const cookieName = `${name}=`;
|
||||
const decodedCookie = decodeURIComponent(document.cookie);
|
||||
@@ -25,43 +46,21 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||
document.cookie = `${name}=${value}; ${expires}; path=/; domain=.e-kreta.hu`;
|
||||
}
|
||||
|
||||
async function getCurrentTheme() {
|
||||
try {
|
||||
const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
|
||||
const response = await chrome.tabs.sendMessage(tab.id, { action: 'getTheme' });
|
||||
return response.theme;
|
||||
} catch (error) {
|
||||
console.error('Error getting current theme:', error);
|
||||
return 'default';
|
||||
}
|
||||
function getCurrentTheme() {
|
||||
return localStorage.getItem('themePreference') ||
|
||||
getCookie('themePreference') ||
|
||||
'light-green';
|
||||
}
|
||||
|
||||
function updateThemeButtons(currentTheme) {
|
||||
document.querySelectorAll('.theme-option').forEach(button => {
|
||||
const theme = button.dataset.theme;
|
||||
button.classList.toggle('active', theme === currentTheme);
|
||||
|
||||
|
||||
/*if (theme === 'light-blue' || theme === 'dark-blue' || theme === 'default') {
|
||||
button.classList.add('disabled');
|
||||
button.setAttribute('disabled', 'true');
|
||||
}*/
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function isThemeDisabled(theme) {
|
||||
return theme === 'default' || theme === 'dark-blue';
|
||||
updateThemeAvailability();
|
||||
}
|
||||
|
||||
async function applyTheme(theme) {
|
||||
|
||||
if (isThemeDisabled(theme)) {
|
||||
alert('Ez a téma jelenleg nem elérhető.');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
setCookie('themePreference', theme);
|
||||
localStorage.setItem('themePreference', theme);
|
||||
|
||||
@@ -101,10 +100,7 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||
});
|
||||
|
||||
|
||||
let initialTheme = localStorage.getItem('themePreference') ||
|
||||
getCookie('themePreference') ||
|
||||
await getCurrentTheme() ||
|
||||
'light-green';
|
||||
let initialTheme = getCurrentTheme();
|
||||
|
||||
|
||||
if (isThemeDisabled(initialTheme)) {
|
||||
@@ -112,6 +108,7 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||
}
|
||||
|
||||
|
||||
updateThemeAvailability();
|
||||
await applyTheme(initialTheme);
|
||||
|
||||
|
||||
@@ -124,7 +121,56 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||
|
||||
|
||||
const manifest = chrome.runtime.getManifest();
|
||||
document.getElementById('version').textContent = `v${manifest.version}`;
|
||||
const versionElement = document.getElementById('version');
|
||||
versionElement.textContent = `v${manifest.version}`;
|
||||
|
||||
|
||||
let clickCount = 0;
|
||||
versionElement.addEventListener('click', () => {
|
||||
clickCount++;
|
||||
if (clickCount >= 5) {
|
||||
localStorage.setItem('blueThemesUnlocked', 'true');
|
||||
updateThemeAvailability();
|
||||
|
||||
|
||||
const notification = document.createElement('div');
|
||||
notification.style.cssText = `
|
||||
position: fixed;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
background: var(--accent-accent);
|
||||
color: white;
|
||||
padding: 12px 20px;
|
||||
border-radius: 8px;
|
||||
font-family: 'Montserrat', sans-serif;
|
||||
font-weight: 500;
|
||||
z-index: 10000;
|
||||
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
|
||||
animation: slideIn 0.3s ease-out;
|
||||
`;
|
||||
notification.textContent = 'Kék témák feloldva! 🎉';
|
||||
|
||||
|
||||
const style = document.createElement('style');
|
||||
style.textContent = `
|
||||
@keyframes slideIn {
|
||||
from { transform: translateX(100%); opacity: 0; }
|
||||
to { transform: translateX(0); opacity: 1; }
|
||||
}
|
||||
`;
|
||||
document.head.appendChild(style);
|
||||
|
||||
document.body.appendChild(notification);
|
||||
|
||||
|
||||
setTimeout(() => {
|
||||
notification.remove();
|
||||
style.remove();
|
||||
}, 3000);
|
||||
|
||||
clickCount = 0;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
themeButtons.forEach(button => {
|
||||
|
||||
@@ -43,57 +43,6 @@ body {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
/* Loading Screen */
|
||||
.loading-screen {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: var(--background);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
.loading-logo {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
border-radius: 16px;
|
||||
}
|
||||
|
||||
.loading-text {
|
||||
color: var(--text-primary);
|
||||
text-align: center;
|
||||
font-family: Montserrat;
|
||||
font-size: 20px;
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
.loading-text2 {
|
||||
align-self: stretch;
|
||||
color: var(--text-secondary);
|
||||
text-align: center;
|
||||
font-family: Figtree;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
line-height: 130%;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
body {
|
||||
font-size: 14px;
|
||||
@@ -123,10 +72,10 @@ body {
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.kreta-header {
|
||||
grid-template-columns: 1fr auto;
|
||||
grid-template-columns: 1fr auto auto;
|
||||
grid-template-areas:
|
||||
"school user"
|
||||
"nav nav";
|
||||
"school toggle user"
|
||||
"nav nav nav";
|
||||
padding: 1rem;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
@@ -191,81 +140,6 @@ body {
|
||||
}
|
||||
}
|
||||
|
||||
/* Updated navigation styles */
|
||||
.kreta-nav {
|
||||
padding: 0 clamp(0.5rem, 3vw, 1.5rem);
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 100;
|
||||
overflow-x: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
scrollbar-width: none;
|
||||
-ms-overflow-style: none;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.kreta-nav {
|
||||
grid-area: nav;
|
||||
padding: 0;
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.kreta-nav::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.nav-links {
|
||||
display: flex;
|
||||
gap: clamp(0.5rem, 2vw, 1rem);
|
||||
padding: 0.25rem;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.nav-links {
|
||||
justify-content: flex-start;
|
||||
width: 100%;
|
||||
gap: 0.25rem;
|
||||
}
|
||||
}
|
||||
|
||||
.nav-links a {
|
||||
color: var(--text-secondary);
|
||||
text-decoration: none;
|
||||
padding: clamp(0.5rem, 1.5vw, 1rem) 0.5rem;
|
||||
font-weight: 500;
|
||||
white-space: nowrap;
|
||||
transition: all 0.2s ease;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.nav-links a {
|
||||
padding: 0.5rem;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.nav-links a .material-icons-round {
|
||||
font-size: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.nav-links a:hover {
|
||||
color: var(--text-primary);
|
||||
text-decoration: none;
|
||||
background-color: var(--card-card);
|
||||
}
|
||||
|
||||
.nav-links a.active {
|
||||
color: var(--accent-accent);
|
||||
}
|
||||
|
||||
/* User profile styles */
|
||||
.user-profile {
|
||||
position: relative;
|
||||
@@ -298,19 +172,6 @@ body {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.user-name {
|
||||
display: block;
|
||||
color: var(--text-primary);
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.user-time {
|
||||
display: block;
|
||||
color: var(--text-secondary);
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.user-dropdown {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
@@ -343,7 +204,6 @@ body {
|
||||
background: var(--button-secondaryFill);
|
||||
}
|
||||
|
||||
/* Main content styles */
|
||||
.kreta-main {
|
||||
flex: 1;
|
||||
padding: clamp(1rem, 3vw, 2rem);
|
||||
@@ -352,7 +212,10 @@ body {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Card styles */
|
||||
.k-overlay, .k-widget.k-window {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.card {
|
||||
border-radius: 24px;
|
||||
overflow: hidden;
|
||||
@@ -360,7 +223,6 @@ body {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
/* Timetable specific styles */
|
||||
.timetable-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 80px repeat(5, 1fr);
|
||||
@@ -419,10 +281,8 @@ body {
|
||||
border-radius: 12px;
|
||||
padding: 8px;
|
||||
transition: transform 0.2s ease;
|
||||
}
|
||||
|
||||
.lesson-slot:hover {
|
||||
transform: scale(1.02);
|
||||
display: grid;
|
||||
grid-gap: 16px;
|
||||
}
|
||||
|
||||
.lesson-card {
|
||||
@@ -537,7 +397,6 @@ body {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* Week selector styling */
|
||||
.week-controls {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
@@ -578,7 +437,6 @@ body {
|
||||
color: var(--accent-accent);
|
||||
}
|
||||
|
||||
/* Responsive adjustments */
|
||||
@media (max-width: 1024px) {
|
||||
.timetable-grid {
|
||||
grid-template-columns: 60px repeat(5, minmax(200px, 1fr));
|
||||
@@ -609,7 +467,6 @@ body {
|
||||
}
|
||||
}
|
||||
|
||||
/* Modal styles */
|
||||
.lesson-modal {
|
||||
display: none;
|
||||
position: fixed;
|
||||
@@ -627,7 +484,7 @@ body {
|
||||
}
|
||||
|
||||
.lesson-modal.show {
|
||||
display: flex;
|
||||
display: flex !important;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
@@ -736,6 +593,14 @@ body {
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.detail-item .line-through {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
.detail-item.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Animations */
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
@@ -781,27 +646,11 @@ body {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.nav-links {
|
||||
justify-content: start;
|
||||
overflow-x: auto;
|
||||
padding-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.nav-links::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.lesson-cell {
|
||||
min-width: 200px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Material Icons */
|
||||
.material-icons-round {
|
||||
font-size: 20px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
/* Scrollbar styling */
|
||||
::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
|
||||
@@ -1,104 +1,20 @@
|
||||
(() => {
|
||||
// Segédfüggvények
|
||||
function convertTimeToMinutes(timeStr) {
|
||||
const [hours, minutes] = timeStr.split(':').map(Number);
|
||||
return hours * 60 + minutes;
|
||||
}
|
||||
function getCookie(name) {
|
||||
const cookieName = `${name}=`;
|
||||
const decodedCookie = decodeURIComponent(document.cookie);
|
||||
const cookieArray = decodedCookie.split(';');
|
||||
|
||||
for(let i = 0; i < cookieArray.length; i++) {
|
||||
let cookie = cookieArray[i];
|
||||
while (cookie.charAt(0) === ' ') {
|
||||
cookie = cookie.substring(1);
|
||||
}
|
||||
if (cookie.indexOf(cookieName) === 0) {
|
||||
return cookie.substring(cookieName.length, cookie.length);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function shortenSchoolName(name, maxLength = 50) {
|
||||
if (!name) return '';
|
||||
if (name.length <= maxLength) return name;
|
||||
|
||||
const parts = name.split(' - ');
|
||||
if (parts.length === 2) {
|
||||
const [code, fullName] = parts;
|
||||
if (fullName.length > maxLength - code.length - 3) {
|
||||
return `${code} - ${fullName.substring(0, maxLength - code.length - 6)}...`;
|
||||
}
|
||||
}
|
||||
return name.substring(0, maxLength - 3) + '...';
|
||||
}
|
||||
|
||||
function showLoadingScreen() {
|
||||
const loadingScreen = document.createElement('div');
|
||||
loadingScreen.className = 'loading-screen';
|
||||
loadingScreen.innerHTML = `
|
||||
<img src="https://i.imgur.com/JE3LzRc.gif" alt="Firka" class="loading-logo">
|
||||
<div class="loading-text">Betöltés alatt...</div>
|
||||
<p class="loading-text2">Kis türelmet!</p>
|
||||
`;
|
||||
document.body.appendChild(loadingScreen);
|
||||
}
|
||||
|
||||
function hideLoadingScreen() {
|
||||
const loadingScreen = document.querySelector('.loading-screen');
|
||||
if (loadingScreen) {
|
||||
loadingScreen.style.opacity = '0';
|
||||
loadingScreen.style.transition = 'opacity 0.3s ease';
|
||||
setTimeout(() => loadingScreen.remove(), 300);
|
||||
}
|
||||
}
|
||||
|
||||
// DOM elemek várása
|
||||
function waitForElement(selector) {
|
||||
return new Promise(resolve => {
|
||||
if (document.querySelector(selector)) {
|
||||
return resolve(document.querySelector(selector));
|
||||
}
|
||||
|
||||
const observer = new MutationObserver(mutations => {
|
||||
if (document.querySelector(selector)) {
|
||||
observer.disconnect();
|
||||
resolve(document.querySelector(selector));
|
||||
}
|
||||
});
|
||||
|
||||
observer.observe(document.body, {
|
||||
childList: true,
|
||||
subtree: true
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Órarendi adatok gyűjtése
|
||||
async function collectTimetableData() {
|
||||
await waitForElement('#Calendar');
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
await helper.waitForElement('#Calendar');
|
||||
await helper.waitForElement('.modalBckgroundMain:not(.isOverlayActiv)');
|
||||
|
||||
const calendar = document.querySelector('#Calendar');
|
||||
const dates = Array.from(document.querySelectorAll('.fc-day-header')).map(header => {
|
||||
const fullText = header.textContent.trim();
|
||||
// Remove the day name from the beginning and clean up the format
|
||||
const dateText = fullText.replace(/^(hétfő|kedd|szerda|csütörtök|péntek)/, '').trim();
|
||||
return {
|
||||
date: fullText,
|
||||
formattedDate: dateText
|
||||
};
|
||||
});
|
||||
// Fix the Thursday issue by ensuring we have all 5 days
|
||||
if (dates.length === 4) {
|
||||
// Get Wednesday's date parts
|
||||
const wedDate = dates[2].formattedDate;
|
||||
const [month, day] = wedDate.split(' ');
|
||||
const dayNum = parseInt(day.replace('.', ''));
|
||||
|
||||
// Create Thursday's date
|
||||
const thursdayDate = `${month} ${dayNum + 1}.`;
|
||||
|
||||
dates.splice(3, 0, {
|
||||
@@ -106,9 +22,8 @@
|
||||
formattedDate: thursdayDate
|
||||
});
|
||||
}
|
||||
// Set week selector based on the current date
|
||||
const weekOptions = Array.from(document.querySelectorAll('#Calendar_tanevHetek_listbox li'));
|
||||
const currentDate = dates[0]?.formattedDate; // Using Monday's date
|
||||
const currentDate = dates[0]?.formattedDate;
|
||||
const matchingWeek = weekOptions.find(opt => opt.textContent.includes(currentDate));
|
||||
|
||||
if (matchingWeek) {
|
||||
@@ -121,11 +36,11 @@
|
||||
}
|
||||
const timetableData = {
|
||||
schoolInfo: {
|
||||
name: getCookie('schoolName') || 'Iskola',
|
||||
id: getCookie('schoolCode') || ''
|
||||
name: cookieManager.get('schoolName') || 'Iskola',
|
||||
id: cookieManager.get('schoolCode') || ''
|
||||
},
|
||||
userData: {
|
||||
name: getCookie('userName') || 'Felhasználó',
|
||||
name: cookieManager.get('userName') || 'Felhasználó',
|
||||
time: document.querySelector('.usermenu_timer')?.textContent?.trim() || '45:00'
|
||||
},
|
||||
weekInfo: {
|
||||
@@ -137,12 +52,11 @@
|
||||
selected: li.classList.contains('k-state-selected')
|
||||
}))
|
||||
},
|
||||
weekDates: dates, // Add the dates to the data object
|
||||
weekDates: dates,
|
||||
lessons: []
|
||||
};
|
||||
|
||||
// Órák adatainak gyűjtése
|
||||
document.querySelectorAll('.fc-event').forEach(event => {
|
||||
|
||||
for (const event of document.querySelectorAll('.fc-event')) {
|
||||
const timeEl = event.querySelector('.fc-time');
|
||||
const titleEl = event.querySelector('.fc-title');
|
||||
|
||||
@@ -151,11 +65,20 @@
|
||||
const [fullSubject, teacher, room] = titleEl.innerHTML.split('<br>').map(str => str.trim());
|
||||
const subject = fullSubject.split('-')[0].trim();
|
||||
|
||||
let originalTeacher = '';
|
||||
if (teacher.startsWith('Helyettesítő:')) {
|
||||
event.click();
|
||||
originalTeacher = await helper.waitForElement("#OraAdatokDetailTabStrip-1 > div > div:nth-child(3) > div:nth-child(2)");
|
||||
originalTeacher = originalTeacher.innerText;
|
||||
document.querySelector("body > div.k-widget.k-window > div.k-window-titlebar.k-header > div > a:nth-child(2)").click();
|
||||
}
|
||||
|
||||
timetableData.lessons.push({
|
||||
startTime,
|
||||
endTime,
|
||||
subject: subject || '',
|
||||
teacher: teacher || '',
|
||||
originalTeacher: originalTeacher || '',
|
||||
room: (room || '').replace(/[()]/g, ''),
|
||||
day: event.closest('td').cellIndex - 1,
|
||||
isSubstituted: event.querySelector('.fc-bg2') !== null,
|
||||
@@ -165,16 +88,14 @@
|
||||
homeworkDetails: event.getAttribute('data-homework') || ''
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
return timetableData;
|
||||
}
|
||||
|
||||
// Grid generálása
|
||||
function generateTimeGrid(lessons, weekDates) {
|
||||
const times = [...new Set(lessons.map(l => l.startTime))].sort((a, b) => {
|
||||
const timeA = convertTimeToMinutes(a);
|
||||
const timeB = convertTimeToMinutes(b);
|
||||
const timeA = helper.convertTimeToMinutes(a);
|
||||
const timeB = helper.convertTimeToMinutes(b);
|
||||
return timeA - timeB;
|
||||
});
|
||||
const days = ['Hétfő', 'Kedd', 'Szerda', 'Csütörtök', 'Péntek'];
|
||||
@@ -226,7 +147,6 @@
|
||||
`).join('')}
|
||||
`;
|
||||
}
|
||||
// Óra részletek modal
|
||||
function showLessonModal(lesson) {
|
||||
const modal = document.createElement('div');
|
||||
modal.className = 'lesson-modal';
|
||||
@@ -242,7 +162,11 @@
|
||||
<div class="lesson-details">
|
||||
<div class="detail-item">
|
||||
<span class="detail-label">Tanár:</span>
|
||||
<span class="detail-value">${lesson.teacher}</span>
|
||||
<span class="detail-value ${(lesson.originalTeacher != '' ? 'line-through' : '')}">${lesson.originalTeacher != '' ? lesson.originalTeacher : lesson.teacher}</span>
|
||||
</div>
|
||||
<div class="detail-item ${(lesson.originalTeacher != '' ? '' : 'hidden')}">
|
||||
<span class="detail-label">Helyettesítő tanár:</span>
|
||||
<span class="detail-value">${lesson.teacher.replace('Helyettesítő:', '')}</span>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<span class="detail-label">Terem:</span>
|
||||
@@ -294,7 +218,6 @@
|
||||
|
||||
document.body.appendChild(modal);
|
||||
|
||||
// Modal bezárás
|
||||
const closeModal = () => {
|
||||
modal.classList.remove('show');
|
||||
setTimeout(() => modal.remove(), 300);
|
||||
@@ -305,7 +228,6 @@
|
||||
if (e.target === modal) closeModal();
|
||||
});
|
||||
|
||||
// ESC gomb kezelése
|
||||
const handleEscape = (e) => {
|
||||
if (e.key === 'Escape') {
|
||||
closeModal();
|
||||
@@ -314,15 +236,12 @@
|
||||
};
|
||||
document.addEventListener('keydown', handleEscape);
|
||||
|
||||
// Animáció
|
||||
requestAnimationFrame(() => {
|
||||
modal.classList.add('show');
|
||||
});
|
||||
}
|
||||
|
||||
// Eseménykezelők beállítása
|
||||
function setupEventListeners(data) {
|
||||
// Órakártyák
|
||||
document.querySelectorAll('.lesson-card').forEach(card => {
|
||||
card.addEventListener('click', () => {
|
||||
const lessonData = JSON.parse(card.dataset.lesson);
|
||||
@@ -330,26 +249,12 @@
|
||||
});
|
||||
});
|
||||
|
||||
// Felhasználói menü
|
||||
const userBtn = document.querySelector('.user-dropdown-btn');
|
||||
const userDropdown = document.querySelector('.user-dropdown');
|
||||
|
||||
userBtn?.addEventListener('click', (e) => {
|
||||
e.stopPropagation();
|
||||
userDropdown?.classList.toggle('show');
|
||||
});
|
||||
|
||||
document.addEventListener('click', () => {
|
||||
userDropdown?.classList.remove('show');
|
||||
});
|
||||
|
||||
// Hét navigáció
|
||||
const prevBtn = document.querySelector('.prev-week');
|
||||
const nextBtn = document.querySelector('.next-week');
|
||||
const weekSelect = document.querySelector('.week-select');
|
||||
|
||||
prevBtn?.addEventListener('click', async () => {
|
||||
showLoadingScreen();
|
||||
loadingScreen.show();
|
||||
const kendoCalendar = document.querySelector('#Calendar')?.__kendoWidget;
|
||||
if (kendoCalendar) {
|
||||
kendoCalendar.prev();
|
||||
@@ -359,7 +264,7 @@
|
||||
});
|
||||
|
||||
nextBtn?.addEventListener('click', async () => {
|
||||
showLoadingScreen();
|
||||
loadingScreen.show();
|
||||
const kendoCalendar = document.querySelector('#Calendar')?.__kendoWidget;
|
||||
if (kendoCalendar) {
|
||||
kendoCalendar.next();
|
||||
@@ -369,7 +274,6 @@
|
||||
});
|
||||
|
||||
weekSelect?.addEventListener('change', async function() {
|
||||
showLoadingScreen();
|
||||
const kendoCombo = document.querySelector('#Calendar_tanevHetek')?.__kendoWidget;
|
||||
if (kendoCombo) {
|
||||
kendoCombo.value(this.value);
|
||||
@@ -378,105 +282,18 @@
|
||||
await transformTimetablePage();
|
||||
}
|
||||
});
|
||||
|
||||
// Kijelentkezés időzítő
|
||||
const startTime = parseInt(data.userData.time?.match(/\d+/)?.[0] || "45");
|
||||
let timeLeft = startTime * 60;
|
||||
|
||||
const updateTimer = () => {
|
||||
const minutes = Math.floor(timeLeft / 60);
|
||||
const seconds = timeLeft % 60;
|
||||
const timerEl = document.getElementById('logoutTimer');
|
||||
if (timerEl) {
|
||||
timerEl.textContent = `${minutes}:${seconds.toString().padStart(2, '0')}`;
|
||||
}
|
||||
|
||||
if (timeLeft <= 0) {
|
||||
window.location.href = '/Home/Logout';
|
||||
} else {
|
||||
timeLeft--;
|
||||
}
|
||||
};
|
||||
|
||||
updateTimer();
|
||||
setInterval(updateTimer, 1000);
|
||||
}
|
||||
|
||||
// Oldal transzformáció
|
||||
async function transformTimetablePage() {
|
||||
try {
|
||||
showLoadingScreen();
|
||||
|
||||
const data = await collectTimetableData();
|
||||
if (!data) {
|
||||
hideLoadingScreen();
|
||||
loadingScreen.hide();
|
||||
return;
|
||||
}
|
||||
|
||||
const schoolNameFull = `${data.schoolInfo.id} - ${data.schoolInfo.name}`;
|
||||
const shortenedSchoolName = shortenSchoolName(schoolNameFull);
|
||||
|
||||
document.body.innerHTML = `
|
||||
<div class="kreta-container">
|
||||
<header class="kreta-header">
|
||||
<div class="school-info">
|
||||
<p class="logo-text">
|
||||
<img src="${chrome.runtime.getURL('images/firka_logo.png')}" alt="Firka" class="logo">
|
||||
Firka
|
||||
</p>
|
||||
<div class="school-details" title="${schoolNameFull}">
|
||||
${shortenedSchoolName}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<nav class="kreta-nav">
|
||||
<div class="nav-links">
|
||||
<a href="/Intezmeny/Faliujsag" data-page="dashboard" class="nav-item">
|
||||
<img src="${chrome.runtime.getURL('icons/dashboard-inactive.svg')}" alt="Kezdőlap">
|
||||
Kezdőlap
|
||||
</a>
|
||||
<a href="/TanuloErtekeles/Osztalyzatok" data-page="grades" class="nav-item">
|
||||
<img src="${chrome.runtime.getURL('icons/grades-inactive.svg')}" alt="Jegyek">
|
||||
Jegyek
|
||||
</a>
|
||||
<a href="/Orarend/InformaciokOrarend" data-page="timetable" class="nav-item active">
|
||||
<img src="${chrome.runtime.getURL('icons/timetable-active.svg')}" alt="Órarend">
|
||||
Órarend
|
||||
</a>
|
||||
<a href="/Hianyzas/Hianyzasok" data-page="absences" class="nav-item">
|
||||
<img src="${chrome.runtime.getURL('icons/absences-inactive.svg')}" alt="Mulasztások">
|
||||
Mulasztások
|
||||
</a>
|
||||
<a href="/Tanulo/TanuloHaziFeladat" data-page="other" class="nav-item">
|
||||
<img src="${chrome.runtime.getURL('icons/others.svg')}" alt="Egyéb">
|
||||
Egyéb
|
||||
</a>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="user-profile">
|
||||
<button class="user-dropdown-btn">
|
||||
<div class="user-info">
|
||||
<span class="user-name">${data.userData.name}</span>
|
||||
<span class="nav-logout-timer" id="logoutTimer">${data.userData.time}</span>
|
||||
</div>
|
||||
</button>
|
||||
<div class="user-dropdown">
|
||||
<a href="/Adminisztracio/Profil" data-page="profile" class="dropdown-item">
|
||||
<img src="${chrome.runtime.getURL('icons/profile.svg')}" alt="Profil">
|
||||
Profil
|
||||
</a>
|
||||
<a href="#" class="dropdown-item" id="settingsBtn">
|
||||
<img src="${chrome.runtime.getURL('icons/settings.svg')}" alt="Beállítások">
|
||||
Beállítások
|
||||
</a>
|
||||
<a href="/Home/Logout" data-page="logout" class="dropdown-item">
|
||||
<img src="${chrome.runtime.getURL('icons/logout.svg')}" alt="Kijelentkezés">
|
||||
Kijelentkezés
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
${createTemplate.header()}
|
||||
|
||||
<main class="kreta-main">
|
||||
<div class="week-controls">
|
||||
@@ -504,39 +321,19 @@
|
||||
</div>
|
||||
`;
|
||||
|
||||
// Szükséges fontok hozzáadása
|
||||
const links = [
|
||||
{ rel: 'preconnect', href: 'https://fonts.googleapis.com' },
|
||||
{ rel: 'preconnect', href: 'https://fonts.gstatic.com', crossorigin: true },
|
||||
{ rel: 'stylesheet', href: 'https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap' },
|
||||
{ rel: 'stylesheet', href: 'https://fonts.googleapis.com/icon?family=Material+Icons+Round' }
|
||||
];
|
||||
|
||||
links.forEach(link => {
|
||||
const linkElement = document.createElement('link');
|
||||
Object.entries(link).forEach(([key, value]) => {
|
||||
linkElement[key] = value;
|
||||
});
|
||||
document.head.appendChild(linkElement);
|
||||
});
|
||||
createTemplate.importFonts();
|
||||
setupUserDropdown();
|
||||
setupMobileNavigation();
|
||||
|
||||
setupEventListeners(data);
|
||||
hideLoadingScreen();
|
||||
loadingScreen.hide();
|
||||
|
||||
} catch (error) {
|
||||
console.error('Hiba az oldal átalakítása során:', error);
|
||||
hideLoadingScreen();
|
||||
loadingScreen.hide();
|
||||
}
|
||||
}
|
||||
|
||||
// Beállítások gomb kezelése
|
||||
document.getElementById('settingsBtn')?.addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
const url = chrome.runtime.getURL('settings/index.html');
|
||||
window.open(url, '_blank', 'width=400,height=600');
|
||||
});
|
||||
|
||||
if (window.location.href.includes('/Orarend/')) {
|
||||
transformTimetablePage();
|
||||
}
|
||||
|
||||
25
tools/cookieManager.js
Normal file
25
tools/cookieManager.js
Normal file
@@ -0,0 +1,25 @@
|
||||
const cookieManager = {
|
||||
get(name) {
|
||||
const cookieName = `${name}=`;
|
||||
const decodedCookie = decodeURIComponent(document.cookie);
|
||||
const cookieArray = decodedCookie.split(';');
|
||||
|
||||
for(let i = 0; i < cookieArray.length; i++) {
|
||||
let cookie = cookieArray[i];
|
||||
while (cookie.charAt(0) === ' ') {
|
||||
cookie = cookie.substring(1);
|
||||
}
|
||||
if (cookie.indexOf(cookieName) === 0) {
|
||||
return cookie.substring(cookieName.length, cookie.length);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
set(name, value, days = 365) {
|
||||
const date = new Date();
|
||||
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
|
||||
const expires = `expires=${date.toUTCString()}`;
|
||||
document.cookie = `${name}=${value}; ${expires}; path=/; domain=.e-kreta.hu`;
|
||||
}
|
||||
}
|
||||
135
tools/createTemplate.js
Normal file
135
tools/createTemplate.js
Normal file
@@ -0,0 +1,135 @@
|
||||
const createTemplate = {
|
||||
header() {
|
||||
const data = {
|
||||
schoolInfo: {
|
||||
name: cookieManager.get('schoolName') || 'Iskola',
|
||||
id: cookieManager.get('schoolCode') || ''
|
||||
},
|
||||
userData: {
|
||||
name: cookieManager.get('userName') || 'Felhasználó',
|
||||
time: document.querySelector('.usermenu_timer')?.textContent?.trim() || '45:00',
|
||||
email: cookieManager.get('userEmail') || ''
|
||||
}
|
||||
};
|
||||
|
||||
const schoolNameFull = `${data.schoolInfo.id} - ${data.schoolInfo.name}`;
|
||||
const shortenedSchoolName = helper.shortenSchoolName(schoolNameFull);
|
||||
|
||||
|
||||
|
||||
const element = `<header class="kreta-header">
|
||||
<div class="school-info">
|
||||
<p class="logo-text">
|
||||
<img src="${chrome.runtime.getURL('images/firka_logo.png')}" alt="Firka" class="logo">
|
||||
Firka
|
||||
</p>
|
||||
<div class="school-details" title="${schoolNameFull}">
|
||||
${shortenedSchoolName}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button class="nav-toggle" aria-label="Navigáció megnyitása">
|
||||
<svg viewBox="0 0 24 24">
|
||||
<path d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z"/>
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<nav class="kreta-nav">
|
||||
<div class="nav-links">
|
||||
<a href="/Intezmeny/Faliujsag" data-page="dashboard" class="nav-item ${( location.pathname == '/Intezmeny/Faliujsag' ? 'active' : '')}">
|
||||
<img src="${chrome.runtime.getURL('icons/dashboard-' + ( location.pathname == '/Intezmeny/Faliujsag' ? 'active' : 'inactive') + '.svg')}" alt="Kezdőlap">
|
||||
Kezdőlap
|
||||
</a>
|
||||
<a href="/TanuloErtekeles/Osztalyzatok" data-page="grades" class="nav-item ${( location.pathname == '/TanuloErtekeles/Osztalyzatok' ? 'active' : '')}">
|
||||
<img src="${chrome.runtime.getURL('icons/grades-' + ( location.pathname == '/TanuloErtekeles/Osztalyzatok' ? 'active' : 'inactive') + '.svg')}" alt="Jegyek">
|
||||
Jegyek
|
||||
</a>
|
||||
<a href="/Orarend/InformaciokOrarend" data-page="timetable" class="nav-item ${( location.pathname == '/Orarend/InformaciokOrarend' ? 'active' : '')}">
|
||||
<img src="${chrome.runtime.getURL('icons/timetable-' + ( location.pathname == '/Orarend/InformaciokOrarend' ? 'active' : 'inactive') + '.svg')}" alt="Órarend">
|
||||
Órarend
|
||||
</a>
|
||||
<a href="/Hianyzas/Hianyzasok" data-page="absences" class="nav-item ${( location.pathname == '/Hianyzas/Hianyzasok' ? 'active' : '')}">
|
||||
<img src="${chrome.runtime.getURL('icons/absences-' + ( location.pathname == '/Hianyzas/Hianyzasok' ? 'active' : 'inactive') + '.svg')}" alt="Mulasztások">
|
||||
Mulasztások
|
||||
</a>
|
||||
<a href="/Tanulo/TanuloHaziFeladat" data-page="other" class="nav-item ${( location.pathname == '/Tanulo/TanuloHaziFeladat' ? 'active' : '')}">
|
||||
<img src="${chrome.runtime.getURL('icons/others.svg')}" alt="Egyéb">
|
||||
Egyéb
|
||||
</a>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="user-profile">
|
||||
<button class="user-dropdown-btn">
|
||||
<div class="user-info">
|
||||
<span class="user-name">${data.userData.name}</span>
|
||||
<span class="nav-logout-timer" id="logoutTimer">${data.userData.time}</span>
|
||||
</div>
|
||||
</button>
|
||||
<div class="user-dropdown">
|
||||
<a href="/Adminisztracio/Profil" data-page="profile" class="dropdown-item">
|
||||
<img src="${chrome.runtime.getURL('icons/profile.svg')}" alt="Profil">
|
||||
Profil
|
||||
</a>
|
||||
<a href="#" class="dropdown-item" id="settingsBtn">
|
||||
<img src="${chrome.runtime.getURL('icons/settings.svg')}" alt="Beállítások">
|
||||
Beállítások
|
||||
</a>
|
||||
<a href="/Home/Logout" data-page="logout" class="dropdown-item">
|
||||
<img src="${chrome.runtime.getURL('icons/logout.svg')}" alt="Kijelentkezés">
|
||||
Kijelentkezés
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</header>`
|
||||
|
||||
const startTime = parseInt(data.userData.time?.match(/\d+/)?.[0] || "45");
|
||||
let timeLeft = startTime * 60;
|
||||
|
||||
const updateTimer = () => {
|
||||
const minutes = Math.floor(timeLeft / 60);
|
||||
const seconds = timeLeft % 60;
|
||||
const timerEl = document.getElementById('logoutTimer');
|
||||
if (timerEl) {
|
||||
timerEl.textContent = `${minutes}:${seconds.toString().padStart(2, '0')}`;
|
||||
}
|
||||
|
||||
if (timeLeft <= 0) {
|
||||
window.location.href = '/Home/Logout';
|
||||
} else {
|
||||
timeLeft--;
|
||||
}
|
||||
};
|
||||
|
||||
setInterval(updateTimer, 1000);
|
||||
|
||||
return element;
|
||||
},
|
||||
|
||||
importFonts() {
|
||||
const links = [
|
||||
{ rel: 'preconnect', href: 'https://fonts.googleapis.com' },
|
||||
{ rel: 'preconnect', href: 'https://fonts.gstatic.com', crossorigin: true },
|
||||
{ rel: 'stylesheet', href: 'https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap' },
|
||||
{ rel: 'stylesheet', href: 'https://fonts.googleapis.com/icon?family=Material+Icons+Round' }
|
||||
];
|
||||
|
||||
links.forEach(link => {
|
||||
const linkElement = document.createElement('link');
|
||||
Object.entries(link).forEach(([key, value]) => {
|
||||
linkElement[key] = value;
|
||||
});
|
||||
document.head.appendChild(linkElement);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", async () => {
|
||||
await helper.waitForElement('#settingsBtn');
|
||||
document.querySelector('#settingsBtn').addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
const url = chrome.runtime.getURL('settings/index.html');
|
||||
window.open(url, '_blank', 'width=400,height=600');
|
||||
});
|
||||
});
|
||||
40
tools/helper.js
Normal file
40
tools/helper.js
Normal file
@@ -0,0 +1,40 @@
|
||||
const helper = {
|
||||
shortenSchoolName(name, maxLength = 50) {
|
||||
if (!name) return '';
|
||||
if (name.length <= maxLength) return name;
|
||||
|
||||
const parts = name.split(' - ');
|
||||
if (parts.length === 2) {
|
||||
const [code, fullName] = parts;
|
||||
if (fullName.length > maxLength - code.length - 3) {
|
||||
return `${code} - ${fullName.substring(0, maxLength - code.length - 6)}...`;
|
||||
}
|
||||
}
|
||||
return name.substring(0, maxLength - 3) + '...';
|
||||
},
|
||||
|
||||
async waitForElement(selector) {
|
||||
return new Promise(resolve => {
|
||||
if (document.querySelector(selector)) {
|
||||
return resolve(document.querySelector(selector));
|
||||
}
|
||||
|
||||
const observer = new MutationObserver(mutations => {
|
||||
if (document.querySelector(selector)) {
|
||||
observer.disconnect();
|
||||
resolve(document.querySelector(selector));
|
||||
}
|
||||
});
|
||||
|
||||
observer.observe(document.body, {
|
||||
childList: true,
|
||||
subtree: true
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
convertTimeToMinutes(timeStr) {
|
||||
const [hours, minutes] = timeStr.split(':').map(Number);
|
||||
return hours * 60 + minutes;
|
||||
}
|
||||
}
|
||||
59
tools/loadingScreen.css
Normal file
59
tools/loadingScreen.css
Normal file
@@ -0,0 +1,59 @@
|
||||
.modalBckgroundMain {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
body:not(.loaded) {
|
||||
opacity: 0 !important;
|
||||
visibility: hidden !important;
|
||||
height: 100vh !important;
|
||||
overflow: hidden !important;
|
||||
}
|
||||
|
||||
.loading-screen {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
background-color: var(--background);
|
||||
z-index: 9999;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: opacity 0.3s ease;
|
||||
}
|
||||
|
||||
.loading-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.loading-logo {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
border-radius: 16px;
|
||||
}
|
||||
|
||||
.loading-text {
|
||||
color: var(--text-primary);
|
||||
text-align: center;
|
||||
font-family: Montserrat;
|
||||
font-size: 20px;
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
.loading-text2 {
|
||||
align-self: stretch;
|
||||
color: var(--text-secondary);
|
||||
text-align: center;
|
||||
font-family: Figtree;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
line-height: 130%;
|
||||
}
|
||||
47
tools/loadingScreen.js
Normal file
47
tools/loadingScreen.js
Normal file
@@ -0,0 +1,47 @@
|
||||
const loadingScreen = {
|
||||
show() {
|
||||
document.body.classList.remove('loaded');
|
||||
const existingLoadingScreen = document.querySelector('.loading-screen');
|
||||
if (existingLoadingScreen) return;
|
||||
|
||||
const loadingScreen = document.createElement('div');
|
||||
loadingScreen.className = 'loading-screen';
|
||||
loadingScreen.innerHTML = `
|
||||
<div class="loading-content">
|
||||
<img src="${chrome.runtime.getURL('images/loading.gif')}" alt="Firka" class="loading-logo">
|
||||
<div class="loading-text">Betöltés alatt...</div>
|
||||
<div class="loading-text2">Kis türelmet!</div>
|
||||
</div>
|
||||
`;
|
||||
document.body.appendChild(loadingScreen);
|
||||
document.body.classList.add('loaded');
|
||||
},
|
||||
|
||||
hide() {
|
||||
document.body.classList.add('loaded');
|
||||
const loadingScreen = document.querySelector('.loading-screen');
|
||||
if (loadingScreen) {
|
||||
loadingScreen.style.opacity = '0';
|
||||
loadingScreen.addEventListener('transitionend', () => {
|
||||
loadingScreen.remove();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener('DOMContentLoaded', () => {
|
||||
const manifest = chrome.runtime.getManifest();
|
||||
const urls = [];
|
||||
|
||||
if (manifest.content_scripts) {
|
||||
manifest.content_scripts.forEach(script => {
|
||||
if (script.matches) {
|
||||
urls.push(...script.matches);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (urls.some(url => url.includes(location.pathname))) {
|
||||
loadingScreen.show();
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user