Synchronize user data between local and server
This commit is contained in:
@@ -345,4 +345,8 @@ ADD_STUDENT_POPUP;Souhaitez-vous ajouter un nouvel élève ?;¿Desea añadir un
|
||||
ADD_DEVICE_POPUP;Souhaitez-vous ajouter un nouvel appareil ? Un élève sera créé automatiquement.;¿Desea añadir un nuevo dispositivo? Se creará un alumno automáticamente.;Gostaria de adicionar um novo dispositivo? Um aluno será criado automaticamente.
|
||||
DELETE_STUDENT_POPUP;Souhaitez-vous supprimer cet élève ? Cette action est définitive et entrainera la perte de la progression de cet élève.;¿Desea eliminar a este estudiante? Esta acción es definitiva y supondrá la pérdida del progreso de este alumno.;Deseja excluir esse aluno? Essa ação é definitiva e resultará na perda do progresso desse aluno.
|
||||
DELETE_STUDENT;Supprimer l'élève;Borrar estudiante;Excluir aluno
|
||||
CHANGE_DEVICE;Changer d'appareil;Cambiar de dispositivo;Trocar de dispositivo
|
||||
CHANGE_DEVICE;Changer d'appareil;Cambiar de dispositivo;Trocar de dispositivo
|
||||
SYNCHRONIZE_ACCOUNT;Synchroniser compte;Sincronizar cuenta;Sincronizar conta
|
||||
SYNC_CHOICE_POPUP;Conflit de données : serveur plus récent. Choisir une version.;Conflicto de datos: el servidor es m‡s reciente. Elige una versi—n.;Conflito de dados: servidor mais recente. Escolha uma vers‹o.
|
||||
SERVER_PRIORITY;Serveur;Servidor;Servidor
|
||||
LOCAL_PRIORITY;Locale;Local;Local
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -439,6 +439,8 @@ vertical_alignment = 1
|
||||
visible = false
|
||||
script = ExtResource("26_pm647")
|
||||
content_text = "NO_INTERNET_ACCESS"
|
||||
confirm_text_override = null
|
||||
cancel_text_override = null
|
||||
|
||||
[node name="TextureRect" type="TextureRect" parent="NoInternetPopup"]
|
||||
top_level = true
|
||||
|
||||
@@ -42,7 +42,7 @@ ORDER BY LessonNb")
|
||||
student_unlock.lesson_GPs = element.GPs
|
||||
student_unlock.lesson_number = element.LessonNb
|
||||
if not progression:
|
||||
Logger.debug("LessonUnlocks: User selected a student with no progression data")
|
||||
Logger.trace("LessonUnlocks: User selected a student with no progression data")
|
||||
return
|
||||
student_unlock.unlocks = progression.unlocks
|
||||
lesson_container.add_child(student_unlock)
|
||||
@@ -101,9 +101,10 @@ func _device_selection_refresh() -> void:
|
||||
|
||||
|
||||
func _device_button_pressed(device_id: int) -> void:
|
||||
device_selection_container.visible = false
|
||||
UserDataManager.teacher_settings.update_student_device(student, device_id)
|
||||
await teacher_settings.refresh_devices_tabs()
|
||||
device = device_id
|
||||
var resSet: Dictionary = await ServerManager.set_student_data(student, {"device_id": device_id})
|
||||
if resSet.code == 200:
|
||||
device_selection_container.visible = false
|
||||
UserDataManager.teacher_settings.update_student_device(student, device_id)
|
||||
await teacher_settings.refresh_devices_tabs()
|
||||
device = device_id
|
||||
if not resSet.success:
|
||||
Logger.trace("LessonUnlock: Device was updated locally for the student, but the network update failed.")
|
||||
|
||||
@@ -10,6 +10,10 @@ const device_tab_scene: PackedScene = preload("res://sources/menus/settings/devi
|
||||
@onready var devices_tab_container : TabContainer = %DevicesTabContainer
|
||||
@onready var lesson_unlocks: LessonUnlocks = $LessonUnlocks
|
||||
@onready var delete_popup: ConfirmPopup = %DeletePopup
|
||||
@onready var sync_choice_popup: ConfirmPopup = %SyncChoicePopup
|
||||
|
||||
@onready var account_type_option_button: OptionButton = %AccountTypeOptionButton
|
||||
@onready var education_method_option_button: OptionButton = %EducationMethodOptionButton
|
||||
|
||||
@onready var add_device_button: Button = %AddDeviceButton
|
||||
@onready var add_student_button: Button = %AddStudentButton
|
||||
@@ -20,6 +24,10 @@ const device_tab_scene: PackedScene = preload("res://sources/menus/settings/devi
|
||||
|
||||
var last_device_id: int = -1
|
||||
|
||||
var synchronizing: bool = false
|
||||
|
||||
var localStringTime: String= ""
|
||||
|
||||
func _ready() -> void:
|
||||
refresh_devices_tabs()
|
||||
|
||||
@@ -32,6 +40,26 @@ func _ready() -> void:
|
||||
|
||||
OpeningCurtain.open()
|
||||
lesson_unlocks.teacher_settings = self
|
||||
|
||||
account_type_option_button.select(UserDataManager.teacher_settings.account_type)
|
||||
education_method_option_button.select(UserDataManager.teacher_settings.education_method)
|
||||
|
||||
func _on_account_type_option_button_item_selected(index: int) -> void:
|
||||
if TeacherSettings.AccountType.values().has(index):
|
||||
UserDataManager.teacher_settings.account_type = index as TeacherSettings.AccountType
|
||||
UserDataManager.teacher_settings.last_modified = Time.get_datetime_string_from_system(true)
|
||||
UserDataManager.save_teacher_settings()
|
||||
else:
|
||||
Logger.warn("SettingsTeacherSettings: Cannot assign index %d to AccountType" % index)
|
||||
|
||||
|
||||
func _on_education_method_option_button_item_selected(index: int) -> void:
|
||||
if TeacherSettings.EducationMethod.values().has(index):
|
||||
UserDataManager.teacher_settings.education_method = index as TeacherSettings.EducationMethod
|
||||
UserDataManager.teacher_settings.last_modified = Time.get_datetime_string_from_system(true)
|
||||
UserDataManager.save_teacher_settings()
|
||||
else:
|
||||
Logger.warn("SettingsTeacherSettings: Cannot assign index %d to EducationMethod" % index)
|
||||
|
||||
|
||||
func refresh_devices_tabs() -> void:
|
||||
@@ -68,6 +96,47 @@ func _on_delete_button_pressed() -> void:
|
||||
delete_popup.show()
|
||||
|
||||
|
||||
func _on_synchronize_button_pressed() -> void:
|
||||
#synchronizing = false
|
||||
#await ServerManager.update_user_data(UserDataManager.teacher_settings, "2025-05-23T09:39:47", true)
|
||||
#return
|
||||
Logger.trace("SettingsTeacherSettings: Start synchronizing user data.")
|
||||
if synchronizing:
|
||||
Logger.trace("SettingsTeacherSettings: User synchronization already started, cancel double-call.")
|
||||
return
|
||||
synchronizing = true
|
||||
var resGetTeacherTimestamp: Dictionary = await ServerManager.get_user_data_timestamp()
|
||||
if resGetTeacherTimestamp.success:
|
||||
Logger.trace("SettingsTeacherSettings: Server timestamp for user data = " + str(resGetTeacherTimestamp.body["last_modified"]))
|
||||
else:
|
||||
Logger.trace("Cannot get server timestamp for user data. Canceling synchronization.")
|
||||
synchronizing = false
|
||||
return
|
||||
var unixTimeServer: int = Time.get_unix_time_from_datetime_string(resGetTeacherTimestamp.body["last_modified"] as String)
|
||||
|
||||
localStringTime = UserDataManager.teacher_settings.last_modified
|
||||
if localStringTime == "":
|
||||
var localResult: Dictionary = UserDataManager.get_latest_modification(UserDataManager.get_teacher_folder())
|
||||
if localResult.error == OK:
|
||||
localStringTime = Time.get_datetime_string_from_datetime_dict(localResult.modification_date as Dictionary, false)
|
||||
Logger.trace("SettingsTeacherSettings: Local user file timestamp = " + localStringTime)
|
||||
else:
|
||||
Logger.warn("SettingsTeacherSettings: Cannot find modification date for local user data: " + error_string(localResult.error as int))
|
||||
synchronizing = false
|
||||
return
|
||||
var localUnixTime: int = Time.get_unix_time_from_datetime_string(localStringTime)
|
||||
|
||||
if localUnixTime == unixTimeServer:
|
||||
Logger.trace("SettingsTeacherSettings: User data timestamp is the same in local and on server. No synchronization necessary")
|
||||
elif localUnixTime > unixTimeServer:
|
||||
_on_sync_choice_local()
|
||||
else:
|
||||
Logger.trace("SettingsTeacherSettings: Local user data timestamp is obsolete, we need to choose a priority")
|
||||
sync_choice_popup.show()
|
||||
return
|
||||
synchronizing = false
|
||||
|
||||
|
||||
func _on_delete_popup_accepted() -> void:
|
||||
var res: Dictionary = await ServerManager.delete_account()
|
||||
if res.code == 200:
|
||||
@@ -150,3 +219,37 @@ func update_student_name(student_code: int, student_name: String) -> void:
|
||||
student_panel.name_label.text = student_name
|
||||
return
|
||||
Logger.warn("SettingsTeacherSettings: update_student_name: student not found with code " + str(student_code))
|
||||
|
||||
|
||||
func _on_sync_choice_server() -> void:
|
||||
Logger.trace("SettingsTeacherSettings: Synchronization priority defined to server")
|
||||
var resGetUserData: Dictionary = await ServerManager.get_user_data()
|
||||
if resGetUserData.success:
|
||||
# {"email": "cvbn@yopmail.com", "account_type": 0, "education_method": 0, "created_at": "2025-05-15T12:27:34Z", "last_modified": "2025-05-22T14:05:42Z"}
|
||||
if resGetUserData.has("body"):
|
||||
var resultBody: Dictionary = resGetUserData.body
|
||||
if resultBody.has("account_type"):
|
||||
UserDataManager.teacher_settings.account_type = resultBody.account_type
|
||||
account_type_option_button.select(UserDataManager.teacher_settings.account_type)
|
||||
else:
|
||||
Logger.warn("SettingsTeacherSettings: user data received from the server has no account_type")
|
||||
if resultBody.has("education_method"):
|
||||
UserDataManager.teacher_settings.education_method = resultBody.education_method
|
||||
education_method_option_button.select(UserDataManager.teacher_settings.education_method)
|
||||
else:
|
||||
Logger.warn("SettingsTeacherSettings: user data received from the server has no education_method")
|
||||
else:
|
||||
Logger.warn("SettingsTeacherSettings: user data received from the server has no body")
|
||||
else:
|
||||
Logger.warn("SettingsTeacherSettings: Failed to get user data from the server")
|
||||
synchronizing = false
|
||||
|
||||
|
||||
func _on_sync_choice_local() -> void:
|
||||
Logger.trace("SettingsTeacherSettings: Synchronization priority defined to local")
|
||||
var resSetUserTimestamp: Dictionary = await ServerManager.update_user_data(UserDataManager.teacher_settings, localStringTime, true)
|
||||
if resSetUserTimestamp.success:
|
||||
Logger.trace("SettingsTeacherSettings: user data successfully sent to the server")
|
||||
else:
|
||||
Logger.warn("SettingsTeacherSettings: Failed to send update of user data to the server")
|
||||
synchronizing = false
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[gd_scene load_steps=9 format=3 uid="uid://ci7ueo06f24k3"]
|
||||
[gd_scene load_steps=10 format=3 uid="uid://ci7ueo06f24k3"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://cil0o87dsb7q4" path="res://sources/menus/settings/teacher_settings.gd" id="1_ojivk"]
|
||||
[ext_resource type="PackedScene" uid="uid://wdjp1sv55q4f" path="res://sources/menus/components/night_sky/night_sky.tscn" id="1_v06h8"]
|
||||
@@ -7,6 +7,7 @@
|
||||
[ext_resource type="Texture2D" uid="uid://tcapan0mj64o" path="res://assets/minigames/minigame_ui/graphic/button_back_disabled.png" id="5_e3piv"]
|
||||
[ext_resource type="PackedScene" uid="uid://bo7rpk4gebh24" path="res://sources/menus/settings/sound_settings_button.tscn" id="6_s8nbl"]
|
||||
[ext_resource type="PackedScene" uid="uid://bhdh5xfyauss0" path="res://sources/ui/Popup.tscn" id="7_jetb7"]
|
||||
[ext_resource type="Theme" uid="uid://dqjvrt5nrtwn1" path="res://resources/themes/kalulu_theme.tres" id="8_7h0sa"]
|
||||
[ext_resource type="PackedScene" uid="uid://qsvbq6ruc44v" path="res://sources/menus/settings/lesson_unlocks.tscn" id="9_mljfd"]
|
||||
|
||||
[node name="TeacherSettings" type="Control"]
|
||||
@@ -56,6 +57,19 @@ theme_override_constants/margin_right = 75
|
||||
[node name="VolumeButton" parent="InterfaceLeft/Container/VolumeContainer" instance=ExtResource("6_s8nbl")]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="SynchronizeButton" type="Button" parent="InterfaceLeft/Container"]
|
||||
layout_mode = 2
|
||||
theme_type_variation = &"FlatButton"
|
||||
theme_override_font_sizes/font_size = 40
|
||||
text = "SYNCHRONIZE_ACCOUNT"
|
||||
|
||||
[node name="DeletePopup" parent="InterfaceLeft/Container/SynchronizeButton" instance=ExtResource("7_jetb7")]
|
||||
visible = false
|
||||
content_text = "Voulez-vous vraiment supprimer votre compte ?
|
||||
Cette action est irréversible !"
|
||||
confirm_text_override = null
|
||||
cancel_text_override = null
|
||||
|
||||
[node name="DeleteButton" type="Button" parent="InterfaceLeft/Container"]
|
||||
layout_mode = 2
|
||||
theme_type_variation = &"DangerButton"
|
||||
@@ -67,6 +81,8 @@ unique_name_in_owner = true
|
||||
visible = false
|
||||
content_text = "Voulez-vous vraiment supprimer votre compte ?
|
||||
Cette action est irréversible !"
|
||||
confirm_text_override = null
|
||||
cancel_text_override = null
|
||||
|
||||
[node name="LogoutButton" type="Button" parent="InterfaceLeft/Container"]
|
||||
layout_mode = 2
|
||||
@@ -74,7 +90,7 @@ theme_override_font_sizes/font_size = 40
|
||||
text = "LOGOUT"
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="."]
|
||||
custom_minimum_size = Vector2(2112, 1800)
|
||||
custom_minimum_size = Vector2(1970, 1800)
|
||||
layout_mode = 1
|
||||
anchors_preset = 11
|
||||
anchor_left = 1.0
|
||||
@@ -84,6 +100,64 @@ offset_left = -632.0
|
||||
grow_horizontal = 0
|
||||
grow_vertical = 2
|
||||
|
||||
[node name="HSeparator" type="HSeparator" parent="VBoxContainer"]
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 50
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="AccountTypeLabel" type="Label" parent="VBoxContainer/HBoxContainer"]
|
||||
layout_mode = 2
|
||||
theme = ExtResource("8_7h0sa")
|
||||
theme_override_font_sizes/font_size = 70
|
||||
text = "ACCOUNT_TYPE"
|
||||
|
||||
[node name="VSeparator" type="VSeparator" parent="VBoxContainer/HBoxContainer"]
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 30
|
||||
|
||||
[node name="AccountTypeOptionButton" type="OptionButton" parent="VBoxContainer/HBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
theme = ExtResource("8_7h0sa")
|
||||
theme_override_font_sizes/font_size = 70
|
||||
item_count = 2
|
||||
popup/item_0/text = "TEACHER"
|
||||
popup/item_0/id = 0
|
||||
popup/item_1/text = "PARENT"
|
||||
popup/item_1/id = 1
|
||||
|
||||
[node name="VSeparator2" type="VSeparator" parent="VBoxContainer/HBoxContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
theme_override_constants/separation = 30
|
||||
|
||||
[node name="EducationMethodeLabel" type="Label" parent="VBoxContainer/HBoxContainer"]
|
||||
layout_mode = 2
|
||||
theme = ExtResource("8_7h0sa")
|
||||
theme_override_font_sizes/font_size = 70
|
||||
text = "EDUCATION_METHOD"
|
||||
|
||||
[node name="VSeparator3" type="VSeparator" parent="VBoxContainer/HBoxContainer"]
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 30
|
||||
|
||||
[node name="EducationMethodOptionButton" type="OptionButton" parent="VBoxContainer/HBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
theme = ExtResource("8_7h0sa")
|
||||
theme_override_font_sizes/font_size = 70
|
||||
item_count = 2
|
||||
popup/item_0/text = "METHOD_APP_ONLY"
|
||||
popup/item_0/id = 0
|
||||
popup/item_1/text = "METHOD_COMPLETE"
|
||||
popup/item_1/id = 1
|
||||
|
||||
[node name="HSeparator2" type="HSeparator" parent="VBoxContainer"]
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 50
|
||||
|
||||
[node name="DevicesTabContainer" type="TabContainer" parent="VBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
@@ -104,6 +178,7 @@ alignment = 2
|
||||
unique_name_in_owner = true
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
theme = ExtResource("8_7h0sa")
|
||||
theme_override_font_sizes/font_size = 70
|
||||
text = "SETTINGS_ADD_STUDENT"
|
||||
|
||||
@@ -111,6 +186,7 @@ text = "SETTINGS_ADD_STUDENT"
|
||||
unique_name_in_owner = true
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
theme = ExtResource("8_7h0sa")
|
||||
theme_override_font_sizes/font_size = 70
|
||||
text = "SETTINGS_ADD_DEVICE"
|
||||
|
||||
@@ -122,21 +198,37 @@ layout_mode = 1
|
||||
unique_name_in_owner = true
|
||||
visible = false
|
||||
content_text = "ADD_STUDENT_POPUP"
|
||||
confirm_text_override = null
|
||||
cancel_text_override = null
|
||||
|
||||
[node name="AddDevicePopup" parent="." instance=ExtResource("7_jetb7")]
|
||||
unique_name_in_owner = true
|
||||
visible = false
|
||||
content_text = "ADD_DEVICE_POPUP"
|
||||
confirm_text_override = null
|
||||
cancel_text_override = null
|
||||
|
||||
[node name="DeleteStudentPopup" parent="." instance=ExtResource("7_jetb7")]
|
||||
unique_name_in_owner = true
|
||||
visible = false
|
||||
content_text = "DELETE_STUDENT_POPUP"
|
||||
confirm_text_override = null
|
||||
cancel_text_override = null
|
||||
|
||||
[node name="SyncChoicePopup" parent="." instance=ExtResource("7_jetb7")]
|
||||
unique_name_in_owner = true
|
||||
visible = false
|
||||
content_text = "SYNC_CHOICE_POPUP"
|
||||
confirm_text_override = "SERVER_PRIORITY"
|
||||
cancel_text_override = "LOCAL_PRIORITY"
|
||||
|
||||
[connection signal="pressed" from="InterfaceLeft/Container/BackButton" to="." method="_on_back_button_pressed"]
|
||||
[connection signal="pressed" from="InterfaceLeft/Container/SynchronizeButton" to="." method="_on_synchronize_button_pressed"]
|
||||
[connection signal="accepted" from="InterfaceLeft/Container/SynchronizeButton/DeletePopup" to="." method="_on_delete_popup_accepted"]
|
||||
[connection signal="pressed" from="InterfaceLeft/Container/DeleteButton" to="." method="_on_delete_button_pressed"]
|
||||
[connection signal="accepted" from="InterfaceLeft/Container/DeleteButton/DeletePopup" to="." method="_on_delete_popup_accepted"]
|
||||
[connection signal="pressed" from="InterfaceLeft/Container/LogoutButton" to="." method="_on_logout_button_pressed"]
|
||||
[connection signal="item_selected" from="VBoxContainer/HBoxContainer/AccountTypeOptionButton" to="." method="_on_account_type_option_button_item_selected"]
|
||||
[connection signal="tab_changed" from="VBoxContainer/DevicesTabContainer" to="." method="_on_devices_tab_container_tab_changed"]
|
||||
[connection signal="pressed" from="VBoxContainer/InterfaceBottom/Container/AddStudentButton" to="." method="_on_add_student_button_pressed"]
|
||||
[connection signal="pressed" from="VBoxContainer/InterfaceBottom/Container/AddDeviceButton" to="." method="_on_add_device_button_pressed"]
|
||||
@@ -144,3 +236,5 @@ content_text = "DELETE_STUDENT_POPUP"
|
||||
[connection signal="accepted" from="AddStudentPopup" to="." method="_on_add_student_popup_accepted"]
|
||||
[connection signal="accepted" from="AddDevicePopup" to="." method="_on_add_device_popup_accepted"]
|
||||
[connection signal="accepted" from="DeleteStudentPopup" to="." method="_on_delete_student_popup_accepted"]
|
||||
[connection signal="accepted" from="SyncChoicePopup" to="." method="_on_sync_choice_server"]
|
||||
[connection signal="refused" from="SyncChoicePopup" to="." method="_on_sync_choice_local"]
|
||||
|
||||
@@ -10,6 +10,8 @@ gradient = SubResource("Gradient_22q4u")
|
||||
|
||||
[node name="Popup" type="CanvasLayer"]
|
||||
script = ExtResource("1_o3fd6")
|
||||
confirm_text_override = null
|
||||
cancel_text_override = null
|
||||
|
||||
[node name="TextureRect" type="TextureRect" parent="."]
|
||||
top_level = true
|
||||
|
||||
@@ -11,8 +11,15 @@ signal refused
|
||||
@onready var confirm_button: Button = %ConfirmButton
|
||||
@onready var cancel_button: Button = %CancelButton
|
||||
|
||||
@export var confirm_text_override: String = ""
|
||||
@export var cancel_text_override: String = ""
|
||||
|
||||
func _ready() -> void:
|
||||
_set_content_text(content_text)
|
||||
if confirm_text_override != "":
|
||||
_set_confirm_text(confirm_text_override)
|
||||
if cancel_text_override != "":
|
||||
_set_cancel_text(cancel_text_override)
|
||||
|
||||
|
||||
func _set_content_text(p_content_text: String) -> void:
|
||||
@@ -21,6 +28,14 @@ func _set_content_text(p_content_text: String) -> void:
|
||||
content_label.text = content_text
|
||||
|
||||
|
||||
func _set_confirm_text(p_content_text: String) -> void:
|
||||
confirm_button.text = p_content_text
|
||||
|
||||
|
||||
func _set_cancel_text(p_content_text: String) -> void:
|
||||
cancel_button.text = p_content_text
|
||||
|
||||
|
||||
func _on_confirm_button_pressed() -> void:
|
||||
accepted.emit()
|
||||
hide()
|
||||
|
||||
@@ -70,8 +70,27 @@ func get_language_pack_url(locale: String) -> Dictionary:
|
||||
return _response()
|
||||
|
||||
|
||||
func get_user_data_timestamp() -> Dictionary:
|
||||
await _get_request("get_user_data_timestamp", {})
|
||||
return _response()
|
||||
|
||||
|
||||
func get_user_data() -> Dictionary:
|
||||
await _get_request("get_user_data", {})
|
||||
return _response()
|
||||
|
||||
|
||||
func update_user_data(teacher: TeacherSettings, timestamp: String, force: bool = false) -> Dictionary:
|
||||
var data: Dictionary = {"account_type": teacher.account_type, "education_method": teacher.education_method ,"timestamp": timestamp}
|
||||
if force:
|
||||
data.merge({"force_sync": "YES"})
|
||||
await _post_json_request("update_user_data", data)
|
||||
return _response()
|
||||
|
||||
|
||||
# p_student must have a device key
|
||||
# it can contain a name, level and age key for parents
|
||||
# TODO POUR ADD / UPDATE / REMOVE STUDENT : RECUPERER LE TIMESTAMP POUR METTRE A JOUR LE USER
|
||||
func add_student(p_student: Dictionary) -> Dictionary:
|
||||
await _post_request("add_student", p_student)
|
||||
return _response()
|
||||
|
||||
@@ -45,7 +45,7 @@ func register(register_settings: TeacherSettings) -> bool:
|
||||
# Save the teacher settings on disk
|
||||
DirAccess.make_dir_recursive_absolute(get_teacher_folder())
|
||||
teacher_settings = register_settings
|
||||
_save_teacher_settings()
|
||||
save_teacher_settings()
|
||||
|
||||
return true
|
||||
|
||||
@@ -89,7 +89,7 @@ func login(infos: Dictionary) -> bool:
|
||||
teacher_settings = load(path) as TeacherSettings
|
||||
|
||||
teacher_settings.update_from_dict(infos)
|
||||
_save_teacher_settings()
|
||||
save_teacher_settings()
|
||||
|
||||
if teacher_settings.students.keys().size() == 1:
|
||||
set_device_id(teacher_settings.students.keys()[0] as int)
|
||||
@@ -268,7 +268,7 @@ func _load_teacher_settings() -> void:
|
||||
_device_settings.device_id = 0
|
||||
_save_device_settings()
|
||||
|
||||
func _save_teacher_settings() -> void:
|
||||
func save_teacher_settings() -> void:
|
||||
ResourceSaver.save(teacher_settings, get_teacher_settings_path())
|
||||
|
||||
func _delete_inexistants_students_saves() -> void:
|
||||
@@ -314,7 +314,7 @@ func update_configuration(configuration: Dictionary) -> bool:
|
||||
if teacher_settings.last_modified != configuration.last_modified:
|
||||
# Update the teacher resource
|
||||
teacher_settings.update_from_dict(configuration)
|
||||
_save_teacher_settings()
|
||||
save_teacher_settings()
|
||||
|
||||
# Check if the device still exists
|
||||
if not _device_settings.device_id in teacher_settings.students.keys():
|
||||
@@ -514,6 +514,60 @@ func move_user_device_folder(old_device: String, new_device: String, student_cod
|
||||
else:
|
||||
Logger.error("UserDataManager: The folder '%s' cannot be moved because it does no exists in %s." % [old_device, parentDirPath])
|
||||
return
|
||||
_save_teacher_settings()
|
||||
save_teacher_settings()
|
||||
|
||||
|
||||
func get_latest_modification(path: String) -> Dictionary:
|
||||
var result: Dictionary = {
|
||||
"error": OK,
|
||||
"modification_date": null
|
||||
}
|
||||
|
||||
if FileAccess.file_exists(path):
|
||||
var time: int = FileAccess.get_modified_time(path)
|
||||
if time > 0:
|
||||
result.modification_date = Time.get_datetime_dict_from_unix_time(time)
|
||||
else:
|
||||
result.error = ERR_CANT_OPEN
|
||||
return result
|
||||
|
||||
if not DirAccess.dir_exists_absolute(path):
|
||||
result.error = ERR_DOES_NOT_EXIST
|
||||
return result
|
||||
|
||||
var latest_time: int = 0
|
||||
latest_time = _scan_dir_recursive(path, latest_time)
|
||||
|
||||
if latest_time > 0:
|
||||
result.modification_date = Time.get_datetime_dict_from_unix_time(latest_time)
|
||||
else:
|
||||
result.error = ERR_FILE_NOT_FOUND # Aucun fichier trouvé
|
||||
|
||||
return result
|
||||
|
||||
|
||||
func _scan_dir_recursive(dir_path: String, latest_time: int) -> int:
|
||||
var dir: DirAccess = DirAccess.open(dir_path)
|
||||
if dir == null:
|
||||
return latest_time
|
||||
|
||||
dir.list_dir_begin()
|
||||
while true:
|
||||
var dirName: String = dir.get_next()
|
||||
if dirName == "":
|
||||
break
|
||||
if dirName.begins_with("."):
|
||||
continue
|
||||
|
||||
var full_path: String = dir_path.path_join(dirName)
|
||||
if dir.current_is_dir():
|
||||
latest_time = _scan_dir_recursive(full_path, latest_time)
|
||||
else:
|
||||
var time: int = FileAccess.get_modified_time(full_path)
|
||||
if time > latest_time:
|
||||
latest_time = time
|
||||
dir.list_dir_end()
|
||||
|
||||
return latest_time
|
||||
|
||||
#endregion
|
||||
|
||||
Reference in New Issue
Block a user