Skip to content

Commit 59642cb

Browse files
committed
fix(v0.2.1): update release notes and profile stability behavior
1 parent eba72d6 commit 59642cb

7 files changed

Lines changed: 119 additions & 30 deletions

File tree

README.md

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,16 @@ Allows authorized users to create, edit, and manage document pages. Support for
3535

3636
---
3737

38-
## 💡 What's New (v0.2.1) - Stability Fixes
38+
## 💡 What's New (v0.2.1) - Stability & Profile Improvements
3939

40-
This patch release focuses on reliability fixes.
40+
This patch release improves reliability and profile editing behavior.
4141

42-
### 🛠 Fixed
42+
### 🛠 Improved
4343

44-
- Fixed a crash when opening the profile dialog if `username` is empty/null (`NoneType` error on `split`).
45-
- Hardened tag generation in the document editor for cases where document/page names are empty or null.
46-
- Added safer handling for malformed virtual category IDs in search/loading flows.
44+
- Fixed a crash when opening the profile window for accounts without a filled display name.
45+
- Improved reliability of profile data updates after backend deployment updates.
46+
- Improved handling of empty values in document and page names.
47+
- Improved stability of search and document loading in edge cases.
4748

4849
---
4950

README_RU.md

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,16 @@
3535

3636
---
3737

38-
## 💡 Что нового (v0.2.1) - Исправления стабильности
38+
## 💡 Что нового (v0.2.1) - Стабильность и профиль
3939

40-
Это патч-обновление сфокусировано на исправлениях надежности.
40+
Это патч-обновление повышает надежность и улучшает поведение при работе с профилем.
4141

42-
### 🛠 Исправлено
42+
### 🛠 Улучшено
4343

44-
- Исправлено падение при открытии окна профиля, если `username` пустой/null (ошибка `NoneType` при вызове `split`).
45-
- Усилена генерация тегов в редакторе документов для случаев, когда имена документа/страниц пустые или null.
46-
- Добавлена безопасная обработка некорректных виртуальных ID категорий в поиске и загрузке.
44+
- Исправлен сбой при открытии профиля для аккаунтов без заполненного отображаемого имени.
45+
- Повышена надежность обновления данных профиля после обновлений backend-сервиса.
46+
- Улучшена обработка пустых значений в названиях документов и страниц.
47+
- Повышена стабильность поиска и загрузки документов в пограничных сценариях.
4748

4849
---
4950

modules/main/mvc/main_controller.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -400,9 +400,13 @@ def _show_profile_dialog(self) -> None:
400400
)
401401

402402
if updated_data:
403+
current_user_id = user_data.get("id") or user_data.get("user_id")
404+
if current_user_id is None:
405+
current_user_id = self.model.get_current_user_id()
406+
403407
worker = APIWorker(
404408
self.model.update_user_profile,
405-
user_id=user_data['id'],
409+
user_id=current_user_id,
406410
data=updated_data
407411
)
408412
self.active_workers.add(worker)
@@ -446,13 +450,16 @@ def _on_department_selected(self, selected, deselected) -> None:
446450
if dept_id is not None and dept_id != self.model.current_department_id:
447451
self.model.current_department_id = dept_id
448452
self.model.current_category_id = None
449-
450-
# Explicitly clear documents to avoid showing stale data from previous department
451-
self._update_documents_list()
453+
452454
self._update_categories_list()
453-
455+
456+
# With active search keep previous table until new results arrive.
457+
# This avoids a blank table if the first request after idle fails.
454458
if self.view.get_search_text():
455459
self._on_search_lineedit_text_changed()
460+
else:
461+
# No search active: clear stale documents and load current category data.
462+
self._update_documents_list()
456463

457464
self._update_create_category_state()
458465
self._update_create_document_state()

modules/main/mvc/main_model.py

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ def get_user_data(self) -> dict | None:
4444
return None
4545

4646
data = self.api.get_user_data(token)
47+
data = self._normalize_user_data(data)
4748

4849
return data
4950

@@ -79,15 +80,38 @@ def get_full_user_data(self) -> dict | None:
7980
return None
8081

8182
# This might be the same as get_user_data, but let's assume it could be different
82-
return self.api.get_user_data(token)
83+
data = self.api.get_user_data(token)
84+
return self._normalize_user_data(data)
85+
86+
def get_current_user_id(self) -> int | None:
87+
"""Returns the currently logged-in user id from local session storage."""
88+
if self.mode == "guest":
89+
return None
90+
91+
last_logged = read_json(self.LOCAL_DIR_LAST_LOGGED)
92+
if not isinstance(last_logged, dict):
93+
return None
94+
95+
user_id = last_logged.get("user_id")
96+
if user_id is None:
97+
return None
98+
99+
try:
100+
return int(user_id)
101+
except (TypeError, ValueError):
102+
return None
83103

