From 65b6698aa82cbc22b99f6157e6f6287562751327 Mon Sep 17 00:00:00 2001
From: Martin Mares <mj@ucw.cz>
Date: Sat, 12 Apr 2025 20:26:06 +0200
Subject: [PATCH] =?UTF-8?q?T=C5=99=C3=ADd=C4=9Bn=C3=AD=20rol=C3=AD=20u?=
 =?UTF-8?q?=C5=BEivatele?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Closes #442.
---
 mo/web/org_users.py            | 10 +++++++++-
 mo/web/templates/org_org.html  |  2 +-
 mo/web/templates/org_orgs.html |  2 +-
 3 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/mo/web/org_users.py b/mo/web/org_users.py
index f0abd8eb..6687a5bc 100644
--- a/mo/web/org_users.py
+++ b/mo/web/org_users.py
@@ -5,7 +5,7 @@ from flask_wtf import FlaskForm
 from sqlalchemy import or_, select, Column
 from sqlalchemy.orm import joinedload, subqueryload
 from sqlalchemy.orm.query import Query
-from typing import Optional, Set, Union, List, Tuple
+from typing import Optional, Set, Union, List, Tuple, Sequence
 import urllib.parse
 import werkzeug.exceptions
 import wtforms
@@ -29,6 +29,12 @@ from mo.web.imports import ImportForm, generic_import_page
 from mo.web.util import PagerForm
 
 
+def sorted_user_roles(roles: Sequence[db.UserRole]) -> List[db.UserRole]:
+    # Používá se ve výpisech rolí jednoho uživatele.
+    # Doporučujeme preloadnout UserRole.place.
+    return sorted(roles, key=lambda ur: (ur.year or 0, ur.seq or 0, mo.rights.role_order_by_type[ur.role], ur.place.level, ur.category or "", ur.user_role_id))
+
+
 class UsersFilterForm(PagerForm):
     # user
     search_name = mo_fields.String("Jméno/příjmení", render_kw={'autofocus': True})
@@ -280,6 +286,7 @@ def org_orgs() -> str:
             can_edit=rr.have_right(Right.edit_orgs),
             can_add=rr.have_right(Right.add_orgs),
             can_send_email=rr.can_send_email(count),
+            sorted_user_roles=sorted_user_roles,
         )
 
 
@@ -411,6 +418,7 @@ def org_org(id: int):
         roles_by_type=mo.rights.roles_by_type, role_errors=role_errors,
         form_add_role=form_add_role, form_remove_role=form_remove_role,
         resend_invite_form=resend_invite_form,
+        sorted_user_roles=sorted_user_roles,
     )
 
 
diff --git a/mo/web/templates/org_org.html b/mo/web/templates/org_org.html
index adce580d..6d99a700 100644
--- a/mo/web/templates/org_org.html
+++ b/mo/web/templates/org_org.html
@@ -54,7 +54,7 @@
 			<th>Role<th>Oblast<th>Ročník<th>Kategorie<th class='has-tip' title='Pořadí kola v kategorii'>Kolo<th>Přidělil<th>Akce
 		</tr>
 	</thead>
-{% for role in user.roles %}
+{% for role in sorted_user_roles(user.roles) %}
 	<tr>
 		<td>{{ roles_by_type[role.role].name }}
 		<td><a href="{{ url_for('org_place', id=role.place_id) }}">{{ role.place.type_name() + ": " + role.place.name or '*' }}</a>
diff --git a/mo/web/templates/org_orgs.html b/mo/web/templates/org_orgs.html
index 5ee560b4..a069834a 100644
--- a/mo/web/templates/org_orgs.html
+++ b/mo/web/templates/org_orgs.html
@@ -85,7 +85,7 @@
 		<td>{% if user.is_system %}systémový uživatel{% elif user.is_admin %}správce{% elif user.roles|count == 0 %}<i>žádná role</i>{% endif %}
 			{% if user.roles|count > 0 %}
 			<ul>
-			{% for role in user.roles %}
+			{% for role in sorted_user_roles(user.roles) %}
 				{% if role.user_role_id in marked_roles_id %}
 					<li><b>{{ role }}</b></li>
 				{% else %}
-- 
GitLab