1.1.0
9
.gitignore
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
|
||||
|
||||
*.zip
|
||||
META-INF/mozilla.rsa
|
||||
META-INF/cose.manifest
|
||||
META-INF/cose.sig
|
||||
META-INF/manifest.mf
|
||||
META-INF/mozilla.sf
|
||||
dashboard/KRÉTA Iskolai Alaprendszer.html
|
||||
9
.idea/Firkaextension.iml
generated
Normal file
@@ -0,0 +1,9 @@
|
||||
<?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
Normal file
@@ -0,0 +1,6 @@
|
||||
<?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
Normal file
@@ -0,0 +1,8 @@
|
||||
<?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
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
45
.idea/workspace.xml
generated
Normal file
@@ -0,0 +1,45 @@
|
||||
<?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>
|
||||
2
LICENSE
@@ -1,4 +1,4 @@
|
||||
GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
Version 3, 19 November 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
|
||||
95
README.md
Normal file
@@ -0,0 +1,95 @@
|
||||
<p align="center">
|
||||
<img src="https://i.imgur.com/WugwlzI.png" width="150">
|
||||
<h1 align="center">Firxa</h1>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
Modern, testre szabható felhasználói felület az e-KRÉTA rendszerhez
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/Zan1456/filc-extension/releases">
|
||||
<img src="https://img.shields.io/github/downloads-pre/Zan1456/filc-extension/total?&logo=github&label=Downloads" alt="Downloads">
|
||||
</a>
|
||||
<a href="https://dc.refilc.hu">
|
||||
<img src="https://img.shields.io/discord/1111649116020285532?logo=discord&label=Discord" alt="Discord">
|
||||
</a>
|
||||
<a href="https://github.com/Zan1456/filc-extension/blob/main/LICENSE">
|
||||
<img src="https://img.shields.io/github/license/Zan1456/filc-extension?color=blue" alt="License">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
## 📱 Funkciók
|
||||
|
||||
- **Modern Dizájn**: Teljesen újratervezett, modern felhasználói felület
|
||||
- **Személyre Szabható Témák**: Világos és sötét módok, kék és zöld színsémákkal
|
||||
- **Továbbfejlesztett Felületek**:
|
||||
- Átdolgozott bejelentkezési képernyő
|
||||
- Átláthatóbb jegynapló
|
||||
- Modernizált órarend
|
||||
- Fejlett hiányzás kezelés
|
||||
- Egyszerűsített szerepkör választó
|
||||
- Új kezdőlap elrendezés
|
||||
- Továbbfejlesztett profilkezelő
|
||||
|
||||
## 🚀 Telepítés
|
||||
|
||||
1. Töltsd le a legfrissebb verziót a [Releases](https://github.com/Zan1456/filc-extension/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
|
||||
|
||||
## ⚙️ Beállítások
|
||||
|
||||
A bővítmény beállításait a böngésző eszköztárán található Filx ikonra kattintva érheted el. Itt módosíthatod:
|
||||
|
||||
- A felület színsémáját (Világos/Sötét)
|
||||
- Az fő színeket (Kék/Zöld)
|
||||
|
||||
## 💡 Támogatott Oldalak
|
||||
|
||||
A bővítmény jelenleg az alábbi e-KRÉTA oldalakat támogatja:
|
||||
|
||||
- Bejelentkezési oldal
|
||||
- Kijelentkezési oldal
|
||||
- Szerepkör választó
|
||||
- Elfelejtett jelszó (részlegesen)
|
||||
- Kezdőlap/Faliújság
|
||||
- Jegyek/Értékelések
|
||||
- Órarend
|
||||
- Hiányzások
|
||||
- Profil (csak dizájn)
|
||||
|
||||
## 👥 Csapat
|
||||
|
||||
- **[Zan1456](https://github.com/Zan1456)** - Vezető Fejlesztő
|
||||
- **[BalazsManus](https://github.com/BalazsManus)** - Fejlesztő
|
||||
- **[Xou](https://github.com/Xou)** - Designer
|
||||
|
||||
## 🤝 Közreműködés
|
||||
|
||||
Örömmel fogadunk minden fejlesztési javaslatot és hibajelentést! Ha szeretnél hozzájárulni a projekthez:
|
||||
|
||||
1. Fork-old a repository-t
|
||||
2. Hozz létre egy új branch-et a fejlesztésednek
|
||||
3. Commit-old a változtatásaidat
|
||||
4. Push-old a branch-et
|
||||
5. Nyiss egy Pull Request-et
|
||||
|
||||
## 📝 Licensz
|
||||
|
||||
A projekt [GNU General Public License v3.0](LICENSE) alatt jelent meg. További információért lásd a LICENSE fájlt.
|
||||
|
||||
## 💬 Kapcsolat
|
||||
|
||||
- Discord: [dc.refilc.hu](https://dc.refilc.hu)
|
||||
- GitHub: [github.com/refilc](https://github.com/refilc)
|
||||
|
||||
---
|
||||
|
||||
<p align="center">
|
||||
Készült ❤️-vel diákoktól diákoknak
|
||||
</p>
|
||||
520
absences/absences.css
Normal file
@@ -0,0 +1,520 @@
|
||||
* {
|
||||
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", serif !important;
|
||||
min-height: 100vh;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
body {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
.kreta-container {
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.kreta-header {
|
||||
padding: clamp(1rem, 3vw, 2rem);
|
||||
display: grid;
|
||||
grid-template-columns: minmax(300px, 400px) 1fr minmax(200px, 300px);
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
@media (max-width: 1200px) {
|
||||
.kreta-header {
|
||||
grid-template-columns: minmax(250px, 350px) 1fr minmax(180px, 250px);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.kreta-header {
|
||||
grid-template-columns: 1fr auto;
|
||||
grid-template-areas:
|
||||
"school user"
|
||||
"nav nav";
|
||||
padding: 1rem;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.school-info {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.school-info {
|
||||
grid-area: school;
|
||||
max-width: none;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.logo-text {
|
||||
color: var(--text-primary);
|
||||
font-size: 24px;
|
||||
font-weight: 600;
|
||||
margin: 0 0 0.5rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.logo-text {
|
||||
margin: 0;
|
||||
font-size: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.logo {
|
||||
width: 24px;
|
||||
border-radius: 8px;
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
|
||||
.school-details {
|
||||
color: var(--text-secondary);
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.school-details span {
|
||||
display: block;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
max-width: 300px;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.school-details span {
|
||||
max-width: 200px;
|
||||
}
|
||||
|
||||
.school-details {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.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;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.user-profile {
|
||||
grid-area: user;
|
||||
}
|
||||
}
|
||||
|
||||
.user-dropdown-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
padding: 0.5rem;
|
||||
border-radius: 8px;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.user-dropdown-btn:hover {
|
||||
background: var(--card-card);
|
||||
}
|
||||
|
||||
.user-info {
|
||||
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%;
|
||||
right: 0;
|
||||
margin-top: 0.5rem;
|
||||
background: var(--card-card);
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
|
||||
width: 200px;
|
||||
display: none;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.user-dropdown.show {
|
||||
display: block;
|
||||
animation: dropdownShow 0.2s ease;
|
||||
}
|
||||
|
||||
.dropdown-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
padding: 0.75rem 1rem;
|
||||
color: var(--text-primary);
|
||||
text-decoration: none;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.dropdown-item:hover {
|
||||
background: var(--button-secondaryFill);
|
||||
}
|
||||
|
||||
|
||||
.kreta-main {
|
||||
flex: 1;
|
||||
padding: clamp(1rem, 3vw, 2rem);
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
||||
.filter-card {
|
||||
background: var(--card-card);
|
||||
border-radius: 24px;
|
||||
padding: 20px;
|
||||
margin-bottom: 24px;
|
||||
box-shadow: 0px 1px var(--shadow-blur) 0px var(--accent-shadow);
|
||||
}
|
||||
|
||||
.filter-header {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.filter-header h2 {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: var(--text-primary);
|
||||
background-color: var(--card-card);
|
||||
}
|
||||
|
||||
.filter-content {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.filter-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.filter-group label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
color: var(--text-secondary);
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.filter-input {
|
||||
padding: 10px;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
background: var(--button-secondaryFill);
|
||||
color: var(--text-primary);
|
||||
font-family: inherit;
|
||||
font-size: 14px;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.filter-input:focus {
|
||||
outline: none;
|
||||
box-shadow: 0 0 0 2px var(--accent-accent);
|
||||
}
|
||||
|
||||
|
||||
.absences-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.absence-group {
|
||||
background: var(--card-card);
|
||||
border-radius: 24px;
|
||||
overflow: hidden;
|
||||
animation: fadeIn 0.3s ease;
|
||||
box-shadow: 0px 1px var(--shadow-blur) 0px var(--accent-shadow);
|
||||
}
|
||||
|
||||
.absence-date {
|
||||
padding: 16px;
|
||||
color: var(--text-primary);
|
||||
font-weight: 600;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.absence-count {
|
||||
margin-left: auto;
|
||||
background: var(--accent-accent);
|
||||
color: var(--button-secondaryFill);
|
||||
padding: 4px 8px;
|
||||
border-radius: 12px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.absence-list {
|
||||
padding: 16px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.absence-item {
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr auto;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
padding: 12px;
|
||||
background: var(--accent-15);
|
||||
border-radius: 12px;
|
||||
transition: transform 0.2s ease;
|
||||
}
|
||||
|
||||
.absence-item:hover {
|
||||
transform: translateX(4px);
|
||||
}
|
||||
|
||||
.absence-time {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
color: var(--text-secondary);
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.absence-details {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.absence-subject {
|
||||
font-weight: 600;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.absence-topic {
|
||||
color: var(--text-secondary);
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.absence-status {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.absence-status.justified {
|
||||
color: var(--grades-4);
|
||||
}
|
||||
|
||||
.absence-status.unjustified {
|
||||
color: var(--grades-1);
|
||||
}
|
||||
|
||||
.absence-status.pending {
|
||||
color: var(--grades-3);
|
||||
}
|
||||
|
||||
|
||||
.loading-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: var(--background);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
.loading-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
padding: 2rem;
|
||||
border-radius: 24px;
|
||||
}
|
||||
|
||||
.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%;
|
||||
}
|
||||
|
||||
.loading-logo {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
margin-bottom: 1rem;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-10px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes dropdownShow {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-10px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: clamp(4px, 1vw, 8px);
|
||||
height: clamp(4px, 1vw, 8px);
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background: var(--background);
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: var(--text-secondary);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: var(--text-primary);
|
||||
}
|
||||
462
absences/absences.js
Normal file
@@ -0,0 +1,462 @@
|
||||
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 new Promise(resolve => setTimeout(resolve, 1000));
|
||||
|
||||
const basicData = {
|
||||
schoolInfo: {
|
||||
name: getCookie('schoolName') || 'Iskola',
|
||||
id: getCookie('schoolCode') || ''
|
||||
},
|
||||
userData: {
|
||||
name: getCookie('userName') || 'Felhasználó',
|
||||
time: document.querySelector('.usermenu_timer')?.textContent?.trim() || '45:00'
|
||||
}
|
||||
};
|
||||
|
||||
const absences = [];
|
||||
const rows = document.querySelectorAll('#HianyzasGrid .k-grid-content tr');
|
||||
rows.forEach(row => {
|
||||
const cells = row.querySelectorAll('td');
|
||||
if (cells.length >= 9) {
|
||||
absences.push({
|
||||
date: cells[1]?.textContent?.trim() || '',
|
||||
lesson: cells[2]?.textContent?.trim() || '',
|
||||
subject: cells[3]?.textContent?.trim() || '',
|
||||
topic: cells[4]?.textContent?.trim() || '',
|
||||
type: cells[5]?.textContent?.trim() || '',
|
||||
justified: cells[6]?.textContent?.trim() === 'Igen',
|
||||
justificationStatus: cells[6]?.textContent?.trim() === 'Igen' ? 'justified' :
|
||||
cells[6]?.textContent?.trim() === 'Nem' ? 'unjustified' : 'pending',
|
||||
purposeful: cells[7]?.textContent?.trim() || '',
|
||||
justificationType: cells[8]?.textContent?.trim() || ''
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
const groupedAbsences = {};
|
||||
absences.forEach(absence => {
|
||||
if (!groupedAbsences[absence.date]) {
|
||||
groupedAbsences[absence.date] = [];
|
||||
}
|
||||
groupedAbsences[absence.date].push(absence);
|
||||
});
|
||||
|
||||
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>
|
||||
|
||||
<main class="kreta-main">
|
||||
<div class="filter-card">
|
||||
<div class="filter-header">
|
||||
<h2>Szűrés</h2>
|
||||
</div>
|
||||
<div class="filter-content">
|
||||
<div class="filter-group">
|
||||
<label>
|
||||
<span class="material-icons-round">date_range</span>
|
||||
Dátum
|
||||
</label>
|
||||
<input type="date" id="dateFilter" class="filter-input" disabled>
|
||||
</div>
|
||||
<div class="filter-group">
|
||||
<label>
|
||||
<span class="material-icons-round">school</span>
|
||||
Tantárgy
|
||||
</label>
|
||||
<select id="subjectFilter" class="filter-input">
|
||||
<option value="">Minden tantárgy</option>
|
||||
${[...new Set(absences.map(a => a.subject))].sort().map(subject =>
|
||||
`<option value="${subject}">${subject}</option>`
|
||||
).join('')}
|
||||
</select>
|
||||
</div>
|
||||
<div class="filter-group">
|
||||
<label>
|
||||
<span class="material-icons-round">check_circle</span>
|
||||
Igazolás
|
||||
</label>
|
||||
<select id="justificationFilter" class="filter-input">
|
||||
<option value="">Mindegy</option>
|
||||
<option value="justified">Igazolt</option>
|
||||
<option value="unjustified">Igazolatlan</option>
|
||||
<option value="pending">Igazolásra vár</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="absences-container">
|
||||
${Object.entries(groupedAbsences).map(([date, dayAbsences]) => `
|
||||
<div class="absence-group" data-date="${date}">
|
||||
<div class="absence-date">
|
||||
<span class="material-icons-round">event</span>
|
||||
${date}
|
||||
<span class="absence-count">${dayAbsences.length} óra</span>
|
||||
</div>
|
||||
<div class="absence-list">
|
||||
${dayAbsences.map(absence => `
|
||||
<div class="absence-item"
|
||||
data-subject="${absence.subject}"
|
||||
data-justified="${absence.justified}">
|
||||
<div class="absence-time">
|
||||
<span class="material-icons-round">schedule</span>
|
||||
${absence.lesson}. óra
|
||||
</div>
|
||||
<div class="absence-details">
|
||||
<div class="absence-subject">${absence.subject}</div>
|
||||
<div class="absence-topic">${absence.topic}</div>
|
||||
</div>
|
||||
<div class="absence-status ${absence.justificationStatus}">
|
||||
${absence.justificationStatus === 'justified' ?
|
||||
`Igazolt <span class="material-icons-round">check_circle</span>` :
|
||||
absence.justificationStatus === 'unjustified' ?
|
||||
`Igazolatlan <span class="material-icons-round">cancel</span>` :
|
||||
`Igazolásra vár <span class="material-icons-round">pending</span>`}
|
||||
</div>
|
||||
</div>
|
||||
`).join('')}
|
||||
</div>
|
||||
</div>
|
||||
`).join('')}
|
||||
</div>
|
||||
</main>
|
||||
</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);
|
||||
});
|
||||
|
||||
setupEventListeners();
|
||||
setupFilters();
|
||||
|
||||
hideLoadingScreen();
|
||||
}
|
||||
|
||||
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 setupFilters() {
|
||||
try {
|
||||
const filters = {
|
||||
dateFilter: document.getElementById('dateFilter'),
|
||||
subject: document.getElementById('subjectFilter'),
|
||||
justified: document.getElementById('justificationFilter')
|
||||
};
|
||||
|
||||
|
||||
if (!filters.dateFilter || !filters.subject || !filters.justified) {
|
||||
console.warn('Some filter elements were not found in the DOM');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (filters.dateFilter) {
|
||||
filters.dateFilter.disabled = true;
|
||||
}
|
||||
|
||||
const filterAbsences = () => {
|
||||
try {
|
||||
|
||||
const dateFilterValue = filters.dateFilter.value;
|
||||
const subject = filters.subject.value;
|
||||
const justified = filters.justified.value;
|
||||
|
||||
|
||||
const selectedDate = dateFilterValue ? new Date(dateFilterValue) : null;
|
||||
|
||||
document.querySelectorAll('.absence-group').forEach(group => {
|
||||
const dateStr = group.dataset.date;
|
||||
const dateParts = dateStr.split('.');
|
||||
|
||||
|
||||
if (dateParts.length < 3) {
|
||||
console.error(`Invalid date format: ${dateStr}`);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
const parsedDay = parseInt(dateParts[0].trim(), 10);
|
||||
const parsedMonth = parseInt(dateParts[1].trim(), 10) - 1;
|
||||
const parsedYear = parseInt(dateParts[2].trim(), 10);
|
||||
|
||||
|
||||
if (isNaN(parsedDay) || isNaN(parsedMonth) || isNaN(parsedYear)) {
|
||||
console.error(`Invalid date components: ${dateStr}`);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
const groupDate = new Date(parsedYear, parsedMonth, parsedDay);
|
||||
|
||||
let showGroup = true;
|
||||
|
||||
|
||||
// if (selectedDate && 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;
|
||||
|
||||
absenceItems.forEach(item => {
|
||||
let showItem = true;
|
||||
if (subject && item.dataset.subject !== subject) showItem = false;
|
||||
|
||||
if (justified) {
|
||||
const statusElement = item.querySelector('.absence-status');
|
||||
const hasStatus = statusElement.classList.contains(justified);
|
||||
if (!hasStatus) showItem = false;
|
||||
}
|
||||
|
||||
item.style.display = showItem ? '' : 'none';
|
||||
if (showItem) visibleItems++;
|
||||
});
|
||||
|
||||
group.style.display = (showGroup && visibleItems > 0) ? '' : 'none';
|
||||
});
|
||||
} catch (err) {
|
||||
|
||||
console.error('Error during filtering absences:', err);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// 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
|
||||
filter.addEventListener('change', filterAbsences);
|
||||
}
|
||||
} catch (err) {
|
||||
if (err.message && err.message.includes('Extension context invalidated')) {
|
||||
console.warn('Extension context invalidated during event listener setup');
|
||||
} else {
|
||||
console.error('Error setting up filter event listener:', err);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
filterAbsences();
|
||||
} catch (err) {
|
||||
|
||||
if (err.message && err.message.includes('Extension context invalidated')) {
|
||||
console.warn('Extension context invalidated during filter setup');
|
||||
} else {
|
||||
console.error('Error setting up filters:', err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (window.location.href.includes('/Hianyzas/Hianyzasok')) {
|
||||
transformAbsencesPage().catch(error => {
|
||||
console.error('Hiba történt az oldal átalakítása során:', error);
|
||||
});
|
||||
}
|
||||
238
dashboard/dashboard.css
Normal file
@@ -0,0 +1,238 @@
|
||||
* {
|
||||
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", serif !important;
|
||||
min-height: 100vh;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.kreta-container {
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
|
||||
.kreta-main {
|
||||
flex: 1;
|
||||
padding: clamp(1rem, 3vw, 2rem);
|
||||
max-width: 1400px;
|
||||
margin: 0 auto;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.grid-container {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
|
||||
.card {
|
||||
background: var(--card-card);
|
||||
padding: 20px;
|
||||
padding-top: 5px !important;
|
||||
border-radius: 24px;
|
||||
overflow: hidden;
|
||||
animation: fadeIn 0.5s ease forwards;
|
||||
box-shadow: 0px 1px var(--shadow-blur) 0px var(--accent-shadow);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.card h2 {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: var(--text-primary);
|
||||
background-color: var(--card-card);
|
||||
}
|
||||
|
||||
.card:last-child {
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
|
||||
|
||||
.grade-item, .absence-item, .note-item, .exam-item, .news-item {
|
||||
border-radius: 6px;
|
||||
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
||||
border: 1px solid var(--card-card);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-bottom: 12px;
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
|
||||
.grade {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 16px;
|
||||
font-weight: 700;
|
||||
margin-right: 1rem;
|
||||
color: var(--text-primary);
|
||||
font-size: 22px;
|
||||
}
|
||||
.subject-name, .absence-type, .note-title, .exam-subject {
|
||||
color: var(--text-primary);
|
||||
font-weight: 600;
|
||||
font-size: 16px;
|
||||
}
|
||||
.grade-type, .absence-date, .note-date, .exam-date {
|
||||
color: var(--text-secondary);
|
||||
font-weight: 500;
|
||||
font-size: 14px;
|
||||
}
|
||||
.more-link {
|
||||
margin-top: auto;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
color: var(--accent-accent);
|
||||
text-decoration: none;
|
||||
font-weight: 500;
|
||||
padding-top: 16px;
|
||||
transition: gap 0.2s ease;
|
||||
font-size: clamp(0.875rem, 1.5vw, 1rem);
|
||||
}
|
||||
@media (hover: hover) {
|
||||
.more-link:hover {
|
||||
color: var(--accent-secondary);
|
||||
gap: 0.75rem;
|
||||
}
|
||||
}
|
||||
.more-link i {
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
.grade-1 {color: var(--grades-1); background-color: var(--grades-background-1);}
|
||||
.grade-2 {color: var(--grades-2); background-color: var(--grades-background-2);}
|
||||
.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);}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-10px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
.user-profile {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.user-dropdown-btn {
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
padding: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.user-dropdown {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
right: 0;
|
||||
background: var(--card-card);
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 12px var(--accent-shadow);
|
||||
min-width: 200px;
|
||||
display: none;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.user-dropdown.active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.dropdown-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 12px 16px;
|
||||
color: var(--text-primary);
|
||||
text-decoration: none;
|
||||
transition: background-color 0.2s ease;
|
||||
}
|
||||
|
||||
.dropdown-item:hover {
|
||||
background-color: var(--accent-15);
|
||||
}
|
||||
|
||||
.dropdown-item svg {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
.subject-name, .absence-type, .note-title, .exam-subject {
|
||||
color: var(--text-primary);
|
||||
font-weight: 600;
|
||||
font-size: 16px;
|
||||
}
|
||||
.grade-type, .absence-date, .note-date, .exam-date {
|
||||
color: var(--text-secondary);
|
||||
font-weight: 500;
|
||||
font-size: 14px;
|
||||
}
|
||||
.more-link {
|
||||
margin-top: auto;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
color: var(--accent-accent);
|
||||
text-decoration: none;
|
||||
font-weight: 500;
|
||||
padding-top: 16px;
|
||||
transition: gap 0.2s ease;
|
||||
font-size: clamp(0.875rem, 1.5vw, 1rem);
|
||||
}
|
||||
@media (hover: hover) {
|
||||
.more-link:hover {
|
||||
color: var(--accent-secondary);
|
||||
gap: 0.75rem;
|
||||
}
|
||||
}
|
||||
.more-link i {
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
.grade-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.grade-details {
|
||||
flex: 1;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.grade-date, .exam-date {
|
||||
color: var(--text-secondary);
|
||||
font-size: 14px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.exam-info {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
margin-top: 4px;
|
||||
color: var(--text-secondary);
|
||||
font-size: 14px;
|
||||
}
|
||||
446
dashboard/dashboard.js
Normal file
@@ -0,0 +1,446 @@
|
||||
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() || '';
|
||||
},
|
||||
|
||||
parseDate(dateStr) {
|
||||
return dateStr?.trim() || '';
|
||||
},
|
||||
|
||||
formatHungarianDate(dateStr) {
|
||||
if (!dateStr) return '';
|
||||
|
||||
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 = [
|
||||
'január', 'február', 'március', 'április', 'május', 'június',
|
||||
'július', 'augusztus', 'szeptember', 'október', 'november', 'december'
|
||||
];
|
||||
|
||||
|
||||
return `${hungarianMonths[month - 1]} ${day}.`;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class DashboardDataExtractor {
|
||||
constructor() {
|
||||
this.data = {
|
||||
grades: [],
|
||||
absences: [],
|
||||
notes: [],
|
||||
upcomingExams: [],
|
||||
news: []
|
||||
};
|
||||
}
|
||||
|
||||
extractGrades() {
|
||||
const gradeRows = document.querySelectorAll('#legutobbiErtekelesek tr:not(:first-child)');
|
||||
|
||||
this.data.grades = Array.from(gradeRows).map(row => {
|
||||
const gradeValue = row.querySelector('span[style*="font-size: 200%"]')?.textContent;
|
||||
const gradeInfo = row.querySelector('span[style*="float: right"]')?.textContent;
|
||||
|
||||
if (!gradeValue || !gradeInfo) return null;
|
||||
|
||||
const [fullSubject, date] = gradeInfo.split('\n').map(str => str.trim());
|
||||
const { subject, type } = this.parseSubjectInfo(fullSubject);
|
||||
|
||||
return {
|
||||
value: utils.formatGradeValue(gradeValue),
|
||||
subject,
|
||||
date: utils.parseDate(date),
|
||||
type: type || 'Értékelés'
|
||||
};
|
||||
}).filter(Boolean);
|
||||
}
|
||||
|
||||
parseSubjectInfo(fullSubject) {
|
||||
const months = ['január', 'február', 'március', 'április', 'május', 'június',
|
||||
'július', 'augusztus', 'szeptember', 'október', 'november', 'december'];
|
||||
const monthPattern = new RegExp(months.join('|'), 'i');
|
||||
const monthMatch = fullSubject.match(monthPattern);
|
||||
|
||||
if (!monthMatch) return { subject: fullSubject, type: '' };
|
||||
|
||||
const monthIndex = fullSubject.lastIndexOf(monthMatch[0]);
|
||||
return {
|
||||
subject: fullSubject.substring(0, monthIndex).trim(),
|
||||
type: fullSubject.substring(monthIndex).trim()
|
||||
};
|
||||
}
|
||||
|
||||
extractAbsences() {
|
||||
const absenceRows = document.querySelectorAll('#legutobbiMulasztasok tr:not(:first-child)');
|
||||
|
||||
this.data.absences = Array.from(absenceRows).map(row => {
|
||||
const spans = row.querySelectorAll('span');
|
||||
if (spans.length < 4) return null;
|
||||
|
||||
return {
|
||||
date: spans[0]?.textContent?.trim() || '',
|
||||
day: spans[2]?.textContent?.trim() || '',
|
||||
type: spans[1]?.textContent?.trim() || '',
|
||||
count: spans[3]?.textContent?.trim() || ''
|
||||
};
|
||||
}).filter(Boolean);
|
||||
}
|
||||
|
||||
extractNotes() {
|
||||
const noteRows = document.querySelectorAll('#legutobbiFeljegyzesek tr:not(:first-child)');
|
||||
|
||||
this.data.notes = Array.from(noteRows).map(row => {
|
||||
const spans = row.querySelectorAll('span');
|
||||
if (spans.length < 3) return null;
|
||||
|
||||
return {
|
||||
title: spans[0]?.textContent?.trim() || '',
|
||||
author: spans[1]?.textContent?.trim() || '',
|
||||
date: spans[2]?.textContent?.trim() || ''
|
||||
};
|
||||
}).filter(Boolean);
|
||||
}
|
||||
|
||||
extractExams() {
|
||||
const examRows = document.querySelectorAll('#legutobbiBejelentettSzamonkeres tr:not(:first-child)');
|
||||
|
||||
this.data.upcomingExams = Array.from(examRows).map(row => {
|
||||
const spans = row.querySelectorAll('span');
|
||||
if (spans.length < 4) return null;
|
||||
|
||||
return {
|
||||
date: spans[0]?.textContent?.trim() || '',
|
||||
subject: spans[1]?.textContent?.trim() || '',
|
||||
day: spans[2]?.textContent?.trim() || '',
|
||||
type: spans[3]?.textContent?.trim() || ''
|
||||
};
|
||||
}).filter(Boolean);
|
||||
}
|
||||
|
||||
extractNews() {
|
||||
const newsContainer = document.querySelector('.faliujsag-lista, #faliujsagLista');
|
||||
if (!newsContainer) return;
|
||||
|
||||
const newsItems = newsContainer.querySelectorAll('.nb-item, .news-item');
|
||||
|
||||
this.data.news = Array.from(newsItems).map(item => {
|
||||
const titleElement = item.querySelector('.subject h4, .news-title');
|
||||
const contentElement = item.querySelector('.content, .news-content');
|
||||
|
||||
|
||||
const dateElement = item.querySelector('.nb-date, .news-date');
|
||||
let dateStr = '';
|
||||
|
||||
if (dateElement) {
|
||||
const yearElement = dateElement.querySelector('.year');
|
||||
const monthElement = dateElement.querySelector('.month');
|
||||
const dayElement = dateElement.querySelector('.day');
|
||||
|
||||
if (yearElement && monthElement && dayElement) {
|
||||
dateStr = `${yearElement.textContent} ${monthElement.textContent} ${dayElement.textContent}`;
|
||||
} else {
|
||||
dateStr = dateElement.textContent;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const authorElement = item.querySelector('.auth-name span, .news-author');
|
||||
|
||||
return {
|
||||
title: titleElement?.textContent?.trim() || '',
|
||||
date: dateStr.trim(),
|
||||
content: contentElement?.textContent?.trim() || '',
|
||||
author: authorElement?.textContent?.trim() || ''
|
||||
};
|
||||
}).filter(news => news.title || news.content);
|
||||
}
|
||||
|
||||
extractAll() {
|
||||
this.extractGrades();
|
||||
this.extractAbsences();
|
||||
this.extractNotes();
|
||||
this.extractExams();
|
||||
this.extractNews();
|
||||
return this.data;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class DashboardUI {
|
||||
constructor(data) {
|
||||
this.data = {
|
||||
...data,
|
||||
schoolInfo: {
|
||||
name: cookies.getCookie(COOKIE_KEYS.SCHOOL_NAME) || DEFAULT_VALUES.SCHOOL,
|
||||
id: cookies.getCookie(COOKIE_KEYS.SCHOOL_CODE) || ''
|
||||
},
|
||||
userData: {
|
||||
name: cookies.getCookie(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);
|
||||
}
|
||||
|
||||
|
||||
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">
|
||||
<div class="grid-container">
|
||||
${this.generateGradeCard()}
|
||||
${this.generateAbsenceCard()}
|
||||
${this.generateNoteCard()}
|
||||
${this.generateExamCard()}
|
||||
${this.generateNewsCard()}
|
||||
</div>
|
||||
</main>
|
||||
`;
|
||||
}
|
||||
generateNewsCard() {
|
||||
const newsItems = this.data.news.map(news => `
|
||||
<div class="news-item">
|
||||
<div class="news-header">
|
||||
<div class="news-date">${news.date}</div>
|
||||
${news.author ? `<div class="news-author">${news.author}</div>` : ''}
|
||||
</div>
|
||||
<div class="news-details">
|
||||
<h3 class="news-title">${news.title}</h3>
|
||||
<div class="news-content">${news.content}</div>
|
||||
</div>
|
||||
</div>
|
||||
`).join('');
|
||||
|
||||
return this.generateCard('Hírek', newsItems || 'Jelenleg ez egy nem támogatott funkció', '/Intezmeny/Faliujsag', 'Összes hír');
|
||||
}
|
||||
generateGradeCard() {
|
||||
const gradeItems = this.data.grades.map(grade => `
|
||||
<div class="grade-item">
|
||||
<div class="grade-row">
|
||||
<div class="grade grade-${grade.value}">${grade.value}</div>
|
||||
<div class="grade-details">
|
||||
<div class="subject-name">${grade.subject}</div>
|
||||
<div class="grade-type">${grade.type}</div>
|
||||
</div>
|
||||
${grade.date ? `<div class="grade-date">${grade.date}</div>` : ''}
|
||||
</div>
|
||||
</div>
|
||||
`).join('');
|
||||
|
||||
return this.generateCard('Értékeléseid', gradeItems, '/TanuloErtekeles/Osztalyzatok', 'Összes jegyed');
|
||||
}
|
||||
generateAbsenceCard() {
|
||||
const absenceItems = this.data.absences.map(absence => `
|
||||
<div class="absence-item">
|
||||
<div class="absence-details">
|
||||
<div class="absence-type">${absence.type}</div>
|
||||
<div class="absence-date">${absence.date}</div>
|
||||
</div>
|
||||
</div>
|
||||
`).join('');
|
||||
|
||||
return this.generateCard('Mulasztások', absenceItems, '/Hianyzas/Hianyzasok', 'Összes mulasztás');
|
||||
}
|
||||
generateNoteCard() {
|
||||
const noteItems = this.data.notes.map(note => `
|
||||
<div class="note-item">
|
||||
<div class="note-details">
|
||||
<div class="note-title">${note.title}</div>
|
||||
<div class="note-date">${note.date}</div>
|
||||
</div>
|
||||
</div>
|
||||
`).join('');
|
||||
|
||||
return this.generateCard('Feljegyzések', noteItems, '/TanuloErtekeles/InformaciokFeljegyzesek', 'Összes üzeneted');
|
||||
}
|
||||
generateExamCard() {
|
||||
const examItems = this.data.upcomingExams.map(exam => `
|
||||
<div class="exam-item">
|
||||
<div class="exam-details">
|
||||
<div class="exam-subject">${exam.subject}</div>
|
||||
<div class="exam-date">${utils.formatHungarianDate(exam.date)}</div>
|
||||
</div>
|
||||
</div>
|
||||
`).join('');
|
||||
|
||||
return this.generateCard('Bejelentett dolgozatok', examItems, '/Tanulo/TanuloBejelentettSzamonkeresek', 'Összes dolgozat');
|
||||
}
|
||||
generateCard(title, content, linkHref, linkText) {
|
||||
return `
|
||||
<div class="card">
|
||||
<h2>${title}</h2>
|
||||
<div class="card-content">
|
||||
${content || `Jelenleg ez egy nem támogatott funkció`}
|
||||
<a href="${linkHref}" class="more-link">
|
||||
${linkText}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="17" viewBox="0 0 16 17" fill="none">
|
||||
<path d="M11.2997 5.19947L5.64282 5.19947M11.2997 5.19947L11.2997 10.8563M11.2997 5.19947L4.70001 11.7991" stroke="var(--accent-accent)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
render() {
|
||||
document.body.innerHTML = `
|
||||
<div class="kreta-container">
|
||||
${DashboardUI.generateHeaderHTML(this.data, this.schoolNameFull, this.shortenedSchoolName)}
|
||||
${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();
|
||||
}
|
||||
|
||||
async initialize() {
|
||||
if (!window.location.href.includes('/Intezmeny/Faliujsag')) return;
|
||||
|
||||
try {
|
||||
const dataExtractor = new DashboardDataExtractor();
|
||||
const dashboardData = dataExtractor.extractAll();
|
||||
FontLoader.loadFonts();
|
||||
const ui = new DashboardUI(dashboardData);
|
||||
ui.render();
|
||||
} catch (error) {
|
||||
console.error('Error initializing dashboard:', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
new DashboardApp();
|
||||
BIN
fonts/Figtree-Regular.woff2
Normal file
BIN
fonts/Montserrat-Medium.woff2
Normal file
BIN
fonts/Montserrat-Regular.woff2
Normal file
BIN
fonts/Montserrat-SemiBold.woff2
Normal file
202
forgotpassword/forgotpassword.css
Normal file
@@ -0,0 +1,202 @@
|
||||
:root {
|
||||
--primary: #050B15;
|
||||
--secondary: #3F444F;
|
||||
--tertiary: #1C469A;
|
||||
--icon: #0A2456;
|
||||
--accent: #3673EE;
|
||||
--bg: #DAE4F7;
|
||||
--card: #EDF3FF;
|
||||
--cardsec: #FBFCFF;
|
||||
--error: #E32D2D;
|
||||
--error-bg: rgba(227, 45, 45, 0.05);
|
||||
}
|
||||
|
||||
:root[data-theme="dark"] {
|
||||
--primary: #EBF1FD;
|
||||
--secondary: #CFD8E9;
|
||||
--tertiary: #AEC8FC;
|
||||
--icon: #BAD1FF;
|
||||
--accent: #3673ed;
|
||||
--bg: #070A0E;
|
||||
--card: #0F131B;
|
||||
--cardsec: #131822;
|
||||
--error: #FF4444;
|
||||
--error-bg: rgba(255, 68, 68, 0.1);
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
color: var(--primary);
|
||||
background-color: var(--bg) !important;
|
||||
font-family: "Montserrat", serif !important;
|
||||
min-height: 100vh;
|
||||
font-size: 16px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.forgot-container {
|
||||
width: 100%;
|
||||
max-width: 500px;
|
||||
padding: 20px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.forgot-header {
|
||||
text-align: center;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.logo-text {
|
||||
color: var(--icon);
|
||||
font-size: 24px;
|
||||
font-weight: 600;
|
||||
margin: 16px 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.logo {
|
||||
width: 24px;
|
||||
border-radius: 8px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.forgot-card {
|
||||
background: var(--card);
|
||||
padding: 24px;
|
||||
border-radius: 24px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.forgot-title {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: var(--primary);
|
||||
margin-bottom: 24px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.form-label {
|
||||
display: block;
|
||||
color: var(--secondary);
|
||||
font-size: 14px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.form-control {
|
||||
width: 100%;
|
||||
padding: 12px 16px;
|
||||
border: 2px solid transparent;
|
||||
border-radius: 12px;
|
||||
font-size: 16px;
|
||||
font-family: "Montserrat", serif;
|
||||
background: var(--cardsec);
|
||||
color: var(--primary);
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.form-control:focus {
|
||||
outline: none;
|
||||
border-color: var(--accent);
|
||||
}
|
||||
|
||||
.form-control::placeholder {
|
||||
color: var(--secondary);
|
||||
}
|
||||
|
||||
.form-actions {
|
||||
margin-top: 24px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.help-link {
|
||||
color: var(--accent);
|
||||
text-decoration: none;
|
||||
font-size: 14px;
|
||||
transition: color 0.2s ease;
|
||||
}
|
||||
|
||||
.help-link:hover {
|
||||
color: var(--tertiary);
|
||||
}
|
||||
|
||||
.btn-submit {
|
||||
padding: 12px 24px;
|
||||
background: var(--accent);
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 12px;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
font-family: "Montserrat", serif;
|
||||
cursor: pointer;
|
||||
transition: background 0.2s ease;
|
||||
}
|
||||
|
||||
.btn-submit:hover {
|
||||
background: var(--tertiary);
|
||||
}
|
||||
|
||||
.btn-submit:disabled {
|
||||
opacity: 0.7;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.error-message {
|
||||
color: var(--error);
|
||||
font-size: 14px;
|
||||
margin-top: 4px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.error-message.show {
|
||||
display: block;
|
||||
animation: fadeIn 0.2s ease;
|
||||
}
|
||||
|
||||
.g-recaptcha {
|
||||
margin-top: 24px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from { opacity: 0; transform: translateY(-4px); }
|
||||
to { opacity: 1; transform: translateY(0); }
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.forgot-container {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.forgot-card {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.form-actions {
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.btn-submit {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
152
forgotpassword/forgotpassword.js
Normal file
@@ -0,0 +1,152 @@
|
||||
(() => {
|
||||
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') {
|
||||
document.documentElement.setAttribute('data-theme', message.darkMode ? 'dark' : 'light');
|
||||
localStorage.setItem('darkMode', message.darkMode);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
document.body.innerHTML = `
|
||||
<div class="forgot-container">
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap" rel="stylesheet">
|
||||
<link href="https://fonts.googleapis.com/icon?family=Material+Icons+Round" rel="stylesheet">
|
||||
|
||||
<header class="forgot-header">
|
||||
<p class="logo-text">
|
||||
<img src="${chrome.runtime.getURL('images/firka_logo.png')}" alt="Firka" class="logo">
|
||||
Firka
|
||||
</p>
|
||||
</header>
|
||||
|
||||
<div class="forgot-card">
|
||||
<h1 class="forgot-title">Elfelejtett jelszó</h1>
|
||||
|
||||
<form id="forgotForm" novalidate>
|
||||
<div class="form-group">
|
||||
<label class="form-label" for="username">OM azonosítód</label>
|
||||
<input type="text" id="username" name="username" class="form-control"
|
||||
placeholder="Add meg az OM azonosítód" required>
|
||||
<div class="error-message">Kérjük, add meg az OM azonosítód.</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label" for="email">E-mail cím</label>
|
||||
<input type="email" id="email" name="email" class="form-control"
|
||||
placeholder="Add meg az e-mail címed" required>
|
||||
<div class="error-message">Kérjük, add meg az e-mail címed.</div>
|
||||
</div>
|
||||
|
||||
<div class="g-recaptcha" data-sitekey="6LcmPB8dAAAAACJPQBj7WfpBoBsEfyibZeIG5Vbl"></div>
|
||||
|
||||
<div class="form-actions">
|
||||
<a href="/Adminisztracio/Login" class="help-link">
|
||||
Vissza a bejelentkezéshez
|
||||
</a>
|
||||
<button type="submit" class="btn-submit">
|
||||
Jelszó visszaállítása
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
setupFormValidation();
|
||||
};
|
||||
|
||||
const setupFormValidation = () => {
|
||||
const form = document.getElementById('forgotForm');
|
||||
const inputs = form.querySelectorAll('.form-control');
|
||||
|
||||
inputs.forEach(input => {
|
||||
|
||||
input.addEventListener('input', () => {
|
||||
validateInput(input);
|
||||
});
|
||||
|
||||
|
||||
input.addEventListener('blur', () => {
|
||||
validateInput(input, true);
|
||||
});
|
||||
});
|
||||
|
||||
form.addEventListener('submit', handleSubmit);
|
||||
};
|
||||
|
||||
const validateInput = (input, showError = false) => {
|
||||
const isValid = input.value.trim().length > 0;
|
||||
const errorElement = input.nextElementSibling;
|
||||
|
||||
if (!isValid && showError) {
|
||||
input.classList.add('error');
|
||||
errorElement?.classList.add('show');
|
||||
} else {
|
||||
input.classList.remove('error');
|
||||
errorElement?.classList.remove('show');
|
||||
}
|
||||
|
||||
return isValid;
|
||||
};
|
||||
|
||||
const handleSubmit = async (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) {
|
||||
return;
|
||||
}
|
||||
|
||||
const submitButton = form.querySelector('.btn-submit');
|
||||
submitButton.disabled = true;
|
||||
|
||||
try {
|
||||
const formData = new FormData(form);
|
||||
const response = await fetch('/Adminisztracio/ElfelejtettJelszo/LinkKuldes', {
|
||||
method: 'POST',
|
||||
body: formData,
|
||||
headers: {
|
||||
'X-Requested-With': 'XMLHttpRequest'
|
||||
}
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (result.Success) {
|
||||
window.location.href = '/Adminisztracio/Login';
|
||||
} else {
|
||||
|
||||
alert(result.Message || 'Hiba történt a jelszó visszaállítása során. (Kérlek használd az eredeti kréta oldalt erre)');
|
||||
grecaptcha.reset();
|
||||
}
|
||||
} catch (error) {
|
||||
//alert('Hiba történt a jelszó visszaállítása során.');
|
||||
grecaptcha.reset();
|
||||
} finally {
|
||||
submitButton.disabled = false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
if (window.location.href.includes('/Adminisztracio/ElfelejtettJelszo')) {
|
||||
transformForgotPasswordPage();
|
||||
}
|
||||
})();
|
||||
51
global/maintenance.css
Normal file
@@ -0,0 +1,51 @@
|
||||
body.maintenance-mode {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: var(--background);
|
||||
color: var(--text-primary);
|
||||
font-family: 'Inter', sans-serif;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: var(--background) !important;
|
||||
}
|
||||
|
||||
.maintenance-container {
|
||||
text-align: center;
|
||||
padding: 2rem;
|
||||
border-radius: 8px;
|
||||
background-color: var(--card-card);
|
||||
box-shadow: 0 var(--shadow-blur) 6px var(--accent-shadow);
|
||||
max-width: 600px;
|
||||
width: 90%;
|
||||
}
|
||||
|
||||
.maintenance-logo {
|
||||
width: 128px;
|
||||
height: 128px;
|
||||
margin: 0 auto 2rem;
|
||||
}
|
||||
|
||||
.maintenance-title {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 600;
|
||||
margin-bottom: 1rem;
|
||||
color: var(--accent-accent);
|
||||
}
|
||||
|
||||
.maintenance-message {
|
||||
font-size: 1rem;
|
||||
line-height: 1.5;
|
||||
margin-bottom: 1.5rem;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.maintenance-footer {
|
||||
font-size: 0.875rem;
|
||||
color: var(--text-secondary);
|
||||
margin-top: 2rem;
|
||||
}
|
||||
65
global/maintenance.js
Normal file
@@ -0,0 +1,65 @@
|
||||
function loadMaintenanceCSS() {
|
||||
const maintenanceCSS = document.createElement('link');
|
||||
maintenanceCSS.rel = 'stylesheet';
|
||||
maintenanceCSS.href = chrome.runtime.getURL('global/maintenance.css');
|
||||
document.head.appendChild(maintenanceCSS);
|
||||
}
|
||||
|
||||
function checkMaintenancePage() {
|
||||
const maintenanceContent = document.querySelector('.login_content');
|
||||
if (maintenanceContent && maintenanceContent.textContent.includes('frissítés alatt')) {
|
||||
const body = document.body;
|
||||
const mainLogo = chrome.runtime.getURL('images/firka_logo_128.png');
|
||||
|
||||
|
||||
const existingStyles = document.querySelectorAll('link[rel="stylesheet"], style');
|
||||
existingStyles.forEach(style => style.remove());
|
||||
|
||||
|
||||
body.innerHTML = '';
|
||||
body.classList.add('maintenance-mode');
|
||||
body.classList.add('theme-enabled');
|
||||
|
||||
|
||||
loadMaintenanceCSS();
|
||||
|
||||
|
||||
const container = document.createElement('div');
|
||||
container.className = 'maintenance-container';
|
||||
|
||||
const logo = document.createElement('img');
|
||||
logo.src = mainLogo;
|
||||
logo.alt = 'Firka Logo';
|
||||
logo.className = 'maintenance-logo';
|
||||
|
||||
const title = document.createElement('h1');
|
||||
title.className = 'maintenance-title';
|
||||
title.textContent = 'Karbantartás';
|
||||
|
||||
const messageDiv = document.createElement('div');
|
||||
messageDiv.className = 'maintenance-message';
|
||||
|
||||
const paragraph1 = document.createElement('p');
|
||||
paragraph1.textContent = 'A KRÉTA rendszer jelenleg frissítés alatt van, hamarosan újra elérhetővé válik.';
|
||||
|
||||
const paragraph2 = document.createElement('p');
|
||||
paragraph2.textContent = 'Köszönjük türelmüket és megértésüket!';
|
||||
|
||||
const footer = document.createElement('div');
|
||||
footer.className = 'maintenance-footer';
|
||||
footer.textContent = 'KRÉTA Csapat';
|
||||
|
||||
|
||||
messageDiv.appendChild(paragraph1);
|
||||
messageDiv.appendChild(paragraph2);
|
||||
|
||||
container.appendChild(logo);
|
||||
container.appendChild(title);
|
||||
container.appendChild(messageDiv);
|
||||
container.appendChild(footer);
|
||||
|
||||
body.appendChild(container);
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', checkMaintenancePage);
|
||||
257
global/navigation.css
Normal file
@@ -0,0 +1,257 @@
|
||||
.kreta-header {
|
||||
padding: clamp(1rem, 3vw, 2rem);
|
||||
display: grid;
|
||||
grid-template-columns: minmax(300px, 400px) 1fr minmax(200px, 300px);
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
background-color: var(--background);
|
||||
}
|
||||
|
||||
|
||||
.school-info {
|
||||
margin: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.logo-text {
|
||||
color: var(--text-primary);
|
||||
font-size: 24px;
|
||||
font-weight: 600;
|
||||
margin: 0 0 0.5rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.logo {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border-radius: 8px;
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
|
||||
.school-details {
|
||||
color: var(--text-secondary);
|
||||
font-size: 14px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
|
||||
.kreta-nav {
|
||||
padding: 0 clamp(0.5rem, 3vw, 1.5rem);
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 100;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.nav-links {
|
||||
display: flex;
|
||||
gap: clamp(0.5rem, 2vw, 1rem);
|
||||
padding: 0.25rem;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.nav-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: clamp(0.5rem, 1.5vw, 1rem) 0.5rem;
|
||||
color: var(--text-secondary);
|
||||
text-decoration: none;
|
||||
font-weight: 500;
|
||||
white-space: nowrap;
|
||||
border-radius: 8px;
|
||||
transition: all 0.2s ease;
|
||||
gap: 0.5rem;
|
||||
text-decoration: none;
|
||||
}
|
||||
.nav-item.active {
|
||||
display: flex;
|
||||
padding: 8px 14px 8px 12px;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
border-radius: 20px;
|
||||
background: var(--button-secondaryFill);
|
||||
box-shadow: 0px 1px var(--shadow-blur, 2px) 0px var(--accent-shadow);
|
||||
}
|
||||
|
||||
.nav-item:hover {
|
||||
color: var(--text-primary);
|
||||
background-color: var(--hover);
|
||||
border-radius: 8px;
|
||||
text-decoration: none;
|
||||
}
|
||||
.nav-item.active:hover {
|
||||
color: var(--accent-accent);
|
||||
background-color: var(--accent-hover);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.nav-item img,
|
||||
.nav-item svg {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
.nav-item.active svg path {
|
||||
fill: var(--accent-accent);
|
||||
}
|
||||
|
||||
|
||||
.user-profile {
|
||||
position: relative;
|
||||
justify-self: flex-end;
|
||||
}
|
||||
|
||||
.user-dropdown-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
padding: 0.5rem;
|
||||
border-radius: 8px;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.user-dropdown-btn:hover {
|
||||
background: var(--hover);
|
||||
}
|
||||
|
||||
.user-info {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.user-name {
|
||||
display: block;
|
||||
color: var(--text-primary);
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.nav-logout-timer {
|
||||
display: block;
|
||||
color: var(--text-secondary);
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.user-dropdown {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
right: 0;
|
||||
margin-top: 0.5rem;
|
||||
background: var(--card-card);
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
|
||||
width: 200px;
|
||||
display: none;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.user-dropdown.show {
|
||||
display: block;
|
||||
animation: dropdownShow 0.2s ease;
|
||||
}
|
||||
|
||||
.dropdown-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
padding: 0.75rem 1rem;
|
||||
color: var(--text-primary);
|
||||
text-decoration: none;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.dropdown-item:hover {
|
||||
background: var(--hover);
|
||||
color: var(--accent-accent);
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
|
||||
@keyframes dropdownShow {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-10px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@media (max-width: 1200px) {
|
||||
.kreta-header {
|
||||
grid-template-columns: minmax(250px, 350px) 1fr minmax(180px, 250px);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.kreta-header {
|
||||
grid-template-columns: 1fr auto;
|
||||
grid-template-areas:
|
||||
"school user"
|
||||
"nav nav";
|
||||
padding: 1rem;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.school-info {
|
||||
grid-area: school;
|
||||
max-width: none;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.logo-text {
|
||||
margin: 0;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.school-details {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
|
||||
.kreta-nav::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.nav-links {
|
||||
justify-content: flex-start;
|
||||
width: 100%;
|
||||
gap: 0.25rem;
|
||||
}
|
||||
|
||||
.nav-item {
|
||||
padding: 0.5rem;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.user-profile {
|
||||
grid-area: user;
|
||||
}
|
||||
|
||||
.user-name {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.nav-logout-timer {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
103
global/navigation.js
Normal file
@@ -0,0 +1,103 @@
|
||||
const COOKIE_KEYS = {
|
||||
SCHOOL_NAME: 'schoolName',
|
||||
SCHOOL_CODE: 'schoolCode',
|
||||
USER_NAME: 'userName',
|
||||
SCHOOL_SUBDOMAIN: 'schoolSubdomain'
|
||||
};
|
||||
|
||||
const DEFAULT_VALUES = {
|
||||
SCHOOL: 'Iskola',
|
||||
USER: 'Felhasználó',
|
||||
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,
|
||||
time: document.querySelector('.usermenu_timer')?.textContent?.trim() || DEFAULT_VALUES.TIMER
|
||||
};
|
||||
|
||||
if (schoolName) {
|
||||
schoolName.textContent = `${userData.schoolId} - ${userData.schoolName}`;
|
||||
}
|
||||
|
||||
if (userName) {
|
||||
userName.textContent = userData.name;
|
||||
}
|
||||
|
||||
if (logoutTimer) {
|
||||
startLogoutTimer(userData.time);
|
||||
}
|
||||
}
|
||||
|
||||
function startLogoutTimer(timeString) {
|
||||
const startTime = parseInt(timeString?.match(/\d+/)?.[0] || "45");
|
||||
let timeLeft = startTime * 60;
|
||||
const timerElement = document.querySelector('.nav-logout-timer');
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
updateHeaderInfo();
|
||||
});
|
||||
|
||||
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');
|
||||
});
|
||||
}
|
||||
|
||||
function setupSettingsButton() {
|
||||
document.getElementById('settingsBtn')?.addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
const url = chrome.runtime.getURL('settings/index.html');
|
||||
window.open(url, '_blank', 'width=400,height=600');
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
updateHeaderInfo();
|
||||
setupUserDropdown();
|
||||
setupSettingsButton();
|
||||
});
|
||||
160
global/theme.css
Normal file
@@ -0,0 +1,160 @@
|
||||
:root {
|
||||
--background: #DAE4F7;
|
||||
--background-0: #dae4f700;
|
||||
--success: var(--grades-4);
|
||||
--shadow-blur: 2px;
|
||||
--text-primary: #050B15;
|
||||
--text-secondary: #050b15cc;
|
||||
--text-teritary: #050b1580;
|
||||
--card-card: #EDF3FF;
|
||||
--card-translucent: #edf3ff80;
|
||||
--button-secondaryFill: #FBFCFF;
|
||||
--accent-accent: #3673EE;
|
||||
--accent-secondary: #1C469A;
|
||||
--accent-shadow: #1c469a26;
|
||||
--accent-15: #3673ee26;
|
||||
--warning-accent: var(--grades-2);
|
||||
--warning-text: #8F531B;
|
||||
--warning-15: #ffa04626;
|
||||
--warning-card: #FAEBDC;
|
||||
--error-accent: var(--grades-1);
|
||||
--error-text: #8F1B4F;
|
||||
--error-15: #FF54A126;
|
||||
--error-card: #FADCE9;
|
||||
--grades-1: #FF54A1;
|
||||
--grades-2: #FFA046;
|
||||
--grades-3: #F9CF00;
|
||||
--grades-4: #92EA3B;
|
||||
--grades-5: #22CCAD;
|
||||
--grades-background-1: #FF54A126;
|
||||
--grades-background-2: #FFA04626;
|
||||
--grades-background-3: #F9CF0026;
|
||||
--grades-background-4: #92EA3B26;
|
||||
--grades-background-5: #22CCAD26;
|
||||
}
|
||||
|
||||
|
||||
:root[data-theme="light-green"] {
|
||||
--background: #FAFFF0;
|
||||
--background-0: #fafff000;
|
||||
--success: var(--grades-4);
|
||||
--shadow-blur: 2px;
|
||||
--text-primary: #394C0A;
|
||||
--text-secondary: #394c0acc;
|
||||
--text-teritary: #394c0a80;
|
||||
--card-card: #F3FBDE;
|
||||
--card-translucent: #f3fbde80;
|
||||
--button-secondaryFill: #FEFFFD;
|
||||
--accent-accent: #A7DC22;
|
||||
--accent-secondary: #6E8F1B;
|
||||
--accent-shadow: #647e2226;
|
||||
--accent-15: #a7dc2226;
|
||||
--warning-accent: var(--grades-2);
|
||||
--warning-text: #8F531B;
|
||||
--warning-15: #ffa04626;
|
||||
--warning-card: #FAEBDC;
|
||||
--error-accent: var(--grades-1);
|
||||
--error-text: #8F1B4F;
|
||||
--error-15: #FF54A126;
|
||||
--error-card: #FADCE9;
|
||||
--grades-1: #FF54A1;
|
||||
--grades-2: #FFA046;
|
||||
--grades-3: #F9CF00;
|
||||
--grades-4: #92EA3B;
|
||||
--grades-5: #22CCAD;
|
||||
--grades-background-1: #FF54A126;
|
||||
--grades-background-2: #FFA04626;
|
||||
--grades-background-3: #F9CF0026;
|
||||
--grades-background-4: #92EA3B26;
|
||||
--grades-background-5: #22CCAD26;
|
||||
}
|
||||
|
||||
|
||||
:root[data-theme="dark-blue"] {
|
||||
--background: #070A0E;
|
||||
--background-0: #070a0e00;
|
||||
--success: var(--grades-4);
|
||||
--shadow-blur: 0;
|
||||
--text-primary: #EBF1FD;
|
||||
--text-secondary: #ebf1fdcc;
|
||||
--text-teritary: #ebf1fd80;
|
||||
--card-card: #0F131B;
|
||||
--card-translucent: #0f131b80;
|
||||
--button-secondaryFill: #131822;
|
||||
--accent-accent: #3673EE;
|
||||
--accent-secondary: #AEC8FC;
|
||||
--accent-shadow: #0000;
|
||||
--accent-15: #3673ee26;
|
||||
--warning-accent: var(--grades-2);
|
||||
--warning-text: #f0b37a;
|
||||
--warning-15: #ffa04626;
|
||||
--warning-card: #201203;
|
||||
--error-accent: var(--grades-1);
|
||||
--error-text: #f59ec5;
|
||||
--error-15: #ff54a126;
|
||||
--error-card: #1e030f;
|
||||
--grades-1: #FF54A1;
|
||||
--grades-2: #FFA046;
|
||||
--grades-3: #F9CF00;
|
||||
--grades-4: #92EA3B;
|
||||
--grades-5: #22CCAD;
|
||||
--grades-background-1: #FF54A126;
|
||||
--grades-background-2: #FFA04626;
|
||||
--grades-background-3: #F9CF0026;
|
||||
--grades-background-4: #92EA3B26;
|
||||
--grades-background-5: #22CCAD26;
|
||||
}
|
||||
|
||||
|
||||
:root[data-theme="dark-green"] {
|
||||
--background: #0D1202;
|
||||
--background-0: #0E130200;
|
||||
--success: var(--grades-4);
|
||||
--shadow-blur: 0;
|
||||
--text-primary: #EAF7CC;
|
||||
--text-secondary: #EAF7CCCC;
|
||||
--text-teritary: #EAF7CC80;
|
||||
--card-card: #141905;
|
||||
--card-translucent: #14190580;
|
||||
--button-secondaryFill: #20290b;
|
||||
--accent-accent: #A7DC22;
|
||||
--accent-secondary: #CBEE71;
|
||||
--accent-shadow: #0000;
|
||||
--accent-15: #a7dc2226;
|
||||
--warning-accent: var(--grades-2);
|
||||
--warning-text: #f0b37a;
|
||||
--warning-15: #ffa04626;
|
||||
--warning-card: #201203;
|
||||
--error-accent: var(--grades-1);
|
||||
--error-text: #f59ec5;
|
||||
--error-15: #ff54a126;
|
||||
--error-card: #1e030f;
|
||||
--grades-1: #FF54A1;
|
||||
--grades-2: #FFA046;
|
||||
--grades-3: #F9CF00;
|
||||
--grades-4: #92EA3B;
|
||||
--grades-5: #22CCAD;
|
||||
--grades-background-1: #FF54A126;
|
||||
--grades-background-2: #FFA04626;
|
||||
--grades-background-3: #F9CF0026;
|
||||
--grades-background-4: #92EA3B26;
|
||||
--grades-background-5: #22CCAD26;
|
||||
}
|
||||
|
||||
|
||||
html {
|
||||
background-color: var(--background) !important;
|
||||
color: var(--text-primary) !important;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: var(--background) !important;
|
||||
color: var(--text-primary) !important;
|
||||
transition: background-color 0.2s ease, color 0.2s ease;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
|
||||
* {
|
||||
transition: background-color 0.2s ease, color 0.2s ease, border-color 0.2s ease;
|
||||
}
|
||||
127
global/theme.js
Normal file
@@ -0,0 +1,127 @@
|
||||
(() => {
|
||||
|
||||
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);
|
||||
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 initializeTheme() {
|
||||
|
||||
const cookieTheme = getCookie('themePreference');
|
||||
const localStorageTheme = localStorage.getItem('themePreference');
|
||||
|
||||
|
||||
const theme = cookieTheme || localStorageTheme || 'light-blue';
|
||||
|
||||
|
||||
setTheme(theme);
|
||||
|
||||
|
||||
if (cookieTheme !== localStorageTheme) {
|
||||
if (cookieTheme) {
|
||||
localStorage.setItem('themePreference', cookieTheme);
|
||||
} else if (localStorageTheme) {
|
||||
setCookie('themePreference', localStorageTheme);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
initializeTheme();
|
||||
});
|
||||
|
||||
|
||||
initializeTheme();
|
||||
} else {
|
||||
|
||||
initializeTheme();
|
||||
}
|
||||
|
||||
|
||||
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
||||
if (message.action === 'changeTheme') {
|
||||
setTheme(message.theme);
|
||||
sendResponse({ success: true });
|
||||
}
|
||||
|
||||
if (message.action === 'getTheme') {
|
||||
const currentTheme = document.documentElement.getAttribute('data-theme') || 'light-blue';
|
||||
sendResponse({ theme: currentTheme });
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
|
||||
const observer = new MutationObserver((mutations) => {
|
||||
const currentTheme = document.documentElement.getAttribute('data-theme');
|
||||
const savedTheme = getCookie('themePreference') || localStorage.getItem('themePreference');
|
||||
|
||||
if ((!currentTheme && savedTheme) || (currentTheme !== savedTheme && savedTheme)) {
|
||||
setTheme(savedTheme);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
observer.observe(document.documentElement, {
|
||||
attributes: true,
|
||||
attributeFilter: ['data-theme']
|
||||
});
|
||||
});
|
||||
} else {
|
||||
observer.observe(document.documentElement, {
|
||||
attributes: true,
|
||||
attributeFilter: ['data-theme']
|
||||
});
|
||||
}
|
||||
})();
|
||||
20
grades/chart.js
Normal file
716
grades/grades.css
Normal file
@@ -0,0 +1,716 @@
|
||||
@font-face {
|
||||
font-family: 'Montserrat';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: url(chrome-extension://__MSG_@@extension_id__/fonts/Montserrat-SemiBold.woff2) format('woff2');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Montserrat';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
src: url(chrome-extension://__MSG_@@extension_id__/fonts/Montserrat-Regular.woff2) format('woff2');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Montserrat';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
src: url(chrome-extension://__MSG_@@extension_id__/fonts/Montserrat-Medium.woff2) format('woff2');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Figtree';
|
||||
src: url('chrome-extension://__MSG_@@extension_id__/fonts/Figtree-Regular.woff2') format('woff2');
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
* {
|
||||
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", serif !important;
|
||||
min-height: 100vh;
|
||||
font-size: 16px;
|
||||
}
|
||||
.kreta-container {
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.grades-chart {
|
||||
width: 100%;
|
||||
height: 250px;
|
||||
margin-bottom: 1.5rem;
|
||||
padding: 1rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.overall-averages {
|
||||
margin-bottom: 2rem;
|
||||
padding: 1.5rem;
|
||||
background: var(--card-card);
|
||||
border-radius: 24px;
|
||||
box-shadow: 0px 1px var(--shadow-blur) 0px var(--accent-shadow);
|
||||
}
|
||||
.average-details {
|
||||
display: flex;
|
||||
gap: 2rem;
|
||||
justify-content: center;
|
||||
}
|
||||
.average-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
}
|
||||
.average-label {
|
||||
color: var(--text-secondary);
|
||||
font-size: 1.1rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
.average-value {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
.average-value.warning {
|
||||
color: var(--error-accent);
|
||||
}
|
||||
|
||||
.grades-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(min(100%, 400px), 1fr));
|
||||
gap: 1.5rem;
|
||||
}
|
||||
.subject-card {
|
||||
background: var(--card-card);
|
||||
border-radius: 24px;
|
||||
padding: 1.5rem;
|
||||
box-shadow: 0px 1px var(--shadow-blur) 0px var(--accent-shadow);
|
||||
}
|
||||
.subject-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 0.5rem;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.subject-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
}
|
||||
.subject-title h3 {
|
||||
padding: 1rem;
|
||||
margin-bottom: 0px !important;
|
||||
margin-top: 0px !important;
|
||||
color: var(--text-primary);
|
||||
font-family: Montserrat;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
line-height: normal;
|
||||
}
|
||||
.subject-averages .average-circle {
|
||||
display: flex;
|
||||
width: 48px;
|
||||
height: 26px;
|
||||
padding: 6px 8px;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 14px;
|
||||
border-radius: 16px;
|
||||
background-color: var(--background-secondary);
|
||||
}
|
||||
.subject-averages .class-average[data-grade="1"] {
|
||||
border: 2px solid var(--grades-1);
|
||||
color: var(--grades-1);
|
||||
}
|
||||
.subject-averages .class-average[data-grade="2"] {
|
||||
border: 2px solid var(--grades-2);
|
||||
color: var(--grades-2);
|
||||
}
|
||||
.subject-averages .class-average[data-grade="3"] {
|
||||
border: 2px solid var(--grades-3);
|
||||
color: var(--grades-3);
|
||||
}
|
||||
.subject-averages .class-average[data-grade="4"] {
|
||||
border: 2px solid var(--grades-4);
|
||||
color: var(--grades-4);
|
||||
}
|
||||
.subject-averages .class-average[data-grade="5"] {
|
||||
border: 2px solid var(--grades-5);
|
||||
color: var(--grades-5);
|
||||
}.subject-averages .average-label {
|
||||
font-size: 0.625rem;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
.subject-averages .average-value {
|
||||
font-size: 0.875rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.subject-averages .my-average[data-grade] .average-value,
|
||||
.subject-averages .class-average[data-grade] .average-value {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.subject-averages {
|
||||
display: flex;
|
||||
gap: 0.75rem;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.grades-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
}
|
||||
.grade-item {
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr auto;
|
||||
gap: 1rem;
|
||||
padding: 1rem;
|
||||
border-radius: 12px;
|
||||
align-items: start;
|
||||
position: relative;
|
||||
background-color: var(--card-card);
|
||||
}
|
||||
.grade-value {
|
||||
display: flex;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
padding: 7.5px 0px;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border-radius: 12px;
|
||||
font-family: Montserrat;
|
||||
font-size: 18px;
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
line-height: normal;
|
||||
text-align: center;
|
||||
}
|
||||
.grade-details {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.25rem;
|
||||
}
|
||||
.grade-theme {
|
||||
overflow: hidden;
|
||||
color: var(--text-primary);
|
||||
text-overflow: ellipsis;
|
||||
font-family: Figtree;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
line-height: 130%;
|
||||
}
|
||||
.grade-meta, .grade-date {
|
||||
overflow: hidden;
|
||||
color: var(--text-secondary);
|
||||
text-overflow: ellipsis;
|
||||
font-family: Figtree;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
line-height: 130%;
|
||||
}
|
||||
|
||||
.grade-date {
|
||||
position: absolute;
|
||||
top: 1rem;
|
||||
right: 1rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.grade-1 .grade-value {
|
||||
background-color: var(--grades-background-1);
|
||||
color: var(--grades-1);
|
||||
}
|
||||
.grade-2 .grade-value {
|
||||
background-color: var(--grades-background-2);
|
||||
color: var(--grades-2);
|
||||
}
|
||||
.grade-3 .grade-value {
|
||||
background-color: var(--grades-background-3);
|
||||
color: var(--grades-3);
|
||||
}
|
||||
.grade-4 .grade-value {
|
||||
background-color: var(--grades-background-4);
|
||||
color: var(--grades-4);
|
||||
}
|
||||
.grade-5 .grade-value {
|
||||
background-color: var(--grades-background-5);
|
||||
color: var(--grades-5);
|
||||
}
|
||||
|
||||
.semester-grade {
|
||||
background-color: var(--button-secondaryFill) !important;
|
||||
border: 2px solid var(--accent-accent) !important;
|
||||
position: relative;
|
||||
padding-top: 1.5rem !important;
|
||||
box-shadow: 0px 1px var(--shadow-blur) 0px var(--accent-shadow);
|
||||
}
|
||||
.semester-grade::before {
|
||||
content: "Félévi értékelés";
|
||||
position: absolute;
|
||||
top: 0.25rem;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
background: var(--accent-accent);
|
||||
color: var(--button-secondaryFill);
|
||||
padding: 2px 12px;
|
||||
border-radius: 12px;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
white-space: nowrap;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.user-profile {
|
||||
position: relative;
|
||||
justify-self: flex-end;
|
||||
}
|
||||
.user-dropdown-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
padding: 0.5rem;
|
||||
border-radius: 8px;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
.user-dropdown-btn:hover {
|
||||
background: var(--card-card);
|
||||
}
|
||||
.user-info {
|
||||
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%;
|
||||
right: 0;
|
||||
margin-top: 0.5rem;
|
||||
background: var(--card-card);
|
||||
border-radius: 12px;
|
||||
box-shadow: 0px 1px var(--shadow-blur) 0px var(--accent-shadow);
|
||||
width: 200px;
|
||||
display: none;
|
||||
z-index: 1000;
|
||||
}
|
||||
.user-dropdown.show {
|
||||
display: block;
|
||||
animation: dropdownShow 0.2s ease;
|
||||
}
|
||||
.dropdown-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
padding: 0.75rem 1rem;
|
||||
color: var(--text-primary);
|
||||
text-decoration: none;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
.dropdown-item:hover {
|
||||
background: var(--button-secondaryFill);
|
||||
}
|
||||
|
||||
.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);
|
||||
}
|
||||
|
||||
.kreta-main {
|
||||
flex: 1;
|
||||
padding: clamp(1rem, 3vw, 2rem);
|
||||
max-width: 1400px;
|
||||
margin: 0 auto;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@keyframes dropdownShow {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-10px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
body {
|
||||
font-size: 14px;
|
||||
}
|
||||
.average-details {
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
}
|
||||
.nav-links {
|
||||
justify-content: flex-start;
|
||||
width: 100%;
|
||||
gap: 0.25rem;
|
||||
}
|
||||
.nav-links a {
|
||||
padding: 0.5rem;
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
|
||||
.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-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%;
|
||||
}
|
||||
|
||||
.material-icons-round {
|
||||
font-size: 20px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
}
|
||||
::-webkit-scrollbar-track {
|
||||
background: var(--background);
|
||||
}
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: var(--text-secondary);
|
||||
border-radius: 4px;
|
||||
}
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: var(--text-primary);
|
||||
}
|
||||
|
||||
.chart-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
padding: 1rem;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.chart-title {
|
||||
white-space: nowrap;
|
||||
color: var(--text-primary);
|
||||
font-family: Montserrat;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
.chart-averages {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
position: absolute;
|
||||
top: 1rem;
|
||||
right: 1rem;
|
||||
}
|
||||
|
||||
.average-circle {
|
||||
display: flex;
|
||||
width: 48px;
|
||||
height: 26px;
|
||||
padding: 6px 8px;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 14px;
|
||||
border-radius: 16px;
|
||||
}
|
||||
.average-circle[data-grade="1"],
|
||||
.my-average[data-grade="1"] {
|
||||
background-color: var(--grades-background-1);
|
||||
color: var(--grades-1);
|
||||
}
|
||||
.class-average[data-grade="1"] {
|
||||
background-color: transparent;
|
||||
border: 2px solid var(--grades-1);
|
||||
color: var(--grades-1);
|
||||
}
|
||||
|
||||
.average-circle[data-grade="2"],
|
||||
.my-average[data-grade="2"] {
|
||||
background-color: var(--grades-background-2);
|
||||
color: var(--grades-2);
|
||||
}
|
||||
.class-average[data-grade="2"] {
|
||||
background-color: transparent;
|
||||
border: 2px solid var(--grades-2);
|
||||
color: var(--grades-2);
|
||||
}
|
||||
|
||||
.average-circle[data-grade="3"],
|
||||
.my-average[data-grade="3"] {
|
||||
background-color: var(--grades-background-3);
|
||||
color: var(--grades-3);
|
||||
}
|
||||
.class-average[data-grade="3"] {
|
||||
background-color: transparent;
|
||||
border: 2px solid var(--grades-3);
|
||||
color: var(--grades-3);
|
||||
}
|
||||
|
||||
.average-circle[data-grade="4"],
|
||||
.my-average[data-grade="4"] {
|
||||
background-color: var(--grades-background-4);
|
||||
color: var(--grades-4);
|
||||
}
|
||||
.class-average[data-grade="4"] {
|
||||
background-color: transparent;
|
||||
border: 2px solid var(--grades-4);
|
||||
color: var(--grades-4);
|
||||
}
|
||||
|
||||
.average-circle[data-grade="5"],
|
||||
.my-average[data-grade="5"] {
|
||||
background-color: var(--grades-background-5);
|
||||
color: var(--grades-5);
|
||||
}
|
||||
.class-average[data-grade="5"] {
|
||||
background-color: transparent;
|
||||
border: 2px solid var(--grades-5);
|
||||
color: var(--grades-5);
|
||||
}
|
||||
.average-circle .average-label {
|
||||
font-size: 0.75rem;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.average-circle .average-value {
|
||||
text-align: center;
|
||||
font-family: Figtree;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
line-height: 130%;
|
||||
}
|
||||
|
||||
.grade-distribution {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.grade-count {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
padding: 4px 8px 4px 4px;
|
||||
border-radius: 16px;
|
||||
border: 1px solid var(--accent-15);
|
||||
}
|
||||
|
||||
.grade-count .grade-value {
|
||||
font-weight: 700;
|
||||
text-align: center;
|
||||
font-family: Montserrat;
|
||||
font-size: 18px;
|
||||
font-style: normal;
|
||||
line-height: 130%;
|
||||
}
|
||||
.grade-count .grade-amount {
|
||||
color: var(--text-primary);
|
||||
text-align: center;
|
||||
font-family: Montserrat;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
line-height: 130%;
|
||||
}
|
||||
|
||||
.grade-count.grade-1 { color: var(--grades-1); }
|
||||
.grade-count.grade-2 { color: var(--grades-2); }
|
||||
.grade-count.grade-3 { color: var(--grades-3); }
|
||||
.grade-count.grade-4 { color: var(--grades-4); }
|
||||
.grade-count.grade-5 { color: var(--grades-5); }
|
||||
|
||||
.grades-overview {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr auto;
|
||||
gap: 1.5rem;
|
||||
margin-bottom: 2rem;
|
||||
align-items: stretch;
|
||||
}
|
||||
.semester-grades {
|
||||
width: 300px;
|
||||
height: 400px;
|
||||
padding: 1.5rem;
|
||||
background: var(--card-card);
|
||||
border-radius: 24px;
|
||||
box-shadow: 0px 1px var(--shadow-blur) 0px var(--accent-shadow);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.semester-grades h3 {
|
||||
padding: 1rem;
|
||||
margin-bottom: 0px !important;
|
||||
margin-top: 0px !important;
|
||||
color: var(--text-primary);
|
||||
font-family: Montserrat;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
line-height: normal;
|
||||
}
|
||||
.semester-grade-item {
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr auto;
|
||||
gap: 1rem;
|
||||
padding: 1rem;
|
||||
border-radius: 12px;
|
||||
align-items: center;
|
||||
}
|
||||
.semester-grade-item:hover {
|
||||
background: var(--button-secondaryFill);
|
||||
}
|
||||
.semester-grades-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
overflow-y: auto;
|
||||
padding-right: 0.5rem;
|
||||
flex: 1;
|
||||
margin: -0.5rem 0;
|
||||
}
|
||||
.semester-grade-subject {
|
||||
overflow: hidden;
|
||||
color: var(--text-primary);
|
||||
text-overflow: ellipsis;
|
||||
font-family: Figtree;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
line-height: 130%;
|
||||
}
|
||||
.semester-grade-value {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 16px;
|
||||
font-weight: 700;
|
||||
font-size: 22px;
|
||||
}
|
||||
.semester-grade-item.grade-1 .semester-grade-value {
|
||||
background-color: var(--grades-background-1);
|
||||
color: var(--grades-1);
|
||||
}
|
||||
.semester-grade-item.grade-2 .semester-grade-value {
|
||||
background-color: var(--grades-background-2);
|
||||
color: var(--grades-2);
|
||||
}
|
||||
.semester-grade-item.grade-3 .semester-grade-value {
|
||||
background-color: var(--grades-background-3);
|
||||
color: var(--grades-3);
|
||||
}
|
||||
.semester-grade-item.grade-4 .semester-grade-value {
|
||||
background-color: var(--grades-background-4);
|
||||
color: var(--grades-4);
|
||||
}
|
||||
.semester-grade-item.grade-5 .semester-grade-value {
|
||||
background-color: var(--grades-background-5);
|
||||
color: var(--grades-5);
|
||||
}
|
||||
|
||||
@media (max-width: 1024px) {
|
||||
.grades-overview {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.semester-grades {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
586
grades/grades.js
Normal file
@@ -0,0 +1,586 @@
|
||||
(() => {
|
||||
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 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();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async function transformGradesPage() {
|
||||
try {
|
||||
showLoadingScreen();
|
||||
|
||||
await 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);
|
||||
|
||||
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 script = document.createElement('script');
|
||||
script.src = chrome.runtime.getURL('grades/chart.js');
|
||||
document.head.appendChild(script);
|
||||
|
||||
links.forEach(link => {
|
||||
const linkElement = document.createElement('link');
|
||||
Object.entries(link).forEach(([key, value]) => {
|
||||
linkElement[key] = value;
|
||||
});
|
||||
document.head.appendChild(linkElement);
|
||||
});
|
||||
|
||||
script.onload = () => {
|
||||
setupGradesChart(gradesData.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')
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
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) {
|
||||
|
||||
subjects.push({
|
||||
name: subjectName,
|
||||
grades: grades,
|
||||
average: average || 0,
|
||||
classAverage: classAvg || 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
|
||||
};
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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 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">
|
||||
<div class="grade-theme" title="${grade.theme}">${shortenedTheme}</div>
|
||||
<div class="grade-meta">${grade.type}</div>
|
||||
</div>
|
||||
<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]++;
|
||||
}
|
||||
});
|
||||
});
|
||||
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;
|
||||
|
||||
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>
|
||||
|
||||
<main class="kreta-main">
|
||||
<div class="grades-overview">
|
||||
<div class="overall-averages card">
|
||||
<div class="chart-header">
|
||||
<div class="chart-title">Jegyek (${totalGrades}db)</div>
|
||||
<div class="chart-averages">
|
||||
<div class="average-circle my-average" data-grade="${studentGradeLevel}">
|
||||
<span class="average-value ${studentAverage < 2 && studentAverage > 0 ? 'warning' : ''}">${studentAverage > 0 ? studentAverage.toFixed(2) : '-'}</span>
|
||||
</div>
|
||||
${classAverage > 0 ? `
|
||||
<div class="average-circle class-average" data-grade="${classGradeLevel}">
|
||||
<span class="average-value">${classAverage.toFixed(2)}</span>
|
||||
</div>
|
||||
` : ''}
|
||||
</div>
|
||||
</div>
|
||||
<div class="grades-chart">
|
||||
<canvas id="gradesChart"></canvas>
|
||||
</div>
|
||||
<div class="grade-distribution">
|
||||
${Object.entries(gradeDistribution)
|
||||
.map(([grade, count]) => `
|
||||
<div class="grade-count grade-${grade}">
|
||||
<span class="grade-value">${grade}</span>
|
||||
<span class="grade-amount">${count}</span>
|
||||
</div>
|
||||
`).join('')}
|
||||
</div>
|
||||
</div>
|
||||
${semesterGrades.length > 0 ? `
|
||||
<div class="semester-grades card">
|
||||
<h3>Félévi értékelések</h3>
|
||||
<div class="semester-grades-list">
|
||||
${semesterGrades.map(grade => `
|
||||
<div class="semester-grade-item grade-${grade.value}">
|
||||
<div class="semester-grade-value">${grade.value}</div>
|
||||
<div class="semester-grade-subject">${grade.subject}</div>
|
||||
</div>
|
||||
`).join('')}
|
||||
</div>
|
||||
</div>
|
||||
` : ''}
|
||||
</div>
|
||||
<div class="grades-grid">
|
||||
${generateSubjectCards(data.subjects)}
|
||||
</div>
|
||||
</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 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
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
allGrades.sort((a, b) => a.date - b.date);
|
||||
|
||||
|
||||
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;
|
||||
|
||||
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">
|
||||
<h3>${subject.name}</h3>
|
||||
</div>
|
||||
<div class="subject-averages">
|
||||
<div class="average-circle my-average ${subject.average < 2 && subject.average > 0 ? 'warning' : ''}" data-grade="${myGrade}">
|
||||
<span class="average-value">${subject.average > 0 ? subject.average.toFixed(2) : '-'}</span>
|
||||
</div>
|
||||
${subject.classAverage > 0 ? `
|
||||
<div class="average-circle class-average" data-grade="${classGrade}">
|
||||
<span class="average-value">${subject.classAverage.toFixed(2)}</span>
|
||||
</div>
|
||||
` : ''}
|
||||
</div>
|
||||
</div>
|
||||
<div class="grades-list">
|
||||
${regularGrades.map(generateGradeItem).join('')}
|
||||
</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);
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
if (window.location.href.includes('/TanuloErtekeles/Osztalyzatok')) {
|
||||
transformGradesPage();
|
||||
}
|
||||
})();
|
||||
527
homework/homework.css
Normal file
@@ -0,0 +1,527 @@
|
||||
@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;
|
||||
}
|
||||
|
||||
* {
|
||||
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", serif !important;
|
||||
min-height: 100vh;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
body {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
.kreta-container {
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.kreta-header {
|
||||
padding: clamp(1rem, 3vw, 2rem);
|
||||
display: grid;
|
||||
grid-template-columns: minmax(300px, 400px) 1fr minmax(200px, 300px);
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
@media (max-width: 1200px) {
|
||||
.kreta-header {
|
||||
grid-template-columns: minmax(250px, 350px) 1fr minmax(180px, 250px);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.kreta-header {
|
||||
grid-template-columns: 1fr auto;
|
||||
grid-template-areas:
|
||||
"school user"
|
||||
"nav nav";
|
||||
padding: 1rem;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.school-info {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.school-info {
|
||||
grid-area: school;
|
||||
max-width: none;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.logo-text {
|
||||
color: var(--text-primary);
|
||||
font-size: 24px;
|
||||
font-weight: 600;
|
||||
margin: 0 0 0.5rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.logo-text {
|
||||
margin: 0;
|
||||
font-size: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.logo {
|
||||
width: 24px;
|
||||
border-radius: 8px;
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
|
||||
.school-details {
|
||||
color: var(--text-secondary);
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.school-details span {
|
||||
display: block;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
max-width: 300px;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.school-details span {
|
||||
max-width: 200px;
|
||||
}
|
||||
|
||||
.school-details {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.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;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.user-profile {
|
||||
grid-area: user;
|
||||
}
|
||||
}
|
||||
|
||||
.user-dropdown-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
padding: 0.5rem;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.user-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
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;
|
||||
background: var(--card-card);
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
||||
min-width: 200px;
|
||||
display: none;
|
||||
z-index: 1000;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.user-dropdown.show {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.dropdown-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
padding: 0.75rem 1rem;
|
||||
color: var(--text-primary);
|
||||
text-decoration: none;
|
||||
transition: background-color 0.2s ease;
|
||||
}
|
||||
|
||||
.dropdown-item:hover {
|
||||
background-color: var(--accent-15);
|
||||
}
|
||||
|
||||
|
||||
.kreta-main {
|
||||
flex: 1;
|
||||
padding: clamp(1rem, 3vw, 2rem);
|
||||
max-width: 1400px;
|
||||
margin: 0 auto;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
||||
.filter-card {
|
||||
background: var(--card-card);
|
||||
border-radius: 24px;
|
||||
padding: 1.5rem;
|
||||
margin-bottom: 1.5rem;
|
||||
box-shadow: 0px 1px 3px 0px var(--accent-shadow);
|
||||
}
|
||||
|
||||
.filter-header {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.filter-header h2 {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: var(--text-primary);
|
||||
background-color: var(--card-card);
|
||||
}
|
||||
|
||||
.filter-content {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
|
||||
gap: 1rem;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.filter-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.filter-group label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
font-size: 14px;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.filter-group select,
|
||||
.filter-group input {
|
||||
padding: 0.75rem;
|
||||
border-radius: 12px;
|
||||
border: 1px solid var(--accent-15);
|
||||
background-color: var(--background);
|
||||
color: var(--text-primary);
|
||||
font-family: inherit;
|
||||
font-size: 14px;
|
||||
width: 100%;
|
||||
transition: border-color 0.2s ease, box-shadow 0.2s ease;
|
||||
}
|
||||
|
||||
.filter-group select:focus,
|
||||
.filter-group input:focus {
|
||||
outline: none;
|
||||
border-color: var(--accent-accent);
|
||||
box-shadow: 0 0 0 2px var(--accent-15);
|
||||
}
|
||||
|
||||
.filter-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 1rem;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.filter-button {
|
||||
padding: 0.5rem 1rem;
|
||||
border-radius: 8px;
|
||||
border: none;
|
||||
font-family: inherit;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.filter-button.primary {
|
||||
background-color: var(--accent-accent);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.filter-button.secondary {
|
||||
background-color: var(--accent-15);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.filter-button:hover {
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
|
||||
.homework-list {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.homework-date-group {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.date-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
margin-bottom: 0.5rem;
|
||||
padding-bottom: 0.5rem;
|
||||
border-bottom: 1px solid var(--accent-15);
|
||||
}
|
||||
|
||||
.date-header h3 {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.homework-item {
|
||||
background: var(--card-card);
|
||||
border-radius: 12px;
|
||||
padding: 1rem;
|
||||
margin-bottom: 0.5rem;
|
||||
box-shadow: 0px 1px 2px 0px var(--accent-shadow);
|
||||
transition: transform 0.2s ease;
|
||||
}
|
||||
|
||||
.homework-item:hover {
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.homework-item.due-tomorrow {
|
||||
border-left: 4px solid var(--accent-accent);
|
||||
background-color: var(--accent-5);
|
||||
}
|
||||
|
||||
.homework-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.homework-subject {
|
||||
font-weight: 600;
|
||||
font-size: 16px;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.homework-deadline {
|
||||
font-size: 14px;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.homework-deadline.urgent {
|
||||
color: var(--accent-accent);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.homework-content {
|
||||
margin-bottom: 0.5rem;
|
||||
color: var(--text-primary);
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.homework-footer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
font-size: 12px;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.homework-teacher {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
|
||||
.loading-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.7);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
.loading-container {
|
||||
background-color: var(--background);
|
||||
padding: 2rem;
|
||||
border-radius: 16px;
|
||||
text-align: center;
|
||||
max-width: 90%;
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
.loading-logo {
|
||||
width: 80px;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.loading-text {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
margin-bottom: 0.5rem;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.loading-text2 {
|
||||
font-size: 14px;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
|
||||
.empty-state {
|
||||
text-align: center;
|
||||
padding: 2rem;
|
||||
color: var(--text-secondary);
|
||||
display: none;
|
||||
}
|
||||
|
||||
.empty-state p {
|
||||
margin-bottom: 1rem;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.filter-content {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.homework-header {
|
||||
flex-direction: column;
|
||||
gap: 0.25rem;
|
||||
}
|
||||
}
|
||||
572
homework/homework.js
Normal file
@@ -0,0 +1,572 @@
|
||||
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 new Promise(resolve => setTimeout(resolve, 1000));
|
||||
|
||||
const basicData = {
|
||||
schoolInfo: {
|
||||
name: getCookie('schoolName') || 'Iskola',
|
||||
id: getCookie('schoolCode') || ''
|
||||
},
|
||||
userData: {
|
||||
name: getCookie('userName') || 'Felhasználó',
|
||||
time: document.querySelector('.usermenu_timer')?.textContent?.trim() || '45:00'
|
||||
}
|
||||
};
|
||||
|
||||
const homeworkItems = [];
|
||||
const rows = document.querySelectorAll('#TanulotHaziFeladatkGrid .k-grid-content tr');
|
||||
rows.forEach(row => {
|
||||
const cells = row.querySelectorAll('td');
|
||||
if (cells.length >= 7) {
|
||||
homeworkItems.push({
|
||||
subject: cells[3]?.textContent?.trim() || '',
|
||||
teacher: cells[4]?.textContent?.trim() || '',
|
||||
description: cells[5]?.textContent?.trim() || '',
|
||||
createdDate: cells[6]?.textContent?.trim() || '',
|
||||
deadline: cells[7]?.textContent?.trim() || ''
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
const groupedHomework = {};
|
||||
homeworkItems.forEach(homework => {
|
||||
|
||||
const deadlineDate = homework.deadline.split(' ').slice(0, 3).join(' ');
|
||||
if (!groupedHomework[deadlineDate]) {
|
||||
groupedHomework[deadlineDate] = [];
|
||||
}
|
||||
groupedHomework[deadlineDate].push(homework);
|
||||
});
|
||||
|
||||
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;
|
||||
|
||||
|
||||
const parts = dateStr.split('.');
|
||||
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 day = parseInt(parts[2].trim());
|
||||
|
||||
const homeworkDate = new Date(year, month, day);
|
||||
|
||||
|
||||
const tomorrow = new Date();
|
||||
tomorrow.setDate(tomorrow.getDate() + 1);
|
||||
tomorrow.setHours(0, 0, 0, 0);
|
||||
|
||||
|
||||
const dayAfterTomorrow = new Date(tomorrow);
|
||||
dayAfterTomorrow.setDate(dayAfterTomorrow.getDate() + 1);
|
||||
|
||||
|
||||
return homeworkDate >= tomorrow && homeworkDate < dayAfterTomorrow;
|
||||
}
|
||||
|
||||
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>
|
||||
|
||||
<main class="kreta-main">
|
||||
<div class="filter-card">
|
||||
<div class="filter-header">
|
||||
<h2>Szűrés</h2>
|
||||
</div>
|
||||
<div class="filter-content">
|
||||
<div class="filter-group">
|
||||
<label>
|
||||
<!--<span class="material-icons-round">subject</span>-->
|
||||
Tantárgy
|
||||
</label>
|
||||
<select id="subjectFilter">
|
||||
<option value="">Összes tantárgy</option>
|
||||
${[...new Set(homeworkItems.map(item => item.subject))]
|
||||
.sort()
|
||||
.map(subject => `<option value="${subject}">${subject}</option>`)
|
||||
.join('')}
|
||||
</select>
|
||||
</div>
|
||||
<div class="filter-group">
|
||||
<label>
|
||||
<!--<span class="material-icons-round">person</span>-->
|
||||
Tanár
|
||||
</label>
|
||||
<select id="teacherFilter">
|
||||
<option value="">Összes tanár</option>
|
||||
${[...new Set(homeworkItems.map(item => item.teacher))]
|
||||
.sort()
|
||||
.map(teacher => `<option value="${teacher}">${teacher}</option>`)
|
||||
.join('')}
|
||||
</select>
|
||||
</div>
|
||||
<div class="filter-group">
|
||||
<label>
|
||||
<!--<span class="material-icons-round">date_range</span>-->
|
||||
Határidő
|
||||
</label>
|
||||
<select id="deadlineFilter">
|
||||
<option value="">Összes határidő</option>
|
||||
<option value="tomorrow">Holnapi határidő</option>
|
||||
<option value="thisWeek">Ezen a héten</option>
|
||||
<option value="nextWeek">Jövő héten</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="homework-list" id="homeworkList">
|
||||
${renderHomeworkList(groupedHomework)}
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
`;
|
||||
|
||||
setupFilters(homeworkItems, groupedHomework);
|
||||
setupUserDropdown();
|
||||
setupLogoutTimer();
|
||||
hideLoadingScreen();
|
||||
}
|
||||
|
||||
function renderHomeworkList(groupedHomework) {
|
||||
|
||||
const sortedDates = Object.keys(groupedHomework).sort((a, b) => {
|
||||
const dateA = new Date(a.replace(/\./g, ''));
|
||||
const dateB = new Date(b.replace(/\./g, ''));
|
||||
return dateA - dateB;
|
||||
});
|
||||
|
||||
if (sortedDates.length === 0) {
|
||||
return `
|
||||
<div class="empty-state">
|
||||
<p>Nincs megjeleníthető házi feladat.</p>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
return sortedDates.map(date => {
|
||||
const homeworkItems = groupedHomework[date];
|
||||
return `
|
||||
<div class="homework-date-group" data-date="${date}">
|
||||
<div class="date-header">
|
||||
<h3>${formatDateHeader(date)}</h3>
|
||||
</div>
|
||||
${homeworkItems.map(homework => {
|
||||
const isTomorrowClass = isTomorrow(homework.deadline) ? 'due-tomorrow' : '';
|
||||
const urgentClass = isTomorrow(homework.deadline) ? 'urgent' : '';
|
||||
|
||||
return `
|
||||
<div class="homework-item ${isTomorrowClass}" data-subject="${homework.subject}" data-teacher="${homework.teacher}">
|
||||
<div class="homework-header">
|
||||
<div class="homework-subject">${homework.subject}</div>
|
||||
<div class="homework-deadline ${urgentClass}">${formatDeadline(homework.deadline)}</div>
|
||||
</div>
|
||||
<div class="homework-content">${formatHomeworkDescription(homework.description)}</div>
|
||||
<div class="homework-footer">
|
||||
<div class="homework-teacher">${homework.teacher}</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}).join('')}
|
||||
</div>
|
||||
`;
|
||||
}).join('');
|
||||
}
|
||||
|
||||
function formatDateHeader(dateStr) {
|
||||
if (!dateStr) return '';
|
||||
|
||||
const today = new Date();
|
||||
today.setHours(0, 0, 0, 0);
|
||||
|
||||
const tomorrow = new Date(today);
|
||||
tomorrow.setDate(tomorrow.getDate() + 1);
|
||||
|
||||
const parts = dateStr.split('.');
|
||||
if (parts.length < 3) return dateStr;
|
||||
|
||||
const year = parseInt(parts[0].trim());
|
||||
const month = parseInt(parts[1].trim()) - 1;
|
||||
const day = parseInt(parts[2].trim());
|
||||
|
||||
const date = new Date(year, month, day);
|
||||
|
||||
|
||||
if (date.toDateString() === today.toDateString()) {
|
||||
return 'Ma - ' + dateStr;
|
||||
} else if (date.toDateString() === tomorrow.toDateString()) {
|
||||
return 'Holnap - ' + dateStr;
|
||||
}
|
||||
|
||||
|
||||
const weekdays = ['Vasárnap', 'Hétfő', 'Kedd', 'Szerda', 'Csütörtök', 'Péntek', 'Szombat'];
|
||||
return `${weekdays[date.getDay()]} - ${dateStr}`;
|
||||
}
|
||||
|
||||
function formatDeadline(dateStr) {
|
||||
if (!dateStr) return '';
|
||||
|
||||
|
||||
if (isTomorrow(dateStr)) {
|
||||
return `Határidő: ${dateStr} (holnap!)`;
|
||||
}
|
||||
|
||||
return `Határidő: ${dateStr}`;
|
||||
}
|
||||
|
||||
function formatDate(dateStr) {
|
||||
if (!dateStr) return '';
|
||||
return dateStr;
|
||||
}
|
||||
|
||||
function formatHomeworkDescription(description) {
|
||||
if (!description) return '';
|
||||
|
||||
|
||||
description = description.replace(/(\d+\.)\s*(\w[^\n.]*)/g, '<strong>$1 $2</strong>');
|
||||
|
||||
|
||||
description = description.replace(/(Határidő:)\s*([^\n]+)/g, '<div class="homework-requirement"><span class="requirement-label">$1</span> $2</div>');
|
||||
description = description.replace(/(MS\s+[^\n.]+szerint\s+adható\s+be\.)/g, '<div class="homework-requirement"><span class="requirement-label">Beadás:</span> $1</div>');
|
||||
|
||||
|
||||
description = description.replace(/\n/g, '<br>');
|
||||
|
||||
return description;
|
||||
}
|
||||
|
||||
function setupFilters(homeworkItems, groupedHomework) {
|
||||
const subjectFilter = document.getElementById('subjectFilter');
|
||||
const teacherFilter = document.getElementById('teacherFilter');
|
||||
const deadlineFilter = document.getElementById('deadlineFilter');
|
||||
const applyFilterBtn = document.getElementById('applyFilterBtn');
|
||||
const resetFilterBtn = document.getElementById('resetFilterBtn');
|
||||
|
||||
|
||||
const applyFilters = () => {
|
||||
const selectedSubject = subjectFilter.value;
|
||||
const selectedTeacher = teacherFilter.value;
|
||||
const selectedDeadline = deadlineFilter.value;
|
||||
|
||||
|
||||
const homeworkElements = document.querySelectorAll('.homework-item');
|
||||
const dateGroups = document.querySelectorAll('.homework-date-group');
|
||||
|
||||
|
||||
dateGroups.forEach(group => {
|
||||
group.style.display = 'none';
|
||||
});
|
||||
|
||||
|
||||
homeworkElements.forEach(item => {
|
||||
const subject = item.getAttribute('data-subject');
|
||||
const teacher = item.getAttribute('data-teacher');
|
||||
const dateGroup = item.closest('.homework-date-group');
|
||||
const dateStr = dateGroup.getAttribute('data-date');
|
||||
|
||||
let showItem = true;
|
||||
|
||||
|
||||
if (selectedSubject && subject !== selectedSubject) {
|
||||
showItem = false;
|
||||
}
|
||||
|
||||
|
||||
if (selectedTeacher && teacher !== selectedTeacher) {
|
||||
showItem = false;
|
||||
}
|
||||
|
||||
|
||||
if (selectedDeadline) {
|
||||
const parts = dateStr.split('.');
|
||||
if (parts.length >= 3) {
|
||||
const year = parseInt(parts[0].trim());
|
||||
const month = parseInt(parts[1].trim()) - 1;
|
||||
const day = parseInt(parts[2].trim());
|
||||
const date = new Date(year, month, day);
|
||||
|
||||
const today = new Date();
|
||||
today.setHours(0, 0, 0, 0);
|
||||
|
||||
const tomorrow = new Date(today);
|
||||
tomorrow.setDate(tomorrow.getDate() + 1);
|
||||
|
||||
|
||||
const startOfWeek = new Date(today);
|
||||
const dayOfWeek = today.getDay() || 7; // Convert Sunday from 0 to 7
|
||||
startOfWeek.setDate(today.getDate() - dayOfWeek + 1); // Monday
|
||||
|
||||
const endOfWeek = new Date(startOfWeek);
|
||||
endOfWeek.setDate(startOfWeek.getDate() + 6); // Sunday
|
||||
|
||||
|
||||
const startOfNextWeek = new Date(endOfWeek);
|
||||
startOfNextWeek.setDate(endOfWeek.getDate() + 1);
|
||||
|
||||
const endOfNextWeek = new Date(startOfNextWeek);
|
||||
endOfNextWeek.setDate(startOfNextWeek.getDate() + 6);
|
||||
|
||||
if (selectedDeadline === 'tomorrow' && date.toDateString() !== tomorrow.toDateString()) {
|
||||
showItem = false;
|
||||
} else if (selectedDeadline === 'thisWeek' && (date < startOfWeek || date > endOfWeek)) {
|
||||
showItem = false;
|
||||
} else if (selectedDeadline === 'nextWeek' && (date < startOfNextWeek || date > endOfNextWeek)) {
|
||||
showItem = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
item.style.display = showItem ? 'block' : 'none';
|
||||
|
||||
|
||||
if (showItem) {
|
||||
dateGroup.style.display = 'block';
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
const visibleItems = document.querySelectorAll('.homework-item[style="display: block"]');
|
||||
const homeworkList = document.getElementById('homeworkList');
|
||||
|
||||
|
||||
let emptyState = homeworkList.querySelector('.empty-state');
|
||||
if (!emptyState) {
|
||||
emptyState = document.createElement('div');
|
||||
emptyState.className = 'empty-state';
|
||||
emptyState.innerHTML = '<p>Nincs a szűrési feltételeknek megfelelő házi feladat.</p>';
|
||||
homeworkList.appendChild(emptyState);
|
||||
}
|
||||
|
||||
|
||||
if (visibleItems.length === 0) {
|
||||
emptyState.style.display = 'block';
|
||||
} else {
|
||||
emptyState.style.display = 'none';
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const resetFilters = () => {
|
||||
subjectFilter.value = '';
|
||||
teacherFilter.value = '';
|
||||
deadlineFilter.value = '';
|
||||
|
||||
|
||||
document.querySelectorAll('.homework-item').forEach(item => {
|
||||
item.style.display = 'block';
|
||||
});
|
||||
|
||||
document.querySelectorAll('.homework-date-group').forEach(group => {
|
||||
group.style.display = 'block';
|
||||
});
|
||||
|
||||
|
||||
const homeworkList = document.getElementById('homeworkList');
|
||||
const existingEmptyState = homeworkList.querySelector('.empty-state');
|
||||
if (existingEmptyState) {
|
||||
homeworkList.removeChild(existingEmptyState);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
subjectFilter.addEventListener('change', applyFilters);
|
||||
teacherFilter.addEventListener('change', applyFilters);
|
||||
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')) {
|
||||
transformHomeworkPage().catch(error => {
|
||||
console.error('Error transforming homework page:', error);
|
||||
});
|
||||
}
|
||||
1
icons/absences-active.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 24 24"><path fill="#A7DC22" d="M8 3a1 1 0 0 1 1-1h6a1 1 0 1 1 0 2H9a1 1 0 0 1-1-1M3 14a9 9 0 0 1 14.618-7.032l.675-.675a1 1 0 1 1 1.414 1.414l-.675.675A9 9 0 1 1 3 14m10-4a1 1 0 1 0-2 0v4a1 1 0 1 0 2 0z" clip-rule="evenodd"/></svg>
|
||||
|
After Width: | Height: | Size: 309 B |
5
icons/absences-inactive.svg
Normal file
@@ -0,0 +1,5 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="none">
|
||||
<g opacity="0.5">
|
||||
<path d="M15.8334 5.83333L14.7143 6.9525M14.7143 6.9525C13.464 5.70223 11.7682 4.99983 10.0001 4.99983C8.23193 4.99983 6.5362 5.70223 5.28592 6.9525C4.03565 8.20278 3.33325 9.89851 3.33325 11.6667C3.33325 13.4348 4.03565 15.1306 5.28592 16.3808C6.5362 17.6311 8.23193 18.3335 10.0001 18.3335C11.7682 18.3335 13.464 17.6311 14.7143 16.3808C15.9645 15.1306 16.6669 13.4348 16.6669 11.6667C16.6669 9.89851 15.9645 8.20278 14.7143 6.9525ZM10.0001 8.33333V11.6667M7.50009 2.5H12.5001" stroke="#6E8F1B" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 696 B |
1
icons/close.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 12L7 7m5 5l5 5m-5-5l5-5m-5 5l-5 5"/></svg>
|
||||
|
After Width: | Height: | Size: 238 B |
3
icons/dashboard-active.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="none">
|
||||
<path d="M16.6666 15.8333V8.74999C16.6666 8.62062 16.6365 8.49302 16.5786 8.37731C16.5208 8.2616 16.4367 8.16095 16.3333 8.08332L10.4999 3.70832C10.3557 3.60014 10.1802 3.54166 9.99992 3.54166C9.81961 3.54166 9.64417 3.60014 9.49992 3.70832L3.66659 8.08332C3.56309 8.16095 3.47909 8.2616 3.42123 8.37731C3.36337 8.49302 3.33325 8.62062 3.33325 8.74999V15.8333C3.33325 16.0543 3.42105 16.2663 3.57733 16.4226C3.73361 16.5789 3.94557 16.6667 4.16659 16.6667H7.49992C7.72093 16.6667 7.93289 16.5789 8.08917 16.4226C8.24545 16.2663 8.33325 16.0543 8.33325 15.8333V13.3333C8.33325 13.1123 8.42105 12.9003 8.57733 12.7441C8.73361 12.5878 8.94557 12.5 9.16658 12.5H10.8333C11.0543 12.5 11.2662 12.5878 11.4225 12.7441C11.5788 12.9003 11.6666 13.1123 11.6666 13.3333V15.8333C11.6666 16.0543 11.7544 16.2663 11.9107 16.4226C12.0669 16.5789 12.2789 16.6667 12.4999 16.6667H15.8333C16.0543 16.6667 16.2662 16.5789 16.4225 16.4226C16.5788 16.2663 16.6666 16.0543 16.6666 15.8333Z" fill="#A7DC22" stroke="#A7DC22" stroke-width="1.66667" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
5
icons/dashboard-inactive.svg
Normal file
@@ -0,0 +1,5 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="none">
|
||||
<g opacity="0.5">
|
||||
<path d="M16.6668 15.8333V8.74999C16.6668 8.62062 16.6367 8.49302 16.5789 8.37731C16.521 8.2616 16.437 8.16095 16.3335 8.08332L10.5002 3.70832C10.3559 3.60014 10.1805 3.54166 10.0002 3.54166C9.81985 3.54166 9.64441 3.60014 9.50016 3.70832L3.66683 8.08332C3.56333 8.16095 3.47933 8.2616 3.42147 8.37731C3.36362 8.49302 3.3335 8.62062 3.3335 8.74999V15.8333C3.3335 16.0543 3.42129 16.2663 3.57757 16.4226C3.73385 16.5789 3.94582 16.6667 4.16683 16.6667H7.50016C7.72118 16.6667 7.93314 16.5789 8.08942 16.4226C8.2457 16.2663 8.3335 16.0543 8.3335 15.8333V13.3333C8.3335 13.1123 8.42129 12.9003 8.57757 12.7441C8.73385 12.5878 8.94582 12.5 9.16683 12.5H10.8335C11.0545 12.5 11.2665 12.5878 11.4228 12.7441C11.579 12.9003 11.6668 13.1123 11.6668 13.3333V15.8333C11.6668 16.0543 11.7546 16.2663 11.9109 16.4226C12.0672 16.5789 12.2791 16.6667 12.5002 16.6667H15.8335C16.0545 16.6667 16.2665 16.5789 16.4228 16.4226C16.579 16.2663 16.6668 16.0543 16.6668 15.8333Z" stroke="#6E8F1B" stroke-width="1.66667" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
5
icons/dkt.svg
Normal file
@@ -0,0 +1,5 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="30" height="23" viewBox="0 0 30 23" fill="none">
|
||||
<path d="M11 12.8333C13.9455 12.8333 16.3333 10.4455 16.3333 7.49996C16.3333 4.55444 13.9455 2.16663 11 2.16663C8.05444 2.16663 5.66663 4.55444 5.66663 7.49996C5.66663 10.4455 8.05444 12.8333 11 12.8333Z" fill="#FFA046" stroke="#FFA046" stroke-width="2.66667" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M11 12.8333C5.84529 12.8333 1.66663 16.4146 1.66663 20.8333H20.3333C20.3333 16.4146 16.1546 12.8333 11 12.8333Z" fill="#FFA046" stroke="#FFA046" stroke-width="2.66667" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M19 12.8333C19.8912 12.8332 20.7681 12.6099 21.5508 12.1836C22.3334 11.7573 22.9967 11.1417 23.4801 10.3931C23.9636 9.64441 24.2517 8.78654 24.3182 7.89785C24.3847 7.00915 24.2274 6.11796 23.8607 5.30569C23.4941 4.49343 22.9297 3.786 22.2193 3.24802C21.5088 2.71005 20.6748 2.35869 19.7935 2.22604C18.9123 2.09339 18.0118 2.18369 17.1745 2.48867C16.3371 2.79366 15.5895 3.30362 15 3.97196M19 12.8333C17.924 12.8333 16.196 12.4426 15 11.1866M19 12.8333C24.1547 12.8333 28.3333 16.4146 28.3333 20.8333H20.3333" stroke="#FFA046" stroke-width="2.66667" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
1
icons/eye-off.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 6.362A9.7 9.7 0 0 1 12 5c6.307 0 9.367 5.683 9.91 6.808c.06.123.06.261 0 .385c-.352.728-1.756 3.362-4.41 5.131M14 18.8a10 10 0 0 1-2 .2c-6.307 0-9.367-5.683-9.91-6.808a.44.44 0 0 1 0-.386c.219-.452.84-1.632 1.91-2.885m6 .843A3 3 0 0 1 14.236 14M3 3l18 18"/></svg>
|
||||
|
After Width: | Height: | Size: 458 B |
1
icons/eye-on.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 24 24"><g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><path d="M12 5c-6.307 0-9.367 5.683-9.91 6.808a.44.44 0 0 0 0 .384C2.632 13.317 5.692 19 12 19s9.367-5.683 9.91-6.808a.44.44 0 0 0 0-.384C21.368 10.683 18.308 5 12 5"/><circle cx="12" cy="12" r="3"/></g></svg>
|
||||
|
After Width: | Height: | Size: 395 B |
3
icons/grades-active.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="none">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.8335 1.66666C5.17045 1.66666 4.53457 1.93005 4.06573 2.39889C3.59689 2.86773 3.3335 3.50362 3.3335 4.16666V16.7817C3.33342 17.0006 3.39087 17.2158 3.50008 17.4056C3.6093 17.5953 3.76645 17.7531 3.95582 17.8631C4.14518 17.973 4.3601 18.0313 4.57906 18.0321C4.79803 18.0329 5.01336 17.9761 5.2035 17.8675L9.58683 15.3625C9.71272 15.2906 9.85519 15.2528 10.0002 15.2528C10.1451 15.2528 10.2876 15.2906 10.4135 15.3625L14.7968 17.8675C14.987 17.9761 15.2023 18.0329 15.4213 18.0321C15.6402 18.0313 15.8552 17.973 16.0445 17.8631C16.2339 17.7531 16.391 17.5953 16.5002 17.4056C16.6095 17.2158 16.6669 17.0006 16.6668 16.7817V4.16666C16.6668 3.50362 16.4034 2.86773 15.9346 2.39889C15.4658 1.93005 14.8299 1.66666 14.1668 1.66666H5.8335Z" fill="#A7DC22"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 906 B |
5
icons/grades-inactive.svg
Normal file
@@ -0,0 +1,5 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="none">
|
||||
<g opacity="0.5">
|
||||
<path d="M14.1667 2.5H5.83341C5.39139 2.5 4.96746 2.67559 4.6549 2.98816C4.34234 3.30072 4.16675 3.72464 4.16675 4.16667V16.7817C4.16677 16.8546 4.18596 16.9263 4.22238 16.9895C4.25881 17.0528 4.3112 17.1053 4.37431 17.1419C4.43742 17.1785 4.50904 17.198 4.58201 17.1982C4.65497 17.1984 4.72672 17.1795 4.79008 17.1433L9.17342 14.6392C9.42519 14.4953 9.71013 14.4197 10.0001 14.4197C10.29 14.4197 10.575 14.4953 10.8267 14.6392L15.2101 17.1442C15.2735 17.1804 15.3453 17.1993 15.4184 17.199C15.4914 17.1987 15.5631 17.1793 15.6262 17.1426C15.6894 17.1058 15.7417 17.0532 15.7781 16.9898C15.8145 16.9265 15.8335 16.8547 15.8334 16.7817V4.16667C15.8334 3.72464 15.6578 3.30072 15.3453 2.98816C15.0327 2.67559 14.6088 2.5 14.1667 2.5Z" stroke="#6E8F1B" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 949 B |
4
icons/logout.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewBox="0 0 28 28" fill="none">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M11.5174 0.419898C12.1146 0.240744 12.7454 0.203682 13.3595 0.311674C13.9736 0.419665 14.5539 0.669717 15.0542 1.04187C15.5544 1.41403 15.9608 1.89798 16.2407 2.45509C16.5207 3.0122 16.6666 3.62706 16.6667 4.25057V23.7492C16.6666 24.3727 16.5207 24.9876 16.2407 25.5447C15.9608 26.1018 15.5544 26.5858 15.0542 26.9579C14.5539 27.3301 13.9736 27.5801 13.3595 27.6881C12.7454 27.7961 12.1146 27.7591 11.5174 27.5799L3.51735 25.1799C2.69349 24.9328 1.97123 24.4266 1.45773 23.7366C0.944226 23.0466 0.666828 22.2094 0.666687 21.3492V6.65057C0.666828 5.79043 0.944226 4.95325 1.45773 4.26321C1.97123 3.57318 2.69349 3.06704 3.51735 2.8199L11.5174 0.419898ZM18 3.33323C18 2.97961 18.1405 2.64047 18.3905 2.39042C18.6406 2.14037 18.9797 1.9999 19.3334 1.9999H23.3334C24.3942 1.9999 25.4116 2.42133 26.1618 3.17147C26.9119 3.92162 27.3334 4.93903 27.3334 5.9999V7.33323C27.3334 7.68685 27.1929 8.02599 26.9428 8.27604C26.6928 8.52609 26.3536 8.66656 26 8.66656C25.6464 8.66656 25.3073 8.52609 25.0572 8.27604C24.8072 8.02599 24.6667 7.68685 24.6667 7.33323V5.9999C24.6667 5.64628 24.5262 5.30714 24.2762 5.05709C24.0261 4.80704 23.687 4.66656 23.3334 4.66656H19.3334C18.9797 4.66656 18.6406 4.52609 18.3905 4.27604C18.1405 4.02599 18 3.68685 18 3.33323ZM26 19.3332C26.3536 19.3332 26.6928 19.4737 26.9428 19.7238C27.1929 19.9738 27.3334 20.3129 27.3334 20.6666V21.9999C27.3334 23.0608 26.9119 24.0782 26.1618 24.8283C25.4116 25.5785 24.3942 25.9999 23.3334 25.9999H19.3334C18.9797 25.9999 18.6406 25.8594 18.3905 25.6094C18.1405 25.3593 18 25.0202 18 24.6666C18 24.3129 18.1405 23.9738 18.3905 23.7238C18.6406 23.4737 18.9797 23.3332 19.3334 23.3332H23.3334C23.687 23.3332 24.0261 23.1928 24.2762 22.9427C24.5262 22.6927 24.6667 22.3535 24.6667 21.9999V20.6666C24.6667 20.3129 24.8072 19.9738 25.0572 19.7238C25.3073 19.4737 25.6464 19.3332 26 19.3332ZM10 12.6666C9.6464 12.6666 9.30726 12.807 9.05721 13.0571C8.80716 13.3071 8.66669 13.6463 8.66669 13.9999C8.66669 14.3535 8.80716 14.6927 9.05721 14.9427C9.30726 15.1928 9.6464 15.3332 10 15.3332H10.0014C10.355 15.3332 10.6941 15.1928 10.9442 14.9427C11.1942 14.6927 11.3347 14.3535 11.3347 13.9999C11.3347 13.6463 11.1942 13.3071 10.9442 13.0571C10.6941 12.807 10.355 12.6666 10.0014 12.6666H10Z" fill="#FF54A1"/>
|
||||
<path d="M19.3334 13.9999H26M26 13.9999L23.3334 11.3333M26 13.9999L23.3334 16.6666" stroke="#FF54A1" stroke-width="2.66667" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.5 KiB |
3
icons/naplo.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32" fill="none">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M4 6.66663C4 5.60576 4.42143 4.58834 5.17157 3.8382C5.92172 3.08805 6.93913 2.66663 8 2.66663H24C25.0609 2.66663 26.0783 3.08805 26.8284 3.8382C27.5786 4.58834 28 5.60576 28 6.66663V25.3333C28 26.3942 27.5786 27.4116 26.8284 28.1617C26.0783 28.9119 25.0609 29.3333 24 29.3333H8C6.93913 29.3333 5.92172 28.9119 5.17157 28.1617C4.42143 27.4116 4 26.3942 4 25.3333V6.66663ZM10.6667 6.66663V16L13.724 12.9426C13.974 12.6927 14.3131 12.5522 14.6667 12.5522C15.0202 12.5522 15.3593 12.6927 15.6093 12.9426L18.6667 16V6.66663C18.6667 6.313 18.5262 5.97387 18.2761 5.72382C18.0261 5.47377 17.687 5.33329 17.3333 5.33329H12C11.6464 5.33329 11.3072 5.47377 11.0572 5.72382C10.8071 5.97387 10.6667 6.313 10.6667 6.66663Z" fill="#A7DC22"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 881 B |
1
icons/open-link.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 24 24"><g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><circle cx="12" cy="12" r="9"/><path d="m11 9l3 3l-3 3"/></g></svg>
|
||||
|
After Width: | Height: | Size: 253 B |
5
icons/others.svg
Normal file
@@ -0,0 +1,5 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="none">
|
||||
<g opacity="0.5">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M1.66699 5.00018C1.66699 4.34271 2.19998 3.80972 2.85745 3.80972H17.1429C17.8004 3.80972 18.3334 4.34271 18.3334 5.00018C18.3334 5.65765 17.8004 6.19064 17.1429 6.19064H2.85745C2.19998 6.19064 1.66699 5.65765 1.66699 5.00018ZM1.66699 9.76201C1.66699 9.10454 2.19998 8.57155 2.85745 8.57155H17.1429C17.8004 8.57155 18.3334 9.10454 18.3334 9.76201C18.3334 10.4195 17.8004 10.9525 17.1429 10.9525H2.85745C2.19998 10.9525 1.66699 10.4195 1.66699 9.76201ZM1.66699 14.5238C1.66699 13.8664 2.19998 13.3334 2.85745 13.3334H17.1429C17.8004 13.3334 18.3334 13.8664 18.3334 14.5238C18.3334 15.1813 17.8004 15.7143 17.1429 15.7143H2.85745C2.19998 15.7143 1.66699 15.1813 1.66699 14.5238Z" fill="#6E8F1B"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 876 B |
1
icons/profile.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewBox="0 0 28 28" fill="none"><g fill-rule="evenodd" clip-rule="evenodd" fill="#A7DC22" stroke="#A7DC22" stroke-width="1.66667" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="8" r="5" fill="#A7DC22"/><path d="M20 21a8 8 0 1 0-16 0"/></g></svg>
|
||||
|
After Width: | Height: | Size: 328 B |
1
icons/settings.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewBox="0 0 28 28" fill="none"><path fill="#A7DC22" fill-rule="evenodd" d="M9.024 2.783A1 1 0 0 1 10 2h4a1 1 0 0 1 .976.783l.44 1.981q.6.285 1.14.66l1.938-.61a1 1 0 0 1 1.166.454l2 3.464a1 1 0 0 1-.19 1.237l-1.497 1.373a8 8 0 0 1 0 1.316l1.497 1.373a1 1 0 0 1 .19 1.237l-2 3.464a1 1 0 0 1-1.166.454l-1.937-.61q-.54.375-1.14.66l-.44 1.98A1 1 0 0 1 14 22h-4a1 1 0 0 1-.976-.783l-.44-1.981q-.6-.285-1.14-.66l-1.938.61a1 1 0 0 1-1.166-.454l-2-3.464a1 1 0 0 1 .19-1.237l1.497-1.373a8 8 0 0 1 0-1.316L2.53 9.97a1 1 0 0 1-.19-1.237l2-3.464a1 1 0 0 1 1.166-.454l1.937.61q.54-.375 1.14-.66l.44-1.98zM12 15a3 3 0 1 0 0-6a3 3 0 0 0 0 6" clip-rule="evenodd"/></svg>
|
||||
|
After Width: | Height: | Size: 717 B |
4
icons/timetable-active.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="18" viewBox="0 0 16 18" fill="none">
|
||||
<path d="M1.3335 4.83332V6.49999H14.6668V4.83332C14.6668 4.3913 14.4912 3.96737 14.1787 3.65481C13.8661 3.34225 13.4422 3.16666 13.0002 3.16666H3.00016C2.55814 3.16666 2.13421 3.34225 1.82165 3.65481C1.50909 3.96737 1.3335 4.3913 1.3335 4.83332Z" fill="#A7DC22"/>
|
||||
<path d="M11.3335 3.16667H13.0002C13.4422 3.16667 13.8661 3.34226 14.1787 3.65482C14.4912 3.96738 14.6668 4.39131 14.6668 4.83333V6.5H1.3335V4.83333C1.3335 4.39131 1.50909 3.96738 1.82165 3.65482C2.13421 3.34226 2.55814 3.16667 3.00016 3.16667H4.66683M11.3335 3.16667V1.5M11.3335 3.16667H4.66683M4.66683 3.16667V1.5M1.3335 6.91667V14.8333C1.3335 15.2754 1.50909 15.6993 1.82165 16.0118C2.13421 16.3244 2.55814 16.5 3.00016 16.5H13.0002C13.4422 16.5 13.8661 16.3244 14.1787 16.0118C14.4912 15.6993 14.6668 15.2754 14.6668 14.8333V6.91667" stroke="#A7DC22" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 991 B |
5
icons/timetable-inactive.svg
Normal file
@@ -0,0 +1,5 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="none">
|
||||
<g opacity="0.5">
|
||||
<path d="M3.33325 7.5V15.8333C3.33325 16.2754 3.50885 16.6993 3.82141 17.0118C4.13397 17.3244 4.55789 17.5 4.99992 17.5H14.9999C15.4419 17.5 15.8659 17.3244 16.1784 17.0118C16.491 16.6993 16.6666 16.2754 16.6666 15.8333V7.5M3.33325 7.5V5.83333C3.33325 5.39131 3.50885 4.96738 3.82141 4.65482C4.13397 4.34226 4.55789 4.16667 4.99992 4.16667H6.66659M3.33325 7.5H16.6666M16.6666 7.5V5.83333C16.6666 5.39131 16.491 4.96738 16.1784 4.65482C15.8659 4.34226 15.4419 4.16667 14.9999 4.16667H13.3333M6.66659 4.16667H13.3333M6.66659 4.16667V2.5M13.3333 4.16667V2.5" stroke="#6E8F1B" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 772 B |
BIN
images/firka_logo.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
images/firka_logo_128.png
Normal file
|
After Width: | Height: | Size: 9.8 KiB |
BIN
images/loading.gif
Normal file
|
After Width: | Height: | Size: 16 KiB |
385
login/login.css
Normal file
@@ -0,0 +1,385 @@
|
||||
@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;
|
||||
}
|
||||
|
||||
.school-name {
|
||||
color: var(--text-secondary);
|
||||
text-align: center;
|
||||
font-family: Figtree;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
line-height: 130%;
|
||||
}
|
||||
|
||||
.school-details {
|
||||
color: var(--text-secondary);
|
||||
text-align: center;
|
||||
font-family: Figtree;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
line-height: 130%;
|
||||
}
|
||||
|
||||
.login-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-actions {
|
||||
margin-top: 24px;
|
||||
}
|
||||
|
||||
.help-links {
|
||||
margin-top: 16px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.help-link {
|
||||
color: var(--text-primary);
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
text-decoration: none;
|
||||
transition: color 0.2s ease;
|
||||
}
|
||||
|
||||
.help-link:hover {
|
||||
color: var(--text-teritary);
|
||||
}
|
||||
|
||||
.btn-login {
|
||||
width: 100%;
|
||||
padding: 12px;
|
||||
background: var(--accent-accent);
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 12px;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
font-family: "Montserrat", serif;
|
||||
cursor: pointer;
|
||||
transition: background 0.2s ease;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.btn-login:hover {
|
||||
background: var(--text-teritary);
|
||||
}
|
||||
|
||||
.btn-login:disabled {
|
||||
opacity: 0.7;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.btn-text {
|
||||
color: var(--text-primary);
|
||||
text-align: center;
|
||||
font-family: Montserrat;
|
||||
font-size: 18px;
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
line-height: normal;
|
||||
letter-spacing: -0.3px;
|
||||
}
|
||||
|
||||
.system-message {
|
||||
display: flex;
|
||||
padding: 20px;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
align-self: stretch;
|
||||
border-radius: 24px;
|
||||
background: var(--card-card);
|
||||
box-shadow: 0px 1px var(--shadow-blur) 0px var(--accent-shadow);
|
||||
}
|
||||
|
||||
.system-message h4 {
|
||||
color: var(--text-primary);
|
||||
text-align: center;
|
||||
font-family: Montserrat;
|
||||
font-size: 20px;
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
.system-message p {
|
||||
color: var(--text-secondary);
|
||||
text-align: center;
|
||||
font-family: Figtree;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
line-height: 130%;
|
||||
}
|
||||
|
||||
.login-footer {
|
||||
align-self: stretch;
|
||||
color: var(--text-secondary);
|
||||
text-align: center;
|
||||
font-family: Figtree;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
line-height: 130%;
|
||||
}
|
||||
|
||||
.privacy-link {
|
||||
align-self: stretch;
|
||||
color: var(--text-secondary);
|
||||
text-align: center;
|
||||
font-family: Figtree;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
line-height: 130%;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.privacy-link:hover {
|
||||
color: var(--text-teritary);
|
||||
}
|
||||
|
||||
|
||||
.form-control.error {
|
||||
border-color: var(--error-accent) !important;
|
||||
background: var(--error-card) !important;
|
||||
}
|
||||
|
||||
.error-message {
|
||||
color: var(--error-text);
|
||||
font-size: 14px;
|
||||
margin-top: 4px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.error-message.show {
|
||||
display: block;
|
||||
animation: fadeIn 0.2s ease;
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from { opacity: 0; transform: translateY(-4px); }
|
||||
to { opacity: 1; transform: translateY(0); }
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
to { transform: translate(-50%, -50%) rotate(360deg); }
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.login-container {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.login-card {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.card-header {
|
||||
margin-bottom: 20px;
|
||||
padding-bottom: 16px;
|
||||
}
|
||||
|
||||
.logo-text {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.school-name {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.school-details {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.form-control {
|
||||
height: 44px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.btn-login {
|
||||
padding: 10px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.help-link {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
201
login/login.js
Normal file
@@ -0,0 +1,201 @@
|
||||
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 || ''
|
||||
};
|
||||
|
||||
|
||||
const titleElement = document.querySelector('.page-title');
|
||||
const schoolInfo = {
|
||||
name: titleElement?.querySelector('b')?.textContent?.trim() || '',
|
||||
kretaId: '',
|
||||
omCode: ''
|
||||
};
|
||||
|
||||
|
||||
const spanElement = titleElement?.querySelector('span');
|
||||
if (spanElement) {
|
||||
const lines = spanElement.textContent?.split('\n').map(line => line.trim()) || [];
|
||||
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">
|
||||
<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="school-name">${schoolInfo.name}</h1>
|
||||
<div class="school-details">
|
||||
${schoolInfo.kretaId ? `<div>${schoolInfo.kretaId}</div>` : ''}
|
||||
${schoolInfo.omCode ? `<div>KRÉTA azonosító: ${schoolInfo.omCode}</div>` : ''}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form class="login-form" method="post" action="${formData.action}" id="loginForm" novalidate>
|
||||
<input type="hidden" id="ReturnUrl" name="ReturnUrl" value="${formData.returnUrl}">
|
||||
<input type="hidden" id="instituteCode" name="InstituteCode" value="${formData.instituteCode}">
|
||||
<input type="hidden" id="IsTemporaryLogin" name="IsTemporaryLogin" value="False">
|
||||
<input type="hidden" id="loginType" name="loginType" value="InstituteLogin">
|
||||
<input name="__RequestVerificationToken" type="hidden" value="${formData.requestToken}">
|
||||
|
||||
<div class="form-group">
|
||||
<input class="form-control" type="text" id="UserName" name="UserName"
|
||||
placeholder="Felhasználónév" maxlength="256" autocomplete="username" required>
|
||||
<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>
|
||||
<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 a jelszavad.</div>
|
||||
</div>
|
||||
|
||||
<div class="form-actions">
|
||||
<button type="submit" class="btn-login">
|
||||
<span class="spinner"></span>
|
||||
<span class="btn-text">Bejelentkezés</span>
|
||||
</button>
|
||||
<div class="help-links">
|
||||
<a href="https://${schoolInfo.omCode ? `${schoolInfo.omCode}` : ''}.e-kreta.hu/Adminisztracio/ElfelejtettJelszo" class="help-link">Elfelejtettem a jelszavam</a>
|
||||
<a href="https://tudasbazis.ekreta.hu/pages/viewpage.action?pageId=2425086" target="_blank" class="help-link">Nem tudsz bejelentkezni?</a>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
${systemMessage ? `
|
||||
<div class="system-message">
|
||||
<h4>Rendszerértesítés</h4>
|
||||
<p>${systemMessage}</p>
|
||||
</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;
|
||||
|
||||
|
||||
setupEventListeners();
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error transforming page:', error);
|
||||
}
|
||||
}
|
||||
|
||||
function setupEventListeners() {
|
||||
const loginForm = document.getElementById('loginForm');
|
||||
const passwordInput = document.getElementById('Password');
|
||||
const togglePasswordBtn = document.querySelector('.show-password');
|
||||
const formInputs = document.querySelectorAll('.form-control');
|
||||
|
||||
|
||||
if (togglePasswordBtn && passwordInput) {
|
||||
togglePasswordBtn.addEventListener('click', () => {
|
||||
const isPassword = passwordInput.type === 'password';
|
||||
passwordInput.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 (loginForm) {
|
||||
loginForm.addEventListener('submit', handleSubmit);
|
||||
}
|
||||
}
|
||||
|
||||
function validateInput(input, showError = false) {
|
||||
const isValid = input.value.trim().length > 0;
|
||||
const errorElement = input.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) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
const submitButton = form.querySelector('.btn-login');
|
||||
const spinner = submitButton.querySelector('.spinner');
|
||||
const buttonText = submitButton.querySelector('.btn-text');
|
||||
|
||||
submitButton.disabled = true;
|
||||
spinner.style.display = 'inline-block';
|
||||
buttonText.style.opacity = '0';
|
||||
|
||||
|
||||
form.submit();
|
||||
}
|
||||
|
||||
|
||||
if (window.location.href.includes('idp.e-kreta.hu/Account/Login')) {
|
||||
transformLoginPage().catch(error => {
|
||||
console.error('Error:', error);
|
||||
});
|
||||
}
|
||||
138
logout/logout.css
Normal file
@@ -0,0 +1,138 @@
|
||||
* {
|
||||
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", serif !important;
|
||||
min-height: 100vh;
|
||||
font-size: 16px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.logout-container {
|
||||
width: 100%;
|
||||
max-width: 500px;
|
||||
padding: 20px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.logout-header {
|
||||
text-align: center;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.logo-text {
|
||||
color: var(--text-primary);
|
||||
font-size: 24px;
|
||||
font-weight: 600;
|
||||
margin: 16px 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.logo {
|
||||
width: 24px;
|
||||
border-radius: 8px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.logout-card {
|
||||
background: var(--card-card);
|
||||
padding: 24px;
|
||||
border-radius: 24px;
|
||||
text-align: center;
|
||||
margin-bottom: 16px;
|
||||
box-shadow: 0px 1px var(--shadow-blur) 0px var(--accent-shadow);
|
||||
}
|
||||
|
||||
.logout-message {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.logout-message strong {
|
||||
font-size: 18px;
|
||||
color: var(--text-primary);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.redirect-timer {
|
||||
font-size: 48px;
|
||||
font-weight: 700;
|
||||
color: var(--accent-accent);
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.btn-continue {
|
||||
display: inline-block;
|
||||
padding: 12px 24px;
|
||||
background: var(--accent-accent);
|
||||
color: var(--button-secondaryFill);
|
||||
text-decoration: none;
|
||||
border-radius: 12px;
|
||||
font-weight: 600;
|
||||
transition: background 0.2s ease, color 0.2s ease;
|
||||
}
|
||||
|
||||
.btn-continue:hover {
|
||||
background: var(--accent-secondary) !important;
|
||||
color: var(--button-secondaryFill) !important;
|
||||
}
|
||||
|
||||
.logout-footer {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.privacy-link {
|
||||
color: var(--text-secondary);
|
||||
text-decoration: none;
|
||||
font-size: 14px;
|
||||
display: inline-block;
|
||||
margin-bottom: 8px;
|
||||
transition: color 0.2s ease;
|
||||
}
|
||||
|
||||
.privacy-link:hover {
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.logout-container {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.logout-card {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.redirect-timer {
|
||||
font-size: 36px;
|
||||
}
|
||||
|
||||
.logo-text {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.logo {
|
||||
width: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-10px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
97
logout/logout.js
Normal file
@@ -0,0 +1,97 @@
|
||||
(() => {
|
||||
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');
|
||||
style.textContent = `
|
||||
@import url('https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500;600;700&display=swap');
|
||||
@import url('https://fonts.googleapis.com/icon?family=Material+Icons+Round');
|
||||
`;
|
||||
document.head.appendChild(style);
|
||||
}
|
||||
function transformLogoutPage() {
|
||||
// Get current theme and school ID from cookies
|
||||
const theme = getCookie('themePreference') || localStorage.getItem('themePreference') || 'light-blue';
|
||||
const instituteCode = getCookie('schoolSubdomain');
|
||||
document.documentElement.setAttribute('data-theme', theme);
|
||||
|
||||
// Create new HTML structure
|
||||
const newHTML = `
|
||||
<div class="logout-container">
|
||||
<header class="logout-header">
|
||||
<p class="logo-text">
|
||||
<img src=${chrome.runtime.getURL('images/firka_logo.png')} alt="Firka" class="logo">
|
||||
Firka
|
||||
</p>
|
||||
</header>
|
||||
|
||||
<div class="logout-card">
|
||||
<div class="logout-message">
|
||||
<strong>Sikeres kijelentkezés!</strong>
|
||||
</div>
|
||||
|
||||
<div class="redirect-timer" id="automaticRedirectTimer">5</div>
|
||||
|
||||
<a href="https://${instituteCode}.e-kreta.hu" class="btn-continue">Tovább</a>
|
||||
</div>
|
||||
|
||||
<footer class="logout-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>
|
||||
`;
|
||||
|
||||
// Replace body content
|
||||
document.body.innerHTML = newHTML;
|
||||
|
||||
// Start countdown timer
|
||||
const timerElement = document.getElementById('automaticRedirectTimer');
|
||||
let remainingTime = 5;
|
||||
|
||||
const countdownInterval = setInterval(() => {
|
||||
remainingTime--;
|
||||
if (timerElement) {
|
||||
timerElement.textContent = remainingTime;
|
||||
}
|
||||
|
||||
if (remainingTime <= 0) {
|
||||
clearInterval(countdownInterval);
|
||||
window.location.href = `https://${instituteCode}.e-kreta.hu`;
|
||||
}
|
||||
}, 1000);
|
||||
|
||||
// Handle manual redirect click
|
||||
document.querySelector('.btn-continue')?.addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
clearInterval(countdownInterval);
|
||||
window.location.href = `https://${instituteCode}.e-kreta.hu`;
|
||||
});
|
||||
}
|
||||
// Load fonts immediately
|
||||
loadFonts();
|
||||
// Run the transformation
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', transformLogoutPage);
|
||||
} else {
|
||||
transformLogoutPage();
|
||||
}
|
||||
})();
|
||||
119
manifest.json
Normal file
@@ -0,0 +1,119 @@
|
||||
{
|
||||
"manifest_version": 3,
|
||||
"name": "Firxa",
|
||||
"version": "1.1.0",
|
||||
"description": "KRÉTA webes verziójának újraírása",
|
||||
"icons": {
|
||||
"128": "images/firka_logo_128.png"
|
||||
},
|
||||
"action": {
|
||||
"default_popup": "settings/index.html",
|
||||
"default_icon": {
|
||||
"128": "images/firka_logo_128.png"
|
||||
}
|
||||
},
|
||||
"web_accessible_resources": [{
|
||||
"resources": [
|
||||
"settings/*",
|
||||
"images/*",
|
||||
"fonts/*.woff2",
|
||||
"icons/*.svg",
|
||||
"grades/chart.js"
|
||||
],
|
||||
"matches": ["https://*.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"],
|
||||
"run_at": "document_start"
|
||||
},
|
||||
{
|
||||
"matches": [
|
||||
"https://*.e-kreta.hu/*"
|
||||
],
|
||||
"css": ["global/maintenance.css"],
|
||||
"run_at": "document_end"
|
||||
},
|
||||
{
|
||||
"matches": ["https://idp.e-kreta.hu/Account/Login*"],
|
||||
"js": ["login/login.js"],
|
||||
"css": ["login/login.css"]
|
||||
},
|
||||
{
|
||||
"matches": [
|
||||
"https://*.e-kreta.hu/Hianyzas/Hianyzasok*"
|
||||
],
|
||||
"js": ["absences/absences.js"],
|
||||
"css": ["absences/absences.css"],
|
||||
"run_at": "document_end"
|
||||
},
|
||||
{
|
||||
"matches": [
|
||||
"https://idp.e-kreta.hu/Account/Logout*"
|
||||
],
|
||||
"js": ["logout/logout.js"],
|
||||
"css": ["logout/logout.css"],
|
||||
"run_at": "document_end"
|
||||
},
|
||||
{
|
||||
"matches": [
|
||||
"https://*.e-kreta.hu/Adminisztracio/BelepesKezelo*"
|
||||
],
|
||||
"js": ["roleselect/roleselect.js"],
|
||||
"css": ["roleselect/roleselect.css"],
|
||||
"run_at": "document_end"
|
||||
},
|
||||
{
|
||||
"matches": [
|
||||
"https://*.e-kreta.hu/Adminisztracio/ElfelejtettJelszo*"
|
||||
],
|
||||
"js": ["forgotpassword/forgotpassword.js"],
|
||||
"css": ["forgotpassword/forgotpassword.css"],
|
||||
"run_at": "document_end"
|
||||
},
|
||||
{
|
||||
"matches": [
|
||||
"https://*.e-kreta.hu/Intezmeny/Faliujsag*"
|
||||
],
|
||||
"js": ["dashboard/dashboard.js"],
|
||||
"css": ["dashboard/dashboard.css"],
|
||||
"run_at": "document_end"
|
||||
},
|
||||
{
|
||||
"matches": [
|
||||
"https://*.e-kreta.hu/TanuloErtekeles/Osztalyzatok*"
|
||||
],
|
||||
"js": ["grades/grades.js", "grades/chart.js"],
|
||||
"css": ["grades/grades.css"],
|
||||
"run_at": "document_end"
|
||||
},
|
||||
{
|
||||
"matches": [
|
||||
"https://*.e-kreta.hu/Orarend/InformaciokOrarend*"
|
||||
],
|
||||
"js": ["timetable/timetable.js"],
|
||||
"css": ["timetable/timetable.css"],
|
||||
"run_at": "document_end"
|
||||
},
|
||||
{
|
||||
"matches": [
|
||||
"https://*.e-kreta.hu/Adminisztracio/Profil*"
|
||||
],
|
||||
"js": ["profile/profile.js"],
|
||||
"css": ["profile/profile.css"],
|
||||
"run_at": "document_end"
|
||||
},
|
||||
{
|
||||
"matches": [
|
||||
"https://*.e-kreta.hu/Tanulo/TanuloHaziFeladat*"
|
||||
],
|
||||
"js": ["homework/homework.js"],
|
||||
"css": ["homework/homework.css"],
|
||||
"run_at": "document_end"
|
||||
}
|
||||
]
|
||||
}
|
||||
487
profile/profile.css
Normal file
@@ -0,0 +1,487 @@
|
||||
* {
|
||||
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", serif !important;
|
||||
min-height: 100vh;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.kreta-container {
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
|
||||
.kreta-header {
|
||||
padding: clamp(1rem, 3vw, 2rem);
|
||||
display: grid;
|
||||
grid-template-columns: minmax(300px, 400px) 1fr minmax(200px, 300px);
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.school-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.logo-text {
|
||||
color: var(--text-primary);
|
||||
font-size: 24px;
|
||||
font-weight: 600;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.logo {
|
||||
width: 24px;
|
||||
border-radius: 8px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.school-details {
|
||||
color: var(--text-secondary);
|
||||
font-size: 14px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
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;
|
||||
}
|
||||
|
||||
.user-dropdown-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
padding: 0.5rem;
|
||||
border-radius: 8px;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.user-dropdown-btn:hover {
|
||||
background: var(--card-card);
|
||||
}
|
||||
|
||||
.user-info {
|
||||
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%;
|
||||
right: 0;
|
||||
margin-top: 0.5rem;
|
||||
background: var(--card-card);
|
||||
border-radius: 12px;
|
||||
box-shadow: 0px 1px var(--shadow-blur) 0px var(--accent-shadow);
|
||||
width: 200px;
|
||||
display: none;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.user-dropdown.show {
|
||||
display: block;
|
||||
animation: dropdownShow 0.2s ease;
|
||||
}
|
||||
|
||||
.dropdown-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
padding: 0.75rem 1rem;
|
||||
color: var(--text-primary);
|
||||
text-decoration: none;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.dropdown-item:hover {
|
||||
background: var(--button-secondaryFill);
|
||||
}
|
||||
|
||||
|
||||
.kreta-main {
|
||||
flex: 1;
|
||||
padding: clamp(1rem, 3vw, 2rem);
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.card {
|
||||
background: var(--card-card);
|
||||
border-radius: 24px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0px 1px var(--shadow-blur) 0px var(--accent-shadow);
|
||||
}
|
||||
|
||||
.card h2 {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: var(--text-primary);
|
||||
padding: 1.5rem;
|
||||
padding-bottom: 0.5rem;
|
||||
background-color: var(--card-card);
|
||||
}
|
||||
|
||||
|
||||
.profile-tabs {
|
||||
padding: 1.5rem;
|
||||
}
|
||||
|
||||
.tab-headers {
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
margin-bottom: 1.5rem;
|
||||
border-bottom: 1px solid var(--card-translucent);
|
||||
overflow-x: auto;
|
||||
scrollbar-width: none;
|
||||
}
|
||||
|
||||
.tab-headers::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tab-header {
|
||||
padding: 0.75rem 1rem;
|
||||
background: none;
|
||||
border: none;
|
||||
color: var(--text-secondary);
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
white-space: nowrap;
|
||||
border-bottom: 2px solid transparent;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.tab-header.active {
|
||||
color: var(--accent-accent);
|
||||
border-bottom-color: var(--accent-accent);
|
||||
}
|
||||
|
||||
.tab-content {
|
||||
display: none;
|
||||
background: var(--button-secondaryFill);
|
||||
border-radius: 8px;
|
||||
padding: 1.5rem;
|
||||
}
|
||||
|
||||
.tab-content.active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.form-label {
|
||||
display: block;
|
||||
color: var(--text-secondary);
|
||||
font-size: 14px;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.form-control {
|
||||
width: 100%;
|
||||
padding: 0.75rem;
|
||||
border: 1px solid var(--accent-15);
|
||||
border-radius: 8px;
|
||||
background: var(--accent-15);
|
||||
color: var(--text-primary);
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.form-control:focus {
|
||||
outline: none;
|
||||
border-color: var(--accent-accent);
|
||||
}
|
||||
|
||||
.form-text {
|
||||
font-size: 12px;
|
||||
color: var(--text-secondary);
|
||||
margin-top: 0.25rem;
|
||||
}
|
||||
|
||||
|
||||
.security-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1.5rem;
|
||||
}
|
||||
|
||||
.step-card {
|
||||
background: var(--button-secondaryFill);
|
||||
border-radius: 12px;
|
||||
padding: 1.5rem;
|
||||
animation: fadeIn 0.3s ease;
|
||||
}
|
||||
|
||||
.step-card h3 {
|
||||
color: var(--text-primary);
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.step-card p {
|
||||
color: var(--text-secondary);
|
||||
font-size: 14px;
|
||||
margin-bottom: 1rem;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.app-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 1.5rem;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.app-section h4 {
|
||||
color: var(--text-primary);
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
margin-bottom: 0.75rem;
|
||||
}
|
||||
|
||||
.app-links {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.app-link {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
padding: 0.75rem;
|
||||
background: var(--card-card);
|
||||
border-radius: 8px;
|
||||
color: var(--text-primary);
|
||||
text-decoration: none;
|
||||
font-size: 14px;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.app-link:hover {
|
||||
background: var(--button-secondaryFill);
|
||||
}
|
||||
|
||||
.qr-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
margin: 1.5rem 0;
|
||||
}
|
||||
|
||||
.qr-container img {
|
||||
background: white;
|
||||
padding: 1rem;
|
||||
border-radius: 8px;
|
||||
max-width: 200px;
|
||||
}
|
||||
|
||||
.setup-key {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.key-display {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
background: var(--card-card);
|
||||
padding: 0.75rem;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.key-display code {
|
||||
font-family: monospace;
|
||||
color: var(--text-primary);
|
||||
font-size: 14px;
|
||||
flex-grow: 1;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.btn-copy {
|
||||
background: none;
|
||||
border: none;
|
||||
color: var(--text-secondary);
|
||||
cursor: pointer;
|
||||
padding: 0.25rem;
|
||||
border-radius: 4px;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.btn-copy:hover {
|
||||
color: var(--text-primary);
|
||||
background: var(--button-secondaryFill);
|
||||
}
|
||||
|
||||
|
||||
.btn-save {
|
||||
padding: 0.75rem 1.5rem;
|
||||
background: var(--accent-accent);
|
||||
color: var(--button-secondaryFill);
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.btn-save:hover {
|
||||
background: var(--accent-secondary);
|
||||
}
|
||||
|
||||
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-10px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes dropdownShow {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-10px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.kreta-header {
|
||||
grid-template-columns: 1fr auto;
|
||||
grid-template-areas:
|
||||
"school user"
|
||||
"nav nav";
|
||||
padding: 1rem;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.school-info {
|
||||
grid-area: school;
|
||||
}
|
||||
|
||||
.nav-links {
|
||||
grid-area: nav;
|
||||
margin-top: 0.5rem;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.user-profile {
|
||||
grid-area: user;
|
||||
}
|
||||
|
||||
.app-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.profile-tabs {
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.tab-content {
|
||||
padding: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.material-icons-round {
|
||||
font-size: 20px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background: var(--background);
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: var(--text-secondary);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: var(--text-primary);
|
||||
}
|
||||
506
profile/profile.js
Normal file
@@ -0,0 +1,506 @@
|
||||
(() => {
|
||||
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">
|
||||
<div class="setup-steps">
|
||||
<div class="step-card">
|
||||
<h3>1. lépés: Hitelesítési alkalmazás telepítése</h3>
|
||||
<p>A kétfaktoros hitelesítés használatához telepítsen egy időalapú, egyszer használatos jelszó (TOTP) alkalmazást:</p>
|
||||
|
||||
<div class="app-grid">
|
||||
<div class="app-section">
|
||||
<h4>Android</h4>
|
||||
<div class="app-links">
|
||||
<a href="https://play.google.com/store/apps/details?id=hu.innobile.niszauth" target="_blank" class="app-link">
|
||||
<span class="material-icons-round">download</span>
|
||||
NISZ Hitelesítő
|
||||
</a>
|
||||
<a href="https://play.google.com/store/apps/details?id=com.azure.authenticator" target="_blank" class="app-link">
|
||||
<span class="material-icons-round">download</span>
|
||||
Microsoft Authenticator
|
||||
</a>
|
||||
<a href="https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2" target="_blank" class="app-link">
|
||||
<span class="material-icons-round">download</span>
|
||||
Google Authenticator
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="app-section">
|
||||
<h4>iPhone</h4>
|
||||
<div class="app-links">
|
||||
<a href="https://apps.apple.com/hu/app/nisz-hiteles%C3%ADt%C5%91/id1603444961" target="_blank" class="app-link">
|
||||
<span class="material-icons-round">download</span>
|
||||
NISZ Hitelesítő
|
||||
</a>
|
||||
<a href="https://apps.apple.com/hu/app/microsoft-authenticator/id983156458" target="_blank" class="app-link">
|
||||
<span class="material-icons-round">download</span>
|
||||
Microsoft Authenticator
|
||||
</a>
|
||||
<a href="https://apps.apple.com/hu/app/google-authenticator/id388497605" target="_blank" class="app-link">
|
||||
<span class="material-icons-round">download</span>
|
||||
Google Authenticator
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="step-card">
|
||||
<h3>2. lépés: Kétfaktoros azonosítás beállítása</h3>
|
||||
<div class="setup-form">
|
||||
<div class="form-group">
|
||||
<button type="button" class="btn-save" id="enable2FA">Kétfaktoros azonosítás bekapcsolása</button>
|
||||
</div>
|
||||
|
||||
<div id="qrSetup" style="display: none;">
|
||||
<div class="qr-container">
|
||||
<img id="qrCode" alt="QR kód" style="display: none;">
|
||||
<div class="setup-key">
|
||||
<label class="form-label">Biztonsági kulcs:</label>
|
||||
<div class="key-display">
|
||||
<code id="secretKey"></code>
|
||||
<button type="button" class="btn-copy" id="copyKey">
|
||||
<span class="material-icons-round">content_copy</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label" for="verificationCode">Ellenőrző kód</label>
|
||||
<input type="text" class="form-control" id="verificationCode" maxlength="6" placeholder="123456">
|
||||
<small class="form-text">Adja meg a hitelesítő alkalmazásban megjelenő 6 számjegyű kódot.</small>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<button type="button" class="btn-save" id="verify2FA">Ellenőrzés és aktiválás</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="step-card" id="backupCodes" style="display: none;">
|
||||
<h3>3. lépés: Biztonsági kódok mentése</h3>
|
||||
<p>Az alábbi biztonsági kódokat használhatja bejelentkezéshez, ha nem fér hozzá a hitelesítő alkalmazásához. Minden kód csak egyszer használható.</p>
|
||||
|
||||
<div class="backup-codes">
|
||||
<pre id="backupCodesList"></pre>
|
||||
<button type="button" class="btn-save" id="downloadCodes">
|
||||
<span class="material-icons-round">download</span>
|
||||
Kódok letöltése
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
function createContactTab() {
|
||||
return `
|
||||
<div class="contact-form">
|
||||
<div class="form-group">
|
||||
<label class="form-label" for="email">E-mail cím</label>
|
||||
<input type="email" class="form-control" id="email" required>
|
||||
<small class="form-text">Az e-mail cím megadása a jelszó emlékeztető miatt szükséges.</small>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label" for="phone">Telefonszám</label>
|
||||
<input type="tel" class="form-control" id="phone" placeholder="+36 xx xxx xxxx">
|
||||
<small class="form-text">A telefonszám megadása nem kötelező.</small>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button type="button" class="btn-save" id="saveContacts">Mentés</button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
function createPasswordTab() {
|
||||
return `
|
||||
<div class="password-form">
|
||||
<div class="form-group">
|
||||
<label class="form-label" for="currentPassword">Jelenlegi jelszó</label>
|
||||
<input type="password" class="form-control" id="currentPassword" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label" for="newPassword">Új jelszó</label>
|
||||
<input type="password" class="form-control" id="newPassword" required minlength="8">
|
||||
<small class="form-text">A jelszónak legalább 8 karakter hosszúnak kell lennie.</small>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label" for="confirmPassword">Új jelszó megerősítése</label>
|
||||
<input type="password" class="form-control" id="confirmPassword" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button type="button" class="btn-save" id="savePassword">Jelszó módosítása</button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
function createSettingsTab() {
|
||||
return `
|
||||
<div class="settings-form">
|
||||
<div class="form-group">
|
||||
<label class="form-label">
|
||||
<input type="checkbox" id="hideTips">
|
||||
Tippek elrejtése
|
||||
</label>
|
||||
<small class="form-text">A tippek megjelenítésének ki/be kapcsolása.</small>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button type="button" class="btn-save" id="saveSettings">Mentés</button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
function setupContactForm() {
|
||||
const form = document.querySelector('.contact-form');
|
||||
if (!form) return;
|
||||
|
||||
const emailInput = form.querySelector('#email');
|
||||
const phoneInput = form.querySelector('#phone');
|
||||
const saveButton = form.querySelector('#saveContacts');
|
||||
|
||||
|
||||
emailInput.value = getCookie('userEmail') || '';
|
||||
phoneInput.value = getCookie('userPhone') || '';
|
||||
|
||||
saveButton?.addEventListener('click', async () => {
|
||||
const email = emailInput.value.trim();
|
||||
const phone = phoneInput.value.trim();
|
||||
|
||||
if (!email) {
|
||||
alert('Az e-mail cím megadása kötelező!');
|
||||
return;
|
||||
}
|
||||
|
||||
if (email && !isValidEmail(email)) {
|
||||
alert('Kérjük, adjon meg egy érvényes e-mail címet!');
|
||||
return;
|
||||
}
|
||||
|
||||
if (phone && !isValidPhone(phone)) {
|
||||
alert('Kérjük, adjon meg egy érvényes telefonszámot!');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch('/Adminisztracio/Profil/SaveElerhetosegek', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'RequestVerificationToken': document.querySelector('input[name="__RequestVerificationToken"]').value
|
||||
},
|
||||
body: JSON.stringify({ email, phone })
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
alert('Elérhetőségek sikeresen mentve!');
|
||||
} else {
|
||||
throw new Error('Hiba történt a mentés során.');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error saving contacts:', error);
|
||||
alert('Hiba történt a mentés során. Kérjük, próbálja újra később.');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function isValidEmail(email) {
|
||||
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
|
||||
}
|
||||
|
||||
function isValidPhone(phone) {
|
||||
return /^\+?[0-9\s-]{9,}$/.test(phone);
|
||||
}
|
||||
|
||||
function setupEventListeners() {
|
||||
|
||||
document.querySelectorAll('.tab-header').forEach(header => {
|
||||
header.addEventListener('click', () => {
|
||||
document.querySelectorAll('.tab-header').forEach(h => h.classList.remove('active'));
|
||||
document.querySelectorAll('.tab-content').forEach(c => c.classList.remove('active'));
|
||||
|
||||
header.classList.add('active');
|
||||
const targetId = header.dataset.tab;
|
||||
document.getElementById(`${targetId}-content`).classList.add('active');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
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('saveSettings')?.addEventListener('click', async () => {
|
||||
const hideTips = document.getElementById('hideTips').checked;
|
||||
|
||||
try {
|
||||
const response = await fetch('/Adminisztracio/Profil/SaveTippekBeallitasa', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'RequestVerificationToken': document.querySelector('input[name="__RequestVerificationToken"]').value
|
||||
},
|
||||
body: JSON.stringify({ hideTips })
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
alert('Beállítások sikeresen mentve! A változtatások érvényesítéséhez jelentkezzen be újra.');
|
||||
} else {
|
||||
throw new Error('Hiba történt a mentés során.');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error saving settings:', error);
|
||||
alert('Hiba történt a mentés során. Kérjük, próbálja újra később.');
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
document.getElementById('savePassword')?.addEventListener('click', async () => {
|
||||
const currentPassword = document.getElementById('currentPassword').value;
|
||||
const newPassword = document.getElementById('newPassword').value;
|
||||
const confirmPassword = document.getElementById('confirmPassword').value;
|
||||
|
||||
if (!currentPassword || !newPassword || !confirmPassword) {
|
||||
alert('Kérjük, töltse ki az összes mezőt!');
|
||||
return;
|
||||
}
|
||||
|
||||
if (newPassword !== confirmPassword) {
|
||||
alert('Az új jelszavak nem egyeznek!');
|
||||
return;
|
||||
}
|
||||
|
||||
if (newPassword.length < 8) {
|
||||
alert('Az új jelszónak legalább 8 karakter hosszúnak kell lennie!');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch('/Adminisztracio/Profil/SaveJelszoModositas', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'RequestVerificationToken': document.querySelector('input[name="__RequestVerificationToken"]').value
|
||||
},
|
||||
body: JSON.stringify({
|
||||
currentPassword,
|
||||
newPassword,
|
||||
confirmPassword
|
||||
})
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
alert('Jelszó sikeresen módosítva!');
|
||||
document.getElementById('currentPassword').value = '';
|
||||
document.getElementById('newPassword').value = '';
|
||||
document.getElementById('confirmPassword').value = '';
|
||||
} else {
|
||||
throw new Error('Hiba történt a jelszó módosítása során.');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error changing password:', error);
|
||||
alert('Hiba történt a jelszó módosítása során. Kérjük, próbálja újra később.');
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
function createProfileHTML(data) {
|
||||
const schoolNameFull = `${data.schoolInfo.id} - ${data.schoolInfo.name}`;
|
||||
const shortenedSchoolName = 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" 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>
|
||||
|
||||
<main class="kreta-main">
|
||||
<div class="card">
|
||||
<h2>Profil beállítások</h2>
|
||||
<div class="profile-tabs">
|
||||
<div class="tab-headers">
|
||||
<button class="tab-header active" data-tab="settings">Beállítások</button>
|
||||
<button class="tab-header" data-tab="password">Jelszó módosítása</button>
|
||||
<button class="tab-header" data-tab="security">Biztonsági beállítások</button>
|
||||
<button class="tab-header" data-tab="contacts">Elérhetőségek</button>
|
||||
</div>
|
||||
|
||||
<div id="settings-content" class="tab-content active">
|
||||
${createSettingsTab()}
|
||||
</div>
|
||||
|
||||
<div id="password-content" class="tab-content">
|
||||
${createPasswordTab()}
|
||||
</div>
|
||||
|
||||
<div id="security-content" class="tab-content">
|
||||
${createSecurityTab()}
|
||||
</div>
|
||||
|
||||
<div id="contacts-content" class="tab-content">
|
||||
${createContactTab()}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
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' }
|
||||
];
|
||||
|
||||
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);
|
||||
setupEventListeners();
|
||||
setupContactForm();
|
||||
}
|
||||
}
|
||||
|
||||
init();
|
||||
})();
|
||||
380
roleselect/roleselect.css
Normal file
@@ -0,0 +1,380 @@
|
||||
@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;
|
||||
}
|
||||
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
color: var(--text-primary);
|
||||
background-color: var(--background) !important;
|
||||
font-family: "Montserrat", serif !important;
|
||||
min-height: 100vh;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
|
||||
.kreta-container {
|
||||
width: 100%;
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: clamp(1rem, 3vw, 2rem);
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
|
||||
.kreta-header {
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr auto;
|
||||
align-items: center;
|
||||
gap: 2rem;
|
||||
margin-bottom: clamp(2rem, 5vw, 3rem);
|
||||
}
|
||||
|
||||
|
||||
.school-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.logo-text {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 1.5rem;
|
||||
font-weight: 600;
|
||||
color: var(--text-primary);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.logo {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 8px;
|
||||
margin-right: 0.75rem;
|
||||
}
|
||||
|
||||
.school-details {
|
||||
color: var(--text-secondary);
|
||||
font-size: 1.1rem;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
max-width: 300px;
|
||||
padding-left: 2px;
|
||||
}
|
||||
|
||||
|
||||
.user-profile {
|
||||
justify-self: flex-end;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.user-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
|
||||
.user-name, .role-text {
|
||||
color: var(--text-primary);
|
||||
font-family: Montserrat;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.user-name {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.role-text {
|
||||
font-size: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.logout-timer, .role-description {
|
||||
color: var(--text-secondary);
|
||||
font-family: Figtree;
|
||||
font-weight: 500;
|
||||
line-height: 130%;
|
||||
}
|
||||
|
||||
.logout-timer {
|
||||
font-size: 14px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.role-description {
|
||||
font-size: 16px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
.role-container {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.role-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr minmax(300px, 1fr);
|
||||
gap: 1.5rem;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.side-roles {
|
||||
display: grid;
|
||||
grid-template-rows: 1fr auto;
|
||||
gap: 1.5rem;
|
||||
}
|
||||
|
||||
|
||||
.role-card {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 1.5rem;
|
||||
padding: 2rem;
|
||||
background: var(--card-card);
|
||||
border-radius: 1rem;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
border: none;
|
||||
box-shadow: 0px 1px var(--shadow-blur) 0px var(--accent-shadow);
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
|
||||
.role-card[data-role="Ellenorzo"] {
|
||||
height: 480px;
|
||||
background: var(--card-card);
|
||||
}
|
||||
|
||||
.role-card[data-role="DKT"] {
|
||||
height: 280px;
|
||||
background: var(--card-card);
|
||||
box-shadow: 0px 1px var(--shadow-blur) 0px var(--accent-shadow);
|
||||
}
|
||||
|
||||
.logout-card {
|
||||
height: 180px;
|
||||
background: var(--error-card);
|
||||
box-shadow: 0px 1px var(--shadow-blur) 0px var(--accent-shadow);
|
||||
}
|
||||
|
||||
|
||||
.role-icon {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 12px;
|
||||
transition: transform 0.2s ease;
|
||||
background: var(--accent-15);
|
||||
}
|
||||
|
||||
.role-icon img {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
transition: transform 0.2s ease;
|
||||
}
|
||||
|
||||
.role-card[data-role="DKT"] .role-icon {
|
||||
background: var(--warning-15);
|
||||
}
|
||||
|
||||
.logout-card .role-icon {
|
||||
background: var(--error-15);
|
||||
}
|
||||
|
||||
.role-icon img {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
transition: transform 0.2s ease;
|
||||
}
|
||||
|
||||
|
||||
.role-card:hover {
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.role-card:hover .role-icon img {
|
||||
transform: scale(1.2);
|
||||
}
|
||||
|
||||
.role-card:active {
|
||||
transform: translateY(1px);
|
||||
box-shadow: 0px 0px var(--shadow-blur) 0px var(--accent-shadow);
|
||||
}
|
||||
|
||||
|
||||
.role-card[data-role="Ellenorzo"]:hover {
|
||||
background-color: var(--accent-15);
|
||||
}
|
||||
|
||||
.role-card[data-role="DKT"]:hover {
|
||||
background-color: var(--accent-15);
|
||||
}
|
||||
|
||||
.role-card[data-role="DKT"]:active {
|
||||
box-shadow: 0px 0px var(--shadow-blur) 0px var(--accent-shadow);
|
||||
}
|
||||
|
||||
.logout-card:hover {
|
||||
background-color: var(--error-15);
|
||||
}
|
||||
|
||||
.logout-card:active {
|
||||
box-shadow: 0px 0px var(--shadow-blur) 0px var(--error-shadow);
|
||||
}
|
||||
|
||||
|
||||
:root[data-theme="light-blue"] .role-card:hover,
|
||||
:root[data-theme="light-green"] .role-card:hover {
|
||||
box-shadow: 0px 1px var(--shadow-blur) 0px var(--accent-shadow);
|
||||
}
|
||||
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background: var(--background);
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: var(--text-secondary);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: var(--text-primary);
|
||||
}
|
||||
|
||||
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-10px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@media (max-width: 1200px) {
|
||||
.role-grid {
|
||||
grid-template-columns: 1fr 280px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 900px) {
|
||||
.role-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.side-roles {
|
||||
grid-template-columns: 1fr 1fr;
|
||||
grid-template-rows: none;
|
||||
}
|
||||
|
||||
.role-card[data-role="Ellenorzo"],
|
||||
.role-card[data-role="DKT"],
|
||||
.logout-card {
|
||||
height: 300px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.kreta-header {
|
||||
grid-template-columns: 1fr auto;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.school-info {
|
||||
max-width: 60%;
|
||||
}
|
||||
|
||||
.school-details {
|
||||
max-width: 200px;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.logo-text {
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
.logo {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
.kreta-container {
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.side-roles {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.role-card {
|
||||
padding: 1.5rem;
|
||||
}
|
||||
|
||||
.role-icon {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.role-icon img {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
.role-text {
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
.role-description {
|
||||
font-size: 1rem;
|
||||
}
|
||||
}
|
||||
183
roleselect/roleselect.js
Normal file
@@ -0,0 +1,183 @@
|
||||
(() => {
|
||||
|
||||
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');
|
||||
|
||||
const updateTimer = () => {
|
||||
const minutes = Math.floor(timeLeft / 60);
|
||||
const seconds = timeLeft % 60;
|
||||
|
||||
if (timerElement) {
|
||||
timerElement.textContent = `${minutes}:${seconds.toString().padStart(2, '0')}`;
|
||||
}
|
||||
|
||||
timeLeft <= 0 ? window.location.href = '/Home/Logout' : timeLeft--;
|
||||
};
|
||||
|
||||
updateTimer();
|
||||
return setInterval(updateTimer, 1000);
|
||||
};
|
||||
|
||||
const handleRoleChange = async (role) => {
|
||||
try {
|
||||
const response = await fetch('/Adminisztracio/SzerepkorValaszto/ChangeRole', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ Role: role })
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
if (data.Success) {
|
||||
window.location.assign(data.Url);
|
||||
} else {
|
||||
throw new Error('Role change failed');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error changing role:', error);
|
||||
alert('Hiba történt a szerepkör váltása közben.');
|
||||
}
|
||||
};
|
||||
|
||||
const createHTML = (schoolCode, fullSchoolName, userName) => `
|
||||
<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>${schoolCode || ''} - ${fullSchoolName || 'Iskola'}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="user-profile">
|
||||
<div class="user-info">
|
||||
<span class="user-name">${userName}</span>
|
||||
<span class="logout-timer" id="logoutTimer">5:00</span>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main class="role-container">
|
||||
<div class="role-grid">
|
||||
<div class="main-role">
|
||||
<div class="role-card" data-role="Ellenorzo">
|
||||
<div class="role-icon">
|
||||
<img src="${chrome.runtime.getURL('icons/naplo.svg')}" alt="Napló ikon">
|
||||
</div>
|
||||
<div class="role-text">
|
||||
Ellenőrzőkönyv
|
||||
<div class="role-description">Jegyek, hiányzások, órarended és egyéb információk megtekintése.</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="side-roles">
|
||||
<div class="role-card" data-role="DKT">
|
||||
<div class="role-icon">
|
||||
<img src="${chrome.runtime.getURL('icons/dkt.svg')}" alt="DKT ikon">
|
||||
</div>
|
||||
<div class="role-text">
|
||||
Digitális Kollaborációs Tér (DKT)
|
||||
<div class="role-description">Osztálytermi kommunikáció és feladatok.</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="role-card logout-card">
|
||||
<div class="role-icon">
|
||||
<img src="${chrome.runtime.getURL('icons/logout.svg')}" alt="Kijelentkezés ikon">
|
||||
</div>
|
||||
<div class="role-text">
|
||||
Kijelentkezés
|
||||
<div class="role-description">Kilépés a rendszerből</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
`;
|
||||
|
||||
const transformRoleSelectPage = async () => {
|
||||
try {
|
||||
if (document.readyState !== 'complete') {
|
||||
await new Promise(resolve => window.addEventListener('load', resolve));
|
||||
}
|
||||
|
||||
|
||||
const schoolNameEl = document.querySelector('.IntezmenyNev');
|
||||
const schoolName = schoolNameEl?.textContent.trim() || 'Iskola neve';
|
||||
const [schoolCode, fullSchoolName] = schoolName.split(' - ');
|
||||
|
||||
|
||||
const schoolSubdomain = window.location.hostname.split('.')[0];
|
||||
|
||||
const userNameEl = document.querySelector('.UserName');
|
||||
const userName = userNameEl?.textContent.trim() || 'Felhasználónév';
|
||||
|
||||
|
||||
if (schoolCode && fullSchoolName) {
|
||||
setCookie('schoolCode', schoolCode);
|
||||
setCookie('schoolName', fullSchoolName);
|
||||
setCookie('schoolSubdomain', schoolSubdomain);
|
||||
}
|
||||
if (userName) {
|
||||
setCookie('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);
|
||||
});
|
||||
|
||||
|
||||
const timerInterval = startLogoutTimer();
|
||||
|
||||
|
||||
document.querySelector('.role-card[data-role="Ellenorzo"]')?.addEventListener('click', () => {
|
||||
handleRoleChange('Ellenorzo');
|
||||
});
|
||||
|
||||
document.querySelector('.role-card[data-role="DKT"]')?.addEventListener('click', () => {
|
||||
window.location.href = '/Adminisztracio/BelepesKezelo/DKTTanuloOrGondviselo';
|
||||
});
|
||||
|
||||
document.querySelector('.logout-card')?.addEventListener('click', async () => {
|
||||
try {
|
||||
clearInterval(timerInterval);
|
||||
await fetch('/Home/LogOut', { method: 'POST' });
|
||||
} catch {
|
||||
window.location.replace("https://idp.e-kreta.hu/Account/Logout");
|
||||
} finally {
|
||||
window.location.replace("https://idp.e-kreta.hu/Account/Logout");
|
||||
}
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error transforming page:', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
if (window.location.href.includes('/Adminisztracio/BelepesKezelo')) {
|
||||
transformRoleSelectPage();
|
||||
}
|
||||
})();
|
||||
276
settings/index.css
Normal file
@@ -0,0 +1,276 @@
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
width: 400px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
color: var(--text-primary);
|
||||
background-color: var(--background) !important;
|
||||
font-family: "Montserrat", serif;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
|
||||
* {
|
||||
scrollbar-width: none;
|
||||
-ms-overflow-style: none;
|
||||
}
|
||||
|
||||
*::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.popup-container {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.popup-header {
|
||||
text-align: center;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.logo-text {
|
||||
color: var(--text-primary);
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
margin: 8px 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.logo {
|
||||
width: 20px;
|
||||
border-radius: 6px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.settings-card,
|
||||
.about-card,
|
||||
.support-card {
|
||||
background: var(--card-card);
|
||||
border-radius: 16px;
|
||||
padding: 16px;
|
||||
margin-bottom: 16px;
|
||||
box-shadow: 0px 1px var(--shadow-blur) 0px var(--accent-shadow);
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: var(--text-primary);
|
||||
margin-bottom: 12px;
|
||||
background-color: var(--card-card);
|
||||
}
|
||||
|
||||
.settings-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.setting-section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.setting-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
color: var(--text-primary);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
|
||||
.theme-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 12px;
|
||||
}
|
||||
.theme-option {
|
||||
background: none;
|
||||
border: none;
|
||||
padding: 0;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
transition: transform 0.2s ease;
|
||||
}
|
||||
.theme-option:hover {
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
.theme-option.active .theme-preview {
|
||||
outline: 2px solid var(--accent-accent);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
.theme-preview {
|
||||
width: 100%;
|
||||
height: 100px;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
.theme-option.disabled {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.theme-option.disabled::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.1);
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
|
||||
.theme-preview.light-blue {
|
||||
background: #DAE4F7;
|
||||
}
|
||||
|
||||
.theme-preview.light-blue .preview-header {
|
||||
background: #EDF3FF;
|
||||
}
|
||||
|
||||
.theme-preview.light-blue .preview-card {
|
||||
background: #FBFCFF;
|
||||
}
|
||||
|
||||
|
||||
.theme-preview.light-green {
|
||||
background: #FAFFF0;
|
||||
}
|
||||
|
||||
.theme-preview.light-green .preview-header {
|
||||
background: #F3FBDE;
|
||||
}
|
||||
|
||||
.theme-preview.light-green .preview-card {
|
||||
background: #FEFFFD;
|
||||
}
|
||||
|
||||
|
||||
.theme-preview.dark-blue {
|
||||
background: #070A0E;
|
||||
}
|
||||
|
||||
.theme-preview.dark-blue .preview-header {
|
||||
background: #0F131B;
|
||||
}
|
||||
|
||||
.theme-preview.dark-blue .preview-card {
|
||||
background: #131822;
|
||||
}
|
||||
|
||||
|
||||
.theme-preview.dark-green {
|
||||
background: #0D1202;
|
||||
}
|
||||
|
||||
.theme-preview.dark-green .preview-header {
|
||||
background: #141905;
|
||||
}
|
||||
|
||||
.theme-preview.dark-green .preview-card {
|
||||
background: #20290b;
|
||||
}
|
||||
|
||||
.preview-header {
|
||||
height: 30%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.preview-content {
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.preview-card {
|
||||
height: 30px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.theme-name {
|
||||
color: var(--text-primary);
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.about-content,
|
||||
.support-content {
|
||||
color: var(--text-secondary);
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.about-content p,
|
||||
.support-content p {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.github-link {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
color: var(--accent-accent);
|
||||
text-decoration: none;
|
||||
font-weight: 500;
|
||||
transition: color 0.2s;
|
||||
}
|
||||
|
||||
.github-link:hover {
|
||||
color: var(--accent-secondary);
|
||||
}
|
||||
|
||||
.support-buttons {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.support-button {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 6px;
|
||||
padding: 8px;
|
||||
background: var(--accent-15);
|
||||
color: var(--text-primary);
|
||||
text-decoration: none;
|
||||
border-radius: 8px;
|
||||
font-weight: 500;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.support-button:hover {
|
||||
background: var(--accent-accent);
|
||||
color: var(--button-secondaryFill);
|
||||
}
|
||||
|
||||
.popup-footer {
|
||||
text-align: center;
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.version-info {
|
||||
color: var(--text-secondary);
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
|
||||
.material-icons-round {
|
||||
font-size: 18px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
103
settings/index.html
Normal file
@@ -0,0 +1,103 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="hu">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Firxa Beállítások</title>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap" rel="stylesheet">
|
||||
<link href="https://fonts.googleapis.com/icon?family=Material+Icons+Round" rel="stylesheet">
|
||||
<link rel="stylesheet" href="index.css">
|
||||
<link rel="stylesheet" href="../global/theme.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="popup-container">
|
||||
<header class="popup-header">
|
||||
<p class="logo-text">
|
||||
<img src="https://i.imgur.com/WugwlzI.png" alt="Firka" class="logo">
|
||||
Firxa
|
||||
</p>
|
||||
</header>
|
||||
|
||||
<div class="settings-card">
|
||||
<h2>Beállítások</h2>
|
||||
<div class="settings-group">
|
||||
<div class="setting-section">
|
||||
<div class="setting-header">
|
||||
<span class="material-icons-round">palette</span>
|
||||
Téma
|
||||
</div>
|
||||
<div class="theme-grid">
|
||||
<button class="theme-option" data-theme="default">
|
||||
<div class="theme-preview light-blue">
|
||||
<div class="preview-header"></div>
|
||||
<div class="preview-content">
|
||||
<div class="preview-card"></div>
|
||||
</div>
|
||||
</div>
|
||||
<span class="theme-name">Világos Kék</span>
|
||||
</button>
|
||||
<button class="theme-option" data-theme="light-green">
|
||||
<div class="theme-preview light-green">
|
||||
<div class="preview-header"></div>
|
||||
<div class="preview-content">
|
||||
<div class="preview-card"></div>
|
||||
</div>
|
||||
</div>
|
||||
<span class="theme-name">Világos Zöld</span>
|
||||
</button>
|
||||
<button class="theme-option" data-theme="dark-blue">
|
||||
<div class="theme-preview dark-blue">
|
||||
<div class="preview-header"></div>
|
||||
<div class="preview-content">
|
||||
<div class="preview-card"></div>
|
||||
</div>
|
||||
</div>
|
||||
<span class="theme-name">Sötét Kék</span>
|
||||
</button>
|
||||
<button class="theme-option" data-theme="dark-green">
|
||||
<div class="theme-preview dark-green">
|
||||
<div class="preview-header"></div>
|
||||
<div class="preview-content">
|
||||
<div class="preview-card"></div>
|
||||
</div>
|
||||
</div>
|
||||
<span class="theme-name">Sötét Zöld</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="about-card">
|
||||
<h2>Névjegy</h2>
|
||||
<div class="about-content">
|
||||
<p>A Firka egy nyílt forráskódú projekt, amely a KRÉTA rendszerhez készít saját felhasználói felületet.</p>
|
||||
<a href="https://github.com/QwIT-Development/" target="_blank" class="github-link">
|
||||
<span class="material-icons-round">code</span>
|
||||
GitHub
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="support-card">
|
||||
<h2>Támogatás</h2>
|
||||
<div class="support-content">
|
||||
<p>Ha tetszik a munkánk és szeretnéd támogatni a fejlesztést, az alábbi módon teheted meg:</p>
|
||||
<div class="support-buttons">
|
||||
<a href="https://ko-fi.com/zan1456" target="_blank" class="support-button">
|
||||
<span class="material-icons-round">coffee</span>
|
||||
Ko-Fi
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<footer class="popup-footer">
|
||||
<div class="version-info" id="version">v1.1.0</div>
|
||||
</footer>
|
||||
</div>
|
||||
<script src="index.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
141
settings/index.js
Normal file
@@ -0,0 +1,141 @@
|
||||
document.addEventListener('DOMContentLoaded', async () => {
|
||||
|
||||
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 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`;
|
||||
}
|
||||
|
||||
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 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';
|
||||
}
|
||||
|
||||
async function applyTheme(theme) {
|
||||
|
||||
if (isThemeDisabled(theme)) {
|
||||
alert('Ez a téma jelenleg nem elérhető.');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
setCookie('themePreference', theme);
|
||||
localStorage.setItem('themePreference', theme);
|
||||
|
||||
|
||||
document.documentElement.setAttribute('data-theme', theme);
|
||||
|
||||
|
||||
updateThemeButtons(theme);
|
||||
|
||||
|
||||
const tabs = await chrome.tabs.query({});
|
||||
tabs.forEach(tab => {
|
||||
chrome.tabs.sendMessage(tab.id, {
|
||||
action: 'changeTheme',
|
||||
theme: theme
|
||||
}).catch(() => {
|
||||
|
||||
console.log('Tab not ready for theme change:', tab.id);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
const themeButtons = document.querySelectorAll('.theme-option');
|
||||
themeButtons.forEach(button => {
|
||||
button.addEventListener('click', () => {
|
||||
const theme = button.dataset.theme;
|
||||
|
||||
|
||||
if (button.hasAttribute('disabled')) {
|
||||
alert('Ez a téma jelenleg nem elérhető.');
|
||||
return;
|
||||
}
|
||||
|
||||
applyTheme(theme);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
let initialTheme = localStorage.getItem('themePreference') ||
|
||||
getCookie('themePreference') ||
|
||||
await getCurrentTheme() ||
|
||||
'light-green';
|
||||
|
||||
|
||||
if (isThemeDisabled(initialTheme)) {
|
||||
initialTheme = 'light-green';
|
||||
}
|
||||
|
||||
|
||||
await applyTheme(initialTheme);
|
||||
|
||||
|
||||
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
||||
if (message.action === 'themeChanged') {
|
||||
updateThemeButtons(message.theme);
|
||||
document.documentElement.setAttribute('data-theme', message.theme);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
const manifest = chrome.runtime.getManifest();
|
||||
document.getElementById('version').textContent = `v${manifest.version}`;
|
||||
|
||||
|
||||
themeButtons.forEach(button => {
|
||||
button.addEventListener('mouseover', () => {
|
||||
if (!button.hasAttribute('disabled')) {
|
||||
button.style.transform = 'translateY(-2px)';
|
||||
}
|
||||
});
|
||||
|
||||
button.addEventListener('mouseout', () => {
|
||||
button.style.transform = 'translateY(0)';
|
||||
});
|
||||
});
|
||||
});
|
||||
822
timetable/timetable.css
Normal file
@@ -0,0 +1,822 @@
|
||||
@font-face {
|
||||
font-family: 'Montserrat';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: url(https://fonts.gstatic.com/s/montserrat/v25/JTUHjIg1_i6t8kCHKm4532VJOt5-QNFgpCtr6Hw5aXp-p7K4KLg.woff2) format('woff2');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Montserrat';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
src: url(https://fonts.gstatic.com/s/montserrat/v25/JTUHjIg1_i6t8kCHKm4532VJOt5-QNFgpCtZ6Hw5aXp-p7K4KLg.woff2) format('woff2');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Montserrat';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
src: url(https://fonts.gstatic.com/s/montserrat/v25/JTUHjIg1_i6t8kCHKm4532VJOt5-QNFgpCu173w5aXp-p7K4KLg.woff2) format('woff2');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Figtree';
|
||||
src: url('chrome-extension://__MSG_@@extension_id__/fonts/Figtree-Regular.woff2') format('woff2');
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: 'Montserrat', sans-serif;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
color: var(--text-primary);
|
||||
background-color: var(--background) !important;
|
||||
min-height: 100vh;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
.kreta-container {
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* Update header styles to match dashboard */
|
||||
.kreta-header {
|
||||
padding: clamp(1rem, 3vw, 2rem);
|
||||
display: grid;
|
||||
grid-template-columns: minmax(300px, 400px) 1fr minmax(200px, 300px);
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
@media (max-width: 1200px) {
|
||||
.kreta-header {
|
||||
grid-template-columns: minmax(250px, 350px) 1fr minmax(180px, 250px);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.kreta-header {
|
||||
grid-template-columns: 1fr auto;
|
||||
grid-template-areas:
|
||||
"school user"
|
||||
"nav nav";
|
||||
padding: 1rem;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.school-info {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.school-info {
|
||||
grid-area: school;
|
||||
max-width: none;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.logo-text {
|
||||
color: var(--text-primary);
|
||||
font-size: 24px;
|
||||
font-weight: 600;
|
||||
margin: 0 0 0.5rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.logo-text {
|
||||
margin: 0;
|
||||
font-size: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.logo {
|
||||
width: 24px;
|
||||
border-radius: 8px;
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
|
||||
.school-details {
|
||||
color: var(--text-secondary);
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.school-details span {
|
||||
display: block;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
max-width: 300px;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.school-details span {
|
||||
max-width: 200px;
|
||||
}
|
||||
|
||||
.school-details {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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;
|
||||
justify-self: flex-end;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.user-profile {
|
||||
grid-area: user;
|
||||
}
|
||||
}
|
||||
|
||||
.user-dropdown-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
padding: 0.5rem;
|
||||
border-radius: 8px;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.user-dropdown-btn:hover {
|
||||
background: var(--card-card);
|
||||
}
|
||||
|
||||
.user-info {
|
||||
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%;
|
||||
right: 0;
|
||||
margin-top: 0.5rem;
|
||||
background: var(--card-card);
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 6px -1px var(--accent-shadow);
|
||||
width: 200px;
|
||||
display: none;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.user-dropdown.show {
|
||||
display: block;
|
||||
animation: dropdownShow 0.2s ease;
|
||||
}
|
||||
|
||||
.dropdown-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
padding: 0.75rem 1rem;
|
||||
color: var(--text-primary);
|
||||
text-decoration: none;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.dropdown-item:hover {
|
||||
background: var(--button-secondaryFill);
|
||||
}
|
||||
|
||||
/* Main content styles */
|
||||
.kreta-main {
|
||||
flex: 1;
|
||||
padding: clamp(1rem, 3vw, 2rem);
|
||||
max-width: 1400px;
|
||||
margin: 0 auto;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Card styles */
|
||||
.card {
|
||||
border-radius: 24px;
|
||||
overflow: hidden;
|
||||
animation: fadeIn 0.3s ease;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
/* Timetable specific styles */
|
||||
.timetable-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 80px repeat(5, 1fr);
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.grid-header {
|
||||
padding: 12px;
|
||||
text-align: center;
|
||||
font-weight: 600;
|
||||
color: var(--text-primary);
|
||||
border-radius: 12px;
|
||||
min-width: 120px;
|
||||
}
|
||||
|
||||
.grid-header:first-child {
|
||||
min-width: 80px;
|
||||
}
|
||||
|
||||
.grid-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
.day-name {
|
||||
text-align: left;
|
||||
color: var(--text-primary);
|
||||
font-family: Montserrat;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
.day-date {
|
||||
text-align: right;
|
||||
color: var(--text-secondary);
|
||||
font-family: Figtree;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
line-height: 130%;
|
||||
}
|
||||
|
||||
.time-slot {
|
||||
padding: 12px;
|
||||
text-align: center;
|
||||
color: var(--text-secondary);
|
||||
font-size: 14px;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.lesson-slot {
|
||||
min-height: 100px;
|
||||
border-radius: 12px;
|
||||
padding: 8px;
|
||||
transition: transform 0.2s ease;
|
||||
}
|
||||
|
||||
.lesson-slot:hover {
|
||||
transform: scale(1.02);
|
||||
}
|
||||
|
||||
.lesson-card {
|
||||
display: flex;
|
||||
padding: 16px;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 10px;
|
||||
align-self: stretch;
|
||||
border-radius: 16px;
|
||||
background: var(--card-card);
|
||||
box-shadow: 0px 1px var(--shadow-blur, 2px) 0px var(--accent-shadow);
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.lesson-card:hover {
|
||||
transform: translateY(-4px);
|
||||
box-shadow: 0 8px 12px var(--accent-shadow);
|
||||
}
|
||||
|
||||
.lesson-card.substituted {
|
||||
background: var(--warning-card);
|
||||
}
|
||||
|
||||
.lesson-card.cancelled {
|
||||
border-radius: 16px;
|
||||
background: var(--card-translucent);
|
||||
}
|
||||
|
||||
.lesson-card.cancelled .lesson-subject, .lesson-card.cancelled .lesson-teacher, .lesson-card.cancelled .lesson-room {
|
||||
opacity: 0.5;
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
.lesson-subject {
|
||||
align-self: stretch;
|
||||
color: var(--text-primary);
|
||||
font-family: Montserrat;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
.lesson-teacher {
|
||||
color: var(--text-secondary);
|
||||
font-family: Figtree;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
line-height: 130%;
|
||||
}
|
||||
.lesson-bottom {
|
||||
margin-top: auto;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-end;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.lesson-room {
|
||||
background: var(--accent-15);
|
||||
color: var(--text-secondary);
|
||||
padding: 4px 8px;
|
||||
border-radius: 12px;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.lesson-card.substituted .lesson-bottom .lesson-room {
|
||||
background: var(--warning-15);
|
||||
}
|
||||
.lesson-time {
|
||||
color: var(--text-secondary);
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
margin-left: auto;
|
||||
text-align: right;
|
||||
min-width: 45px;
|
||||
}
|
||||
.lesson-indicators {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
right: 8px;
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.lesson-indicator {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border-radius: 50%;
|
||||
background: var(--accent-15);
|
||||
color: var(--accent-accent);
|
||||
}
|
||||
|
||||
.lesson-indicator.homework-indicator {
|
||||
background: var(--accent-15);
|
||||
color: var(--accent-accent);
|
||||
}
|
||||
|
||||
.lesson-indicator.test-indicator {
|
||||
background: var(--warning-15);
|
||||
color: var(--warning-accent);
|
||||
}
|
||||
|
||||
.lesson-indicator .material-icons-round {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* Week selector styling */
|
||||
.week-controls {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
align-items: center;
|
||||
margin: 16px;
|
||||
background: var(--card-card);
|
||||
border-radius: 24px;
|
||||
max-width: 400px;
|
||||
}
|
||||
|
||||
.week-select {
|
||||
flex: 1;
|
||||
padding: 12px;
|
||||
border: none;
|
||||
border-radius: 12px;
|
||||
background: var(--button-secondaryFill);
|
||||
color: var(--text-primary);
|
||||
font-family: inherit;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.week-nav-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border: none;
|
||||
border-radius: 12px;
|
||||
background: var(--button-secondaryFill);
|
||||
color: var(--text-secondary);
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.week-nav-btn:hover {
|
||||
background: var(--accent-15);
|
||||
color: var(--accent-accent);
|
||||
}
|
||||
|
||||
/* Responsive adjustments */
|
||||
@media (max-width: 1024px) {
|
||||
.timetable-grid {
|
||||
grid-template-columns: 60px repeat(5, minmax(200px, 1fr));
|
||||
}
|
||||
|
||||
.lesson-slot {
|
||||
min-height: 80px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.timetable-container {
|
||||
overflow-x: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
.lesson-card {
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.lesson-subject {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.lesson-teacher,
|
||||
.lesson-room {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Modal styles */
|
||||
.lesson-modal {
|
||||
display: none;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0,0,0,0.5);
|
||||
z-index: 1000;
|
||||
padding: 1rem;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s ease;
|
||||
}
|
||||
|
||||
.lesson-modal.show {
|
||||
display: flex;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
background: var(--card-card);
|
||||
border-radius: 24px;
|
||||
border-width: 0 !important;
|
||||
width: 100%;
|
||||
max-width: 500px;
|
||||
max-height: 90vh;
|
||||
overflow-y: auto;
|
||||
position: relative;
|
||||
transform: translateY(20px);
|
||||
opacity: 0;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.lesson-modal.show .modal-content {
|
||||
transform: translateY(0);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.modal-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 1.5rem;
|
||||
background: var(--button-secondaryFill);
|
||||
}
|
||||
|
||||
.modal-title {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.modal-close {
|
||||
background: none;
|
||||
border: none;
|
||||
color: var(--text-secondary);
|
||||
cursor: pointer;
|
||||
padding: 0.5rem;
|
||||
border-radius: 8px;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.modal-close:hover {
|
||||
background: var(--background);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
padding: 1.5rem;
|
||||
background-color: var(--button-secondaryFill);
|
||||
}
|
||||
|
||||
.lesson-details {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.detail-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
.detail-label {
|
||||
color: var(--text-secondary);
|
||||
font-weight: 500;
|
||||
min-width: 80px;
|
||||
}
|
||||
|
||||
.detail-value {
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.modal-section {
|
||||
margin-top: 1.5rem;
|
||||
padding-top: 1.5rem;
|
||||
border-top: 1px solid var(--background-0);
|
||||
}
|
||||
|
||||
.modal-section h4 {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
color: var(--text-primary);
|
||||
font-size: 16px;
|
||||
margin-bottom: 0.75rem;
|
||||
}
|
||||
|
||||
.homework-section h4 {
|
||||
color: var(--accent-accent);
|
||||
}
|
||||
|
||||
.test-section h4 {
|
||||
color: var(--warning-accent);
|
||||
}
|
||||
|
||||
.homework-content, .test-content {
|
||||
background: var(--card-translucent);
|
||||
padding: 1rem;
|
||||
border-radius: 8px;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
/* Animations */
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-20px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes dropdownShow {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-10px) scale(0.95);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0) scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes modalShow {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: scale(0.9);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Responsive adjustments */
|
||||
@media (max-width: 768px) {
|
||||
.kreta-header {
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.user-info {
|
||||
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;
|
||||
height: 8px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background: var(--background);
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: var(--text-secondary);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: var(--text-primary);
|
||||
}
|
||||
543
timetable/timetable.js
Normal file
@@ -0,0 +1,543 @@
|
||||
(() => {
|
||||
// Segédfüggvények
|
||||
function convertTimeToMinutes(timeStr) {
|
||||
const [hours, minutes] = timeStr.split(':').map(Number);
|
||||
return hours * 60 + minutes;
|
||||
}
|
||||
function getCookie(name) {
|
||||
const cookieName = `${name}=`;
|
||||
const decodedCookie = decodeURIComponent(document.cookie);
|
||||
const cookieArray = decodedCookie.split(';');
|
||||
|
||||
for(let i = 0; i < cookieArray.length; i++) {
|
||||
let cookie = cookieArray[i];
|
||||
while (cookie.charAt(0) === ' ') {
|
||||
cookie = cookie.substring(1);
|
||||
}
|
||||
if (cookie.indexOf(cookieName) === 0) {
|
||||
return cookie.substring(cookieName.length, cookie.length);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function shortenSchoolName(name, maxLength = 50) {
|
||||
if (!name) return '';
|
||||
if (name.length <= maxLength) return name;
|
||||
|
||||
const parts = name.split(' - ');
|
||||
if (parts.length === 2) {
|
||||
const [code, fullName] = parts;
|
||||
if (fullName.length > maxLength - code.length - 3) {
|
||||
return `${code} - ${fullName.substring(0, maxLength - code.length - 6)}...`;
|
||||
}
|
||||
}
|
||||
return name.substring(0, maxLength - 3) + '...';
|
||||
}
|
||||
|
||||
function showLoadingScreen() {
|
||||
const loadingScreen = document.createElement('div');
|
||||
loadingScreen.className = 'loading-screen';
|
||||
loadingScreen.innerHTML = `
|
||||
<img src="https://i.imgur.com/JE3LzRc.gif" alt="Firka" class="loading-logo">
|
||||
<div class="loading-text">Betöltés alatt...</div>
|
||||
<p class="loading-text2">Kis türelmet!</p>
|
||||
`;
|
||||
document.body.appendChild(loadingScreen);
|
||||
}
|
||||
|
||||
function hideLoadingScreen() {
|
||||
const loadingScreen = document.querySelector('.loading-screen');
|
||||
if (loadingScreen) {
|
||||
loadingScreen.style.opacity = '0';
|
||||
loadingScreen.style.transition = 'opacity 0.3s ease';
|
||||
setTimeout(() => loadingScreen.remove(), 300);
|
||||
}
|
||||
}
|
||||
|
||||
// DOM elemek várása
|
||||
function waitForElement(selector) {
|
||||
return new Promise(resolve => {
|
||||
if (document.querySelector(selector)) {
|
||||
return resolve(document.querySelector(selector));
|
||||
}
|
||||
|
||||
const observer = new MutationObserver(mutations => {
|
||||
if (document.querySelector(selector)) {
|
||||
observer.disconnect();
|
||||
resolve(document.querySelector(selector));
|
||||
}
|
||||
});
|
||||
|
||||
observer.observe(document.body, {
|
||||
childList: true,
|
||||
subtree: true
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Órarendi adatok gyűjtése
|
||||
async function collectTimetableData() {
|
||||
await waitForElement('#Calendar');
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
|
||||
const calendar = document.querySelector('#Calendar');
|
||||
const dates = Array.from(document.querySelectorAll('.fc-day-header')).map(header => {
|
||||
const fullText = header.textContent.trim();
|
||||
// Remove the day name from the beginning and clean up the format
|
||||
const dateText = fullText.replace(/^(hétfő|kedd|szerda|csütörtök|péntek)/, '').trim();
|
||||
return {
|
||||
date: fullText,
|
||||
formattedDate: dateText
|
||||
};
|
||||
});
|
||||
// Fix the Thursday issue by ensuring we have all 5 days
|
||||
if (dates.length === 4) {
|
||||
// Get Wednesday's date parts
|
||||
const wedDate = dates[2].formattedDate;
|
||||
const [month, day] = wedDate.split(' ');
|
||||
const dayNum = parseInt(day.replace('.', ''));
|
||||
|
||||
// Create Thursday's date
|
||||
const thursdayDate = `${month} ${dayNum + 1}.`;
|
||||
|
||||
dates.splice(3, 0, {
|
||||
date: `csütörtök${thursdayDate}`,
|
||||
formattedDate: thursdayDate
|
||||
});
|
||||
}
|
||||
// Set week selector based on the current date
|
||||
const weekOptions = Array.from(document.querySelectorAll('#Calendar_tanevHetek_listbox li'));
|
||||
const currentDate = dates[0]?.formattedDate; // Using Monday's date
|
||||
const matchingWeek = weekOptions.find(opt => opt.textContent.includes(currentDate));
|
||||
|
||||
if (matchingWeek) {
|
||||
const kendoCombo = document.querySelector('#Calendar_tanevHetek')?.__kendoWidget;
|
||||
if (kendoCombo) {
|
||||
const weekIndex = weekOptions.indexOf(matchingWeek);
|
||||
kendoCombo.value(weekIndex.toString());
|
||||
kendoCombo.trigger('change');
|
||||
}
|
||||
}
|
||||
const timetableData = {
|
||||
schoolInfo: {
|
||||
name: getCookie('schoolName') || 'Iskola',
|
||||
id: getCookie('schoolCode') || ''
|
||||
},
|
||||
userData: {
|
||||
name: getCookie('userName') || 'Felhasználó',
|
||||
time: document.querySelector('.usermenu_timer')?.textContent?.trim() || '45:00'
|
||||
},
|
||||
weekInfo: {
|
||||
title: document.querySelector('.fc-center h2')?.textContent?.trim() || 'Hét',
|
||||
options: Array.from(document.querySelectorAll('#Calendar_tanevHetek_listbox li'))
|
||||
.map((li, i) => ({
|
||||
text: li.textContent.trim(),
|
||||
value: i.toString(),
|
||||
selected: li.classList.contains('k-state-selected')
|
||||
}))
|
||||
},
|
||||
weekDates: dates, // Add the dates to the data object
|
||||
lessons: []
|
||||
};
|
||||
|
||||
// Órák adatainak gyűjtése
|
||||
document.querySelectorAll('.fc-event').forEach(event => {
|
||||
const timeEl = event.querySelector('.fc-time');
|
||||
const titleEl = event.querySelector('.fc-title');
|
||||
|
||||
if (timeEl && titleEl) {
|
||||
const [startTime, endTime] = (timeEl.getAttribute('data-full') || timeEl.textContent || '').split(' - ');
|
||||
const [fullSubject, teacher, room] = titleEl.innerHTML.split('<br>').map(str => str.trim());
|
||||
const subject = fullSubject.split('-')[0].trim();
|
||||
|
||||
timetableData.lessons.push({
|
||||
startTime,
|
||||
endTime,
|
||||
subject: subject || '',
|
||||
teacher: teacher || '',
|
||||
room: (room || '').replace(/[()]/g, ''),
|
||||
day: event.closest('td').cellIndex - 1,
|
||||
isSubstituted: event.querySelector('.fc-bg2') !== null,
|
||||
isCancelled: event.classList.contains('fc-textline-through'),
|
||||
hasHomework: titleEl.querySelector('.hasCalendarIcon') !== null,
|
||||
testInfo: event.getAttribute('data-tooltiptext') || '',
|
||||
homeworkDetails: event.getAttribute('data-homework') || ''
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return timetableData;
|
||||
}
|
||||
|
||||
// Grid generálása
|
||||
function generateTimeGrid(lessons, weekDates) {
|
||||
const times = [...new Set(lessons.map(l => l.startTime))].sort((a, b) => {
|
||||
const timeA = convertTimeToMinutes(a);
|
||||
const timeB = convertTimeToMinutes(b);
|
||||
return timeA - timeB;
|
||||
});
|
||||
const days = ['Hétfő', 'Kedd', 'Szerda', 'Csütörtök', 'Péntek'];
|
||||
|
||||
return `
|
||||
<div class="grid-header"></div>
|
||||
${days.map((day, index) => `
|
||||
<div class="grid-header">
|
||||
<span class="day-name">${day}</span>
|
||||
<span class="day-date">${weekDates[index]?.formattedDate || ''}</span>
|
||||
</div>
|
||||
`).join('')}
|
||||
${times.map(time => `
|
||||
<div class="time-slot">${time}</div>
|
||||
${Array(5).fill().map((_, dayIndex) => {
|
||||
const dayLessons = lessons.filter(l => l.startTime === time && l.day === dayIndex);
|
||||
return `
|
||||
<div class="lesson-slot">
|
||||
${dayLessons.map(lesson => `
|
||||
<div class="lesson-card ${lesson.isSubstituted ? 'substituted' : ''}
|
||||
${lesson.isCancelled ? 'cancelled' : ''}
|
||||
${lesson.hasHomework ? 'has-homework' : ''}"
|
||||
data-lesson='${JSON.stringify(lesson)}'>
|
||||
<div class="lesson-subject">${lesson.subject}</div>
|
||||
<div class="lesson-teacher">${lesson.teacher}</div>
|
||||
<div class="lesson-bottom">
|
||||
<div class="lesson-room">${lesson.room}</div>
|
||||
<div class="lesson-time">${lesson.isCancelled ? 'Elmarad' : lesson.startTime}</div>
|
||||
</div>
|
||||
${lesson.hasHomework || lesson.testInfo ? `
|
||||
<div class="lesson-indicators">
|
||||
${lesson.hasHomework ? `
|
||||
<span class="lesson-indicator homework-indicator" title="Házi feladat">
|
||||
<span class="material-icons-round">assignment</span>
|
||||
</span>
|
||||
` : ''}
|
||||
${lesson.testInfo ? `
|
||||
<span class="lesson-indicator test-indicator" title="Számonkérés">
|
||||
<span class="material-icons-round">quiz</span>
|
||||
</span>
|
||||
` : ''}
|
||||
</div>
|
||||
` : ''}
|
||||
</div>
|
||||
`).join('')}
|
||||
</div>
|
||||
`;
|
||||
}).join('')}
|
||||
`).join('')}
|
||||
`;
|
||||
}
|
||||
// Óra részletek modal
|
||||
function showLessonModal(lesson) {
|
||||
const modal = document.createElement('div');
|
||||
modal.className = 'lesson-modal';
|
||||
modal.innerHTML = `
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title">${lesson.subject}</h3>
|
||||
<button class="modal-close">
|
||||
<span class="material-icons-round">close</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="lesson-details">
|
||||
<div class="detail-item">
|
||||
<span class="detail-label">Tanár:</span>
|
||||
<span class="detail-value">${lesson.teacher}</span>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<span class="detail-label">Terem:</span>
|
||||
<span class="detail-value">${lesson.room}</span>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<span class="detail-label">Időpont:</span>
|
||||
<span class="detail-value">${lesson.startTime} - ${lesson.endTime}</span>
|
||||
</div>
|
||||
${lesson.isSubstituted ? `
|
||||
<div class="detail-item">
|
||||
<span class="detail-label">Állapot:</span>
|
||||
<span class="detail-value"><span class="material-icons-round">sync_alt</span> Helyettesítés</span>
|
||||
</div>
|
||||
` : ''}
|
||||
${lesson.isCancelled ? `
|
||||
<div class="detail-item">
|
||||
<span class="detail-label">Állapot:</span>
|
||||
<span class="detail-value"><span class="material-icons-round">cancel</span> Elmarad</span>
|
||||
</div>
|
||||
` : ''}
|
||||
</div>
|
||||
|
||||
${lesson.hasHomework ? `
|
||||
<div class="modal-section homework-section">
|
||||
<h4>
|
||||
<span class="material-icons-round">assignment</span>
|
||||
Házi feladat
|
||||
</h4>
|
||||
<div class="homework-content">
|
||||
${lesson.homeworkDetails ? `<p>${lesson.homeworkDetails}</p>` : '<p>Van házi feladat</p>'}
|
||||
</div>
|
||||
</div>
|
||||
` : ''}
|
||||
${lesson.testInfo ? `
|
||||
<div class="modal-section test-section">
|
||||
<h4>
|
||||
<span class="material-icons-round">quiz</span>
|
||||
Számonkérés
|
||||
</h4>
|
||||
<div class="test-content">
|
||||
<p>${lesson.testInfo}</p>
|
||||
</div>
|
||||
</div>
|
||||
` : ''}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
document.body.appendChild(modal);
|
||||
|
||||
// Modal bezárás
|
||||
const closeModal = () => {
|
||||
modal.classList.remove('show');
|
||||
setTimeout(() => modal.remove(), 300);
|
||||
};
|
||||
|
||||
modal.querySelector('.modal-close').addEventListener('click', closeModal);
|
||||
modal.addEventListener('click', (e) => {
|
||||
if (e.target === modal) closeModal();
|
||||
});
|
||||
|
||||
// ESC gomb kezelése
|
||||
const handleEscape = (e) => {
|
||||
if (e.key === 'Escape') {
|
||||
closeModal();
|
||||
document.removeEventListener('keydown', handleEscape);
|
||||
}
|
||||
};
|
||||
document.addEventListener('keydown', handleEscape);
|
||||
|
||||
// Animáció
|
||||
requestAnimationFrame(() => {
|
||||
modal.classList.add('show');
|
||||
});
|
||||
}
|
||||
|
||||
// Eseménykezelők beállítása
|
||||
function setupEventListeners(data) {
|
||||
// Órakártyák
|
||||
document.querySelectorAll('.lesson-card').forEach(card => {
|
||||
card.addEventListener('click', () => {
|
||||
const lessonData = JSON.parse(card.dataset.lesson);
|
||||
showLessonModal(lessonData);
|
||||
});
|
||||
});
|
||||
|
||||
// Felhasználói menü
|
||||
const userBtn = document.querySelector('.user-dropdown-btn');
|
||||
const userDropdown = document.querySelector('.user-dropdown');
|
||||
|
||||
userBtn?.addEventListener('click', (e) => {
|
||||
e.stopPropagation();
|
||||
userDropdown?.classList.toggle('show');
|
||||
});
|
||||
|
||||
document.addEventListener('click', () => {
|
||||
userDropdown?.classList.remove('show');
|
||||
});
|
||||
|
||||
// Hét navigáció
|
||||
const prevBtn = document.querySelector('.prev-week');
|
||||
const nextBtn = document.querySelector('.next-week');
|
||||
const weekSelect = document.querySelector('.week-select');
|
||||
|
||||
prevBtn?.addEventListener('click', async () => {
|
||||
showLoadingScreen();
|
||||
const kendoCalendar = document.querySelector('#Calendar')?.__kendoWidget;
|
||||
if (kendoCalendar) {
|
||||
kendoCalendar.prev();
|
||||
await new Promise(resolve => setTimeout(resolve, 500));
|
||||
await transformTimetablePage();
|
||||
}
|
||||
});
|
||||
|
||||
nextBtn?.addEventListener('click', async () => {
|
||||
showLoadingScreen();
|
||||
const kendoCalendar = document.querySelector('#Calendar')?.__kendoWidget;
|
||||
if (kendoCalendar) {
|
||||
kendoCalendar.next();
|
||||
await new Promise(resolve => setTimeout(resolve, 500));
|
||||
await transformTimetablePage();
|
||||
}
|
||||
});
|
||||
|
||||
weekSelect?.addEventListener('change', async function() {
|
||||
showLoadingScreen();
|
||||
const kendoCombo = document.querySelector('#Calendar_tanevHetek')?.__kendoWidget;
|
||||
if (kendoCombo) {
|
||||
kendoCombo.value(this.value);
|
||||
kendoCombo.trigger('change');
|
||||
await new Promise(resolve => setTimeout(resolve, 500));
|
||||
await transformTimetablePage();
|
||||
}
|
||||
});
|
||||
|
||||
// Kijelentkezés időzítő
|
||||
const startTime = parseInt(data.userData.time?.match(/\d+/)?.[0] || "45");
|
||||
let timeLeft = startTime * 60;
|
||||
|
||||
const updateTimer = () => {
|
||||
const minutes = Math.floor(timeLeft / 60);
|
||||
const seconds = timeLeft % 60;
|
||||
const timerEl = document.getElementById('logoutTimer');
|
||||
if (timerEl) {
|
||||
timerEl.textContent = `${minutes}:${seconds.toString().padStart(2, '0')}`;
|
||||
}
|
||||
|
||||
if (timeLeft <= 0) {
|
||||
window.location.href = '/Home/Logout';
|
||||
} else {
|
||||
timeLeft--;
|
||||
}
|
||||
};
|
||||
|
||||
updateTimer();
|
||||
setInterval(updateTimer, 1000);
|
||||
}
|
||||
|
||||
// Oldal transzformáció
|
||||
async function transformTimetablePage() {
|
||||
try {
|
||||
showLoadingScreen();
|
||||
|
||||
const data = await collectTimetableData();
|
||||
if (!data) {
|
||||
hideLoadingScreen();
|
||||
return;
|
||||
}
|
||||
|
||||
const schoolNameFull = `${data.schoolInfo.id} - ${data.schoolInfo.name}`;
|
||||
const shortenedSchoolName = shortenSchoolName(schoolNameFull);
|
||||
|
||||
document.body.innerHTML = `
|
||||
<div class="kreta-container">
|
||||
<header class="kreta-header">
|
||||
<div class="school-info">
|
||||
<p class="logo-text">
|
||||
<img src="${chrome.runtime.getURL('images/firka_logo.png')}" alt="Firka" class="logo">
|
||||
Firka
|
||||
</p>
|
||||
<div class="school-details" title="${schoolNameFull}">
|
||||
${shortenedSchoolName}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<nav class="kreta-nav">
|
||||
<div class="nav-links">
|
||||
<a href="/Intezmeny/Faliujsag" data-page="dashboard" class="nav-item">
|
||||
<img src="${chrome.runtime.getURL('icons/dashboard-inactive.svg')}" alt="Kezdőlap">
|
||||
Kezdőlap
|
||||
</a>
|
||||
<a href="/TanuloErtekeles/Osztalyzatok" data-page="grades" class="nav-item">
|
||||
<img src="${chrome.runtime.getURL('icons/grades-inactive.svg')}" alt="Jegyek">
|
||||
Jegyek
|
||||
</a>
|
||||
<a href="/Orarend/InformaciokOrarend" data-page="timetable" class="nav-item active">
|
||||
<img src="${chrome.runtime.getURL('icons/timetable-active.svg')}" alt="Órarend">
|
||||
Órarend
|
||||
</a>
|
||||
<a href="/Hianyzas/Hianyzasok" data-page="absences" class="nav-item">
|
||||
<img src="${chrome.runtime.getURL('icons/absences-inactive.svg')}" alt="Mulasztások">
|
||||
Mulasztások
|
||||
</a>
|
||||
<a href="/Tanulo/TanuloHaziFeladat" data-page="other" class="nav-item">
|
||||
<img src="${chrome.runtime.getURL('icons/others.svg')}" alt="Egyéb">
|
||||
Egyéb
|
||||
</a>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="user-profile">
|
||||
<button class="user-dropdown-btn">
|
||||
<div class="user-info">
|
||||
<span class="user-name">${data.userData.name}</span>
|
||||
<span class="nav-logout-timer" id="logoutTimer">${data.userData.time}</span>
|
||||
</div>
|
||||
</button>
|
||||
<div class="user-dropdown">
|
||||
<a href="/Adminisztracio/Profil" data-page="profile" class="dropdown-item">
|
||||
<img src="${chrome.runtime.getURL('icons/profile.svg')}" alt="Profil">
|
||||
Profil
|
||||
</a>
|
||||
<a href="#" class="dropdown-item" id="settingsBtn">
|
||||
<img src="${chrome.runtime.getURL('icons/settings.svg')}" alt="Beállítások">
|
||||
Beállítások
|
||||
</a>
|
||||
<a href="/Home/Logout" data-page="logout" class="dropdown-item">
|
||||
<img src="${chrome.runtime.getURL('icons/logout.svg')}" alt="Kijelentkezés">
|
||||
Kijelentkezés
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main class="kreta-main">
|
||||
<div class="week-controls">
|
||||
<button class="week-nav-btn prev-week">
|
||||
<span class="material-icons-round">chevron_left</span>
|
||||
</button>
|
||||
<select class="week-select">
|
||||
${data.weekInfo.options.map(opt => `
|
||||
<option value="${opt.value}" ${opt.selected ? 'selected' : ''}>
|
||||
${opt.text}
|
||||
</option>
|
||||
`).join('')}
|
||||
</select>
|
||||
<button class="week-nav-btn next-week">
|
||||
<span class="material-icons-round">chevron_right</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="timetable-container">
|
||||
<div class="timetable-grid">
|
||||
${generateTimeGrid(data.lessons, data.weekDates)}
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// Szükséges fontok hozzáadása
|
||||
const links = [
|
||||
{ rel: 'preconnect', href: 'https://fonts.googleapis.com' },
|
||||
{ rel: 'preconnect', href: 'https://fonts.gstatic.com', crossorigin: true },
|
||||
{ rel: 'stylesheet', href: 'https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap' },
|
||||
{ rel: 'stylesheet', href: 'https://fonts.googleapis.com/icon?family=Material+Icons+Round' }
|
||||
];
|
||||
|
||||
links.forEach(link => {
|
||||
const linkElement = document.createElement('link');
|
||||
Object.entries(link).forEach(([key, value]) => {
|
||||
linkElement[key] = value;
|
||||
});
|
||||
document.head.appendChild(linkElement);
|
||||
});
|
||||
|
||||
setupEventListeners(data);
|
||||
hideLoadingScreen();
|
||||
|
||||
} catch (error) {
|
||||
console.error('Hiba az oldal átalakítása során:', error);
|
||||
hideLoadingScreen();
|
||||
}
|
||||
}
|
||||
|
||||
// Beállítások gomb kezelése
|
||||
document.getElementById('settingsBtn')?.addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
const url = chrome.runtime.getURL('settings/index.html');
|
||||
window.open(url, '_blank', 'width=400,height=600');
|
||||
});
|
||||
|
||||
if (window.location.href.includes('/Orarend/')) {
|
||||
transformTimetablePage();
|
||||
}
|
||||
})();
|
||||