84104

85-
def update_user_profile(self, user_id: int, data: dict) -> dict:
105+
def update_user_profile(self, user_id: int | None, data: dict) -> dict:
86106
"""Updates the user's profile data."""
107+
resolved_user_id = user_id if user_id is not None else self.get_current_user_id()
108+
if resolved_user_id is None:
109+
raise ValueError("Cannot update profile: missing current user id")
110+
87111
# The data dict should contain 'username', 'department' (ID)
88112
return self._make_authorized_request(
89113
self.api.update_user_data,
90-
user_id=user_id,
114+
user_id=resolved_user_id,
91115
data=data
92116
)
93117

@@ -330,6 +354,18 @@ def _get_user_token(self) -> str | None:
330354
)
331355

332356
return access_token
357+
358+
@staticmethod
359+
def _normalize_user_data(data: dict | None) -> dict | None:
360+
"""Normalizes API user payload to a flat user dict."""
361+
if not isinstance(data, dict):
362+
return None
363+
364+
nested_user = data.get("user")
365+
if isinstance(nested_user, dict):
366+
return nested_user
367+
368+
return data
333369

334370

335371
def _get_departments(self) -> list[dict]:

tests/test_main.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,21 @@ def test_department_selection(self, controller):
8888
assert controller.model.current_category_id is None
8989
controller.view.update_categories.assert_called()
9090

91+
def test_department_selection_with_search_does_not_clear_table(self, controller):
92+
"""With active search, department switch should not clear table before search response."""
93+
mock_index = Mock()
94+
mock_index.data.return_value = 2
95+
mock_selection = Mock()
96+
mock_selection.indexes.return_value = [mock_index]
97+
controller.view.get_search_text.return_value = "query"
98+
99+
with patch.object(controller, "_update_documents_list") as mock_update_docs, \
100+
patch.object(controller, "_on_search_lineedit_text_changed") as mock_search_changed:
101+
controller._on_department_selected(mock_selection, None)
102+
103+
mock_update_docs.assert_not_called()
104+
mock_search_changed.assert_called_once()
105+
91106

92107
def test_category_selection(self, controller):
93108
"""Test selecting a category triggers document loading."""

tests/test_main_model.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
from unittest.mock import patch
2+
3+
from modules.main.mvc.main_model import MainModel
4+
5+
6+
class TestMainModel:
7+
def _build_model(self):
8+
with patch("modules.main.mvc.main_model.load_config", return_value={"base_url": "http://localhost"}), \
9+
patch("modules.main.mvc.main_model.get_app_data_dir"), \
10+
patch("modules.main.mvc.main_model.get_local_data_dir"):
11+
return MainModel(mode="auth")
12+
13+
def test_get_user_data_normalizes_nested_payload(self):
14+
model = self._build_model()
15+
model._get_user_token = lambda: "token"
16+
model.api.get_user_data = lambda token: {"user": {"id": 7, "email": "u@x.test"}}
17+
18+
data = model.get_user_data()
19+
20+
assert data == {"id": 7, "email": "u@x.test"}
21+
22+
def test_get_full_user_data_normalizes_nested_payload(self):
23+
model = self._build_model()
24+
model._get_user_token = lambda: "token"
25+
model.api.get_user_data = lambda token: {"user": {"id": 3, "username": "Test User"}}
26+
27+
data = model.get_full_user_data()
28+
29+
assert data == {"id": 3, "username": "Test User"}
30+
31+
def test_normalize_user_data_keeps_flat_payload(self):
32+
flat = {"id": 1, "email": "flat@x.test"}
33+
assert MainModel._normalize_user_data(flat) == flat
34+

utils/whats_new_modal.py

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,12 @@
1919
RELEASE_NOTES = {
2020
"0.2.1": [
2121
{
22-
"title": "Исправления стабильности",
22+
"title": "Стабильность и профиль",
2323
"items": [
24-
"Исправлено падение при открытии профиля, если username отсутствует (ошибка NoneType при split).",
25-
"Усилена обработка данных в генерации тегов: пустые/null имена документа и страниц больше не приводят к ошибкам.",
26-
"Добавлена безопасная обработка некорректных virtual ID категорий в поиске и загрузке документов.",
27-
],
28-
},
29-
{
30-
"title": "Качество и проверка",
31-
"items": [
32-
"Добавлены регрессионные тесты для случаев с null/некорректными значениями в критичных сценариях.",
24+
"Исправлен сбой при открытии профиля для аккаунтов без заполненного отображаемого имени.",
25+
"Повышена надежность обновления данных профиля после обновлений backend-сервиса.",
26+
"Улучшена обработка пустых значений в названиях документов и страниц.",
27+
"Повышена стабильность поиска и загрузки документов в пограничных сценариях.",
3328
],
3429
},
3530
],

0 commit comments

Comments
 (0)