1
0
Fork 0
forked from Fuji/Fuji
Fuji/src/main.py

398 lines
No EOL
13 KiB
Python

import json
import pickle
import base64
import gettext
import keyring
import threading
import configparser
import flet as ft
from i18n import *
from utils import *
from pages.home import *
from pages.exams import *
from pages.grades import *
from pages.homework import *
from pages.settings import *
from sqlitehandlernr import *
from pages.timetable import *
from pages.behaviour import *
from pages.attendance import *
from constants import defconf, usrconf
from sdk.src.interfaces.prometheus.context import *
from sdk.src.interfaces.prometheus.interface import *
config = configparser.ConfigParser()
def sync(page: ft.Page):
auth_context_raw = loadauth("Fuji", "Auth Context")
auth_context = PrometheusAuthContext.model_validate_json(auth_context_raw)
interface = PrometheusInterface(
auth_context=auth_context,
student_context=None,
)
try:
interface.login()
except NoLoggedInException:
print("NoLoggedInException, or in other words, vulcan shitted itself.")
exit()
students = interface.get_students()
student = int(keyring.get_password("Fuji", "Student_Index"))
interface.select_student(students[student].context)
auth_context = interface.get_auth_context()
jsoncontext = auth_context.model_dump_json()
saveauth("Fuji", "Auth Context", jsoncontext)
student = students[student]
current_period = next(period for period in student.periods if period.current)
grades = interface.get_grades(current_period.number)
notes = interface.get_notes()
create_notes_database(notes_list=notes)
create_grades_database(grades_list=grades)
def change_page(route):
routes = {
"/": HomePage(),
"/grades": GradesPage(page),
"/timetable": TimetablePage(),
"/homework": HomeworkPage(),
"/exams": ExamsPage(),
"/attendance": AttendancePage(),
"/behaviour": BehaviourPage(),
"/settings": SettingsPage(page)
}
page.views.clear()
view = ft.View(route, [
ft.Row([
bar,
ft.Container(content=routes.get(route, HomePage()), expand=True)
], expand=True)
])
page.views.append(view)
page.update()
change_page(page.route)
def main(page: ft.Page):
global bar
# Page settings
page.title = "Fuji"
page.theme = ft.Theme(
color_scheme_seed=getattr(ft.Colors, getthemecolor()),
font_family="Roboto",
page_transitions=ft.PageTransitionsTheme(
macos=ft.PageTransitionTheme.NONE,
linux=ft.PageTransitionTheme.NONE,
windows=ft.PageTransitionTheme.NONE
),
)
# Sync
s = threading.Thread(target=sync, args=(page,))
s.start()
# Page routing
def change_page(route):
routes = {
"/": HomePage(),
"/grades": GradesPage(page),
"/timetable": TimetablePage(),
"/homework": HomeworkPage(),
"/exams": ExamsPage(),
"/attendance": AttendancePage(),
"/behaviour": BehaviourPage(),
"/settings": SettingsPage(page)
}
page.views.clear()
view = ft.View(route, [
ft.Row([
bar,
ft.Container(content=routes.get(route, HomePage()), expand=True)
], expand=True)
])
page.views.append(view)
page.update()
def on_route_change(e):
change_page(e.route)
# Navigation bar
bar = ft.NavigationRail(
selected_index=0,
label_type=ft.NavigationRailLabelType.ALL,
extended=False,
min_width=50,
min_extended_width=400,
group_alignment=0,
destinations=[
ft.NavigationRailDestination(icon=ft.Icons.HOME_OUTLINED, selected_icon=ft.Icons.HOME, label=(_("Home"))),
ft.NavigationRailDestination(icon=ft.Icons.LOOKS_6_OUTLINED, selected_icon=ft.Icons.LOOKS_6, label=(_("Grades"))),
ft.NavigationRailDestination(icon=ft.Icons.BACKPACK_OUTLINED, selected_icon=ft.Icons.BACKPACK, label=(_("Timetable"))),
ft.NavigationRailDestination(icon=ft.Icons.BOOK_OUTLINED, selected_icon=ft.Icons.BOOK, label=(_("Homework"))),
ft.NavigationRailDestination(icon=ft.Icons.CALENDAR_TODAY_OUTLINED, selected_icon=ft.Icons.CALENDAR_TODAY, label=(_("Exams"))),
ft.NavigationRailDestination(icon=ft.Icons.EVENT_NOTE_OUTLINED, selected_icon=ft.Icons.EVENT_NOTE, label=(_("Attendance"))),
ft.NavigationRailDestination(icon=ft.Icons.STICKY_NOTE_2_OUTLINED, selected_icon=ft.Icons.STICKY_NOTE_2, label=(_("Behaviour"))),
ft.NavigationRailDestination(icon=ft.Icons.SETTINGS_OUTLINED, selected_icon=ft.Icons.SETTINGS_ROUNDED, label=(_("Settings"))),
],
on_change=lambda e: page.go([
"/",
"/grades",
"/timetable",
"/homework",
"/exams",
"/attendance",
"/behaviour",
"/settings"
][e.control.selected_index])
)
page.on_route_change = on_route_change
page.go("/")
def login(page: ft.Page):
# Page settings
page.title = "Log in"
page.theme = ft.Theme(
color_scheme_seed=ft.Colors.RED,
font_family="Roboto",
page_transitions=ft.PageTransitionsTheme(
android=ft.PageTransitionTheme.PREDICTIVE,
ios=ft.PageTransitionTheme.PREDICTIVE,
macos=ft.PageTransitionTheme.PREDICTIVE,
linux=ft.PageTransitionTheme.PREDICTIVE,
windows=ft.PageTransitionTheme.PREDICTIVE
)
)
interface = None
data = {"usr": None, "passwd": None}
# Saving credentials
def changeusr(e):
global usr
data["usr"] = e.control.value
#print(usr)
def changepasswd(e):
global passwd
data["passwd"] = e.control.value
#print(passwd)
# Login event
def loginev(e):
global interface
login = data["usr"]
password = data["passwd"]
if login and password:
interface = PrometheusInterface(auth_context=PrometheusAuthContext(prometheus_web_credentials=PrometheusWebCredentials(username=login, password=password)))
interface.login()
page.go("/students")
else:
print("No credentials!")
# Students fetching, dropdown and selection
def students():
global interface
students = interface.get_students()
def on_change(e):
selected_index = next((i for i, student in enumerate(students) if student.full_name == e.control.value), -1)
interface.select_student(students[selected_index].context)
keyring.set_password("Fuji", "Student_Index", str(selected_index))
auth_context = interface.get_auth_context()
jsoncontext = auth_context.model_dump_json()
saveauth("Fuji", "Auth Context", jsoncontext)
config.read(f"{getconfigpath()}/config.ini")
config['Settings']['isLogged'] = 'True'
config['User']['fullName'] = students[selected_index].full_name
config['User']['grade'] = students[selected_index].class_name
with open(f"{getconfigpath()}/config.ini", "w") as file:
config.write(file)
page.go("/start")
dropdown = ft.Dropdown(
label="Select a Student",
options=[
ft.dropdown.Option(student.full_name) for student in students
],
on_change=on_change,
width=300
)
return dropdown
# Page routing
def route_change(route):
page.views.clear()
# Welcome view
if page.route == "/login":
welcome_view = ft.View(
route="/login",
controls=[
ft.Container(
content=ft.Column(
[
ft.Image(
src="src/assets/logo.png",
width=256,
height=256,
fit=ft.ImageFit.CONTAIN,
border_radius=ft.border_radius.all(100000)
),
ft.Text(value=(_("Welcome to Fuji!")), size=64),
ft.Button(
(_("Get Started")),
scale=2.0,
width=230,
on_click=lambda e: page.go("/login/eduvulcan")
),
],
alignment=ft.MainAxisAlignment.CENTER,
horizontal_alignment=ft.CrossAxisAlignment.CENTER,
spacing=30
),
alignment=ft.alignment.center,
expand=True,
padding=ft.padding.all(20)
)
]
)
page.views.append(welcome_view)
# Login form view
elif page.route == "/login/eduvulcan":
login_view = ft.View(
route="/login/eduvulcan",
controls=[
ft.Container(
content=ft.Column(
[
ft.Text(value=(_("Log in")), size=32, weight="bold",
text_align=ft.TextAlign.CENTER),
ft.TextField(
label=(_("Username")),
autofill_hints=[ft.AutofillHint.USERNAME],
width=300,
on_change=changeusr
),
ft.TextField(
label=(_("Password")),
password=True,
can_reveal_password=True,
autofill_hints=[ft.AutofillHint.PASSWORD],
width=300,
on_change=changepasswd
),
ft.Button((_("Log in")), scale=1.25, width=250, on_click=loginev),
],
alignment=ft.MainAxisAlignment.CENTER,
horizontal_alignment=ft.CrossAxisAlignment.CENTER,
spacing=30
),
alignment=ft.alignment.center,
expand=True,
padding=ft.padding.all(20)
)
]
)
page.views.append(login_view)
# Students view
elif page.route == "/students":
students_view = ft.View(
route="/students",
controls=[
ft.Container(
content=ft.Column(
[
ft.Text(value=(_("Select a student")), size=32, weight="bold",
text_align=ft.TextAlign.CENTER),
students(),
],
alignment=ft.MainAxisAlignment.CENTER,
horizontal_alignment=ft.CrossAxisAlignment.CENTER,
spacing=30
),
alignment=ft.alignment.center,
expand=True,
padding=ft.padding.all(20)
)
]
)
page.views.append(students_view)
# Start view
elif page.route == "/start":
# start_view = ft.View(
restart(page)
page.update()
def view_pop(view):
page.views.pop()
top_view = page.views[-1]
page.go(top_view.route)
page.on_route_change = route_change
page.on_view_pop = view_pop
page.go("/login")
# App configuration
if __name__ == "__main__":
try:
config.read(f"{getconfigpath()}/config.ini")
isLogged = config['Settings']['isLogged']
match isLogged:
case 'True':
ft.app(target=main)
case 'False':
ft.app(target=login)
except (FileNotFoundError, KeyError):
os.makedirs(getconfigpath())
config['Settings'] = defconf
config['User'] = usrconf
with open(f"{getconfigpath()}/config.ini", "w") as file:
config.write(file)
ft.app(target=login)
except FileExistsError:
config['Settings'] = defconf
config['User'] = usrconf
with open(f"{getconfigpath()}/config.ini", "w") as file:
config.write(file)
ft.app(target=login)