django-microsys 2.2.3__tar.gz → 2.2.5__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (274) hide show
  1. {django_microsys-2.2.3 → django_microsys-2.2.5}/PKG-INFO +2 -1
  2. {django_microsys-2.2.3 → django_microsys-2.2.5}/django_microsys.egg-info/PKG-INFO +2 -1
  3. {django_microsys-2.2.3 → django_microsys-2.2.5}/django_microsys.egg-info/SOURCES.txt +10 -0
  4. django_microsys-2.2.5/microsys/VERSION +1 -0
  5. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/api.py +11 -1
  6. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/constants.py +6 -0
  7. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/context_processors.py +13 -0
  8. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/discovery.py +56 -14
  9. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/forms.py +217 -39
  10. django_microsys-2.2.5/microsys/management/commands/microsys_settings.py +136 -0
  11. django_microsys-2.2.5/microsys/migrations/0006_systemsettings_navbar_config.py +19 -0
  12. django_microsys-2.2.5/microsys/migrations/0007_systemsettings_prevent_multiple_active_sessions.py +18 -0
  13. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/models.py +15 -0
  14. django_microsys-2.2.5/microsys/navbar.py +247 -0
  15. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/scaffold_templates/project/compose.yml.tmpl +1 -0
  16. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/helpers/wizard/js/main.js +29 -0
  17. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/main/css/main.css +25 -0
  18. django_microsys-2.2.5/microsys/static/microsys/main/css/navbar.css +106 -0
  19. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/main/css/options.css +115 -21
  20. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/main/css/system_setup.css +282 -0
  21. django_microsys-2.2.5/microsys/static/microsys/main/js/navbar.js +163 -0
  22. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/main/js/options.js +27 -0
  23. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/main/js/system_setup.js +614 -18
  24. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/sidebar/css/main.css +35 -0
  25. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/themes/css/gothic.css +8 -0
  26. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/themes/css/mono.css +19 -4
  27. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/themes/css/neon.css +5 -5
  28. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/themes/css/retro.css +8 -0
  29. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/themes/js/main.js +81 -3
  30. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/users/js/profile_2fa.js +166 -69
  31. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/templates/microsys/base.html +9 -6
  32. django_microsys-2.2.5/microsys/templates/microsys/includes/navbar.html +22 -0
  33. django_microsys-2.2.5/microsys/templates/microsys/includes/navbar_builder.html +55 -0
  34. django_microsys-2.2.5/microsys/templates/microsys/includes/navbar_mode_previews.html +30 -0
  35. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/templates/microsys/includes/options.html +82 -27
  36. django_microsys-2.2.5/microsys/templates/microsys/includes/system_setup.html +79 -0
  37. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/templates/microsys/includes/theme_settings_matrix.html +2 -0
  38. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/templates/microsys/sidebar/extra_groups.html +2 -2
  39. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/templates/microsys/sidebar/main.html +1 -1
  40. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/templates/microsys/sidebar/tree.html +2 -2
  41. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/templates/microsys/users/profile.html +25 -5
  42. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/templatetags/microsys_tags.py +28 -0
  43. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/translations.py +141 -10
  44. django_microsys-2.2.5/microsys/trust.py +227 -0
  45. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/urls.py +1 -0
  46. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/utils.py +292 -6
  47. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/views/__init__.py +1 -1
  48. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/views/general.py +39 -3
  49. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/views/profile.py +74 -20
  50. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/views/sections.py +1 -1
  51. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/views/twofa.py +17 -102
  52. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/views/users.py +2 -0
  53. {django_microsys-2.2.3 → django_microsys-2.2.5}/pyproject.toml +1 -0
  54. django_microsys-2.2.3/microsys/VERSION +0 -1
  55. django_microsys-2.2.3/microsys/templates/microsys/includes/system_setup.html +0 -33
  56. {django_microsys-2.2.3 → django_microsys-2.2.5}/LICENSE +0 -0
  57. {django_microsys-2.2.3 → django_microsys-2.2.5}/MANIFEST.in +0 -0
  58. {django_microsys-2.2.3 → django_microsys-2.2.5}/README.md +0 -0
  59. {django_microsys-2.2.3 → django_microsys-2.2.5}/django_microsys.egg-info/dependency_links.txt +0 -0
  60. {django_microsys-2.2.3 → django_microsys-2.2.5}/django_microsys.egg-info/entry_points.txt +0 -0
  61. {django_microsys-2.2.3 → django_microsys-2.2.5}/django_microsys.egg-info/requires.txt +0 -0
  62. {django_microsys-2.2.3 → django_microsys-2.2.5}/django_microsys.egg-info/top_level.txt +0 -0
  63. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/__init__.py +0 -0
  64. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/__main__.py +0 -0
  65. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/admin.py +0 -0
  66. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/apps.py +0 -0
  67. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/cli.py +0 -0
  68. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/fetcher.py +0 -0
  69. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/filters.py +0 -0
  70. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/fonts.py +0 -0
  71. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/formats/__init__.py +0 -0
  72. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/formats/ar/__init__.py +0 -0
  73. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/formats/ar/formats.py +0 -0
  74. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/formats/en/__init__.py +0 -0
  75. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/formats/en/formats.py +0 -0
  76. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/guards.py +0 -0
  77. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/management/commands/__init__.py +0 -0
  78. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/management/commands/microsys_check.py +0 -0
  79. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/management/commands/microsys_setup.py +0 -0
  80. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/management/commands/migrator.py +0 -0
  81. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/management/commands/seed_activity_log.py +0 -0
  82. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/managers.py +0 -0
  83. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/middleware.py +0 -0
  84. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/migrations/0001_initial.py +0 -0
  85. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/migrations/0002_public_registration.py +0 -0
  86. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/migrations/0003_public_root_split.py +0 -0
  87. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/migrations/0004_client_ip_and_trusted_devices.py +0 -0
  88. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/migrations/0005_systemsettings_allow_user_font_override_and_more.py +0 -0
  89. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/migrations/__init__.py +0 -0
  90. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/patches.py +0 -0
  91. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/registration.py +0 -0
  92. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/scaffold.py +0 -0
  93. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/scaffold_templates/app/README.md.tmpl +0 -0
  94. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/scaffold_templates/app/__init__.py.tmpl +0 -0
  95. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/scaffold_templates/app/apps.py.tmpl +0 -0
  96. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/scaffold_templates/app/filters.py.tmpl +0 -0
  97. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/scaffold_templates/app/forms.py.tmpl +0 -0
  98. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/scaffold_templates/app/migrations/__init__.py.tmpl +0 -0
  99. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/scaffold_templates/app/models.py.tmpl +0 -0
  100. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/scaffold_templates/app/tables.py.tmpl +0 -0
  101. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/scaffold_templates/app/templates/example_record_confirm_delete.html.tmpl +0 -0
  102. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/scaffold_templates/app/templates/example_record_detail.html.tmpl +0 -0
  103. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/scaffold_templates/app/templates/example_record_form.html.tmpl +0 -0
  104. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/scaffold_templates/app/templates/example_record_list.html.tmpl +0 -0
  105. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/scaffold_templates/app/tests/__init__.py.tmpl +0 -0
  106. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/scaffold_templates/app/tests/test_app.py.tmpl +0 -0
  107. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/scaffold_templates/app/translations.py.tmpl +0 -0
  108. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/scaffold_templates/app/urls.py.tmpl +0 -0
  109. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/scaffold_templates/app/views.py.tmpl +0 -0
  110. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/scaffold_templates/project/.nginx/nginx.conf.tmpl +0 -0
  111. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/scaffold_templates/project/.secrets/.env.tmpl +0 -0
  112. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/scaffold_templates/project/Dockerfile.tmpl +0 -0
  113. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/scaffold_templates/project/README.md.tmpl +0 -0
  114. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/scaffold_templates/project/compose.dev.yml.tmpl +0 -0
  115. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/scaffold_templates/project/dockerignore.tmpl +0 -0
  116. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/scaffold_templates/project/docs/README.md.tmpl +0 -0
  117. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/scaffold_templates/project/entrypoint.sh.tmpl +0 -0
  118. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/scaffold_templates/project/gitattributes.tmpl +0 -0
  119. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/scaffold_templates/project/gitignore.tmpl +0 -0
  120. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/scaffold_templates/project/gunicorn.py.tmpl +0 -0
  121. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/scaffold_templates/project/manage.py.tmpl +0 -0
  122. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/scaffold_templates/project/package/__init__.py.tmpl +0 -0
  123. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/scaffold_templates/project/package/asgi.py.tmpl +0 -0
  124. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/scaffold_templates/project/package/celery.py.tmpl +0 -0
  125. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/scaffold_templates/project/package/settings.py.tmpl +0 -0
  126. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/scaffold_templates/project/package/urls.py.tmpl +0 -0
  127. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/scaffold_templates/project/package/wsgi.py.tmpl +0 -0
  128. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/scaffold_templates/project/req.txt.tmpl +0 -0
  129. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/scaffold_templates/project/start.ps1.tmpl +0 -0
  130. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/scaffold_templates/project/start.sh.tmpl +0 -0
  131. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/scaffold_templates/project/tests/__init__.py.tmpl +0 -0
  132. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/scaffold_templates/project/tests/test_scaffold.py.tmpl +0 -0
  133. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/scaffold_templates/project/tools/smtp_relay.py.tmpl +0 -0
  134. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/signals.py +0 -0
  135. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/bootstrap/bootstrap-icons.css +0 -0
  136. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/bootstrap/bootstrap-icons.woff +0 -0
  137. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/bootstrap/bootstrap-icons.woff2 +0 -0
  138. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/bootstrap/bootstrap.bundle.min.js +0 -0
  139. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/bootstrap/bootstrap.bundle.min.js.map +0 -0
  140. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/bootstrap/bootstrap.min.css +0 -0
  141. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/bootstrap/bootstrap.min.css.map +0 -0
  142. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/bootstrap/bootstrap.rtl.min.css +0 -0
  143. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/bootstrap/bootstrap.rtl.min.css.map +0 -0
  144. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/favicon.ico +0 -0
  145. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/img/base_logo.webp +0 -0
  146. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/img/default_profile.webp +0 -0
  147. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/img/login_logo.webp +0 -0
  148. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/accessibility/css/main.css +0 -0
  149. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/accessibility/js/main.js +0 -0
  150. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/activitylog/js/main.js +0 -0
  151. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/fonts/TwemojiCountryFlags.woff2 +0 -0
  152. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/fonts/cairo-bold.woff2 +0 -0
  153. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/fonts/cairo-medium.woff2 +0 -0
  154. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/fonts/cairo-regular.woff2 +0 -0
  155. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/fonts/shabwa-bold.woff2 +0 -0
  156. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/fonts/shabwa-medium.woff2 +0 -0
  157. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/fonts/shabwa-regular.woff2 +0 -0
  158. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/forms/css/file_field.css +0 -0
  159. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/forms/css/form_actions.css +0 -0
  160. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/forms/css/form_fields.css +0 -0
  161. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/forms/js/file_field.js +0 -0
  162. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/forms/js/filter_form.js +0 -0
  163. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/helpers/autofill/js/main.js +0 -0
  164. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/helpers/context_menu/css/main.css +0 -0
  165. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/helpers/context_menu/js/main.js +0 -0
  166. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/helpers/context_menu/js/section_manager.js +0 -0
  167. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/helpers/dynamic_modal/js/main.js +0 -0
  168. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/helpers/prevent_double_submit.js +0 -0
  169. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/helpers/scan_link/js/main.js +0 -0
  170. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/helpers/scan_link/js/scan_button.js +0 -0
  171. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/language/css/main.css +0 -0
  172. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/language/js/main.js +0 -0
  173. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/language/js/translations.js +0 -0
  174. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/main/css/buttons.css +0 -0
  175. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/main/css/dropdowns.css +0 -0
  176. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/main/css/index_cards.css +0 -0
  177. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/main/css/pagination.css +0 -0
  178. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/main/css/selectors.css +0 -0
  179. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/main/css/tables.css +0 -0
  180. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/main/css/template_cleanup.css +0 -0
  181. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/main/css/titlebar.css +0 -0
  182. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/main/js/base_head.js +0 -0
  183. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/main/js/base_runtime.js +0 -0
  184. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/main/js/selectors.js +0 -0
  185. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/main/js/tables.js +0 -0
  186. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/sections/js/manage_sections.js +0 -0
  187. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/sidebar/css/reorder.css +0 -0
  188. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/sidebar/css/theme_picker.css +0 -0
  189. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/sidebar/js/main.js +0 -0
  190. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/sidebar/js/preload.js +0 -0
  191. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/sidebar/js/reorder.js +0 -0
  192. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/sidebar/js/theme_picker.js +0 -0
  193. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/themes/css/blue.css +0 -0
  194. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/themes/css/dark.css +0 -0
  195. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/themes/css/gold.css +0 -0
  196. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/themes/css/green.css +0 -0
  197. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/themes/css/light.css +0 -0
  198. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/themes/css/red.css +0 -0
  199. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/tutorial/css/main.css +0 -0
  200. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/tutorial/js/driver.js +0 -0
  201. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/tutorial/js/main.js +0 -0
  202. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/users/css/login.css +0 -0
  203. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/users/css/permissions.css +0 -0
  204. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/users/css/profile.css +0 -0
  205. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/users/css/user_hub.css +0 -0
  206. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/users/js/login.js +0 -0
  207. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/users/js/manage_users.js +0 -0
  208. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/users/js/permissions.js +0 -0
  209. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/users/js/profile_image_widget.js +0 -0
  210. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/users/js/twofa_verify.js +0 -0
  211. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/microsys/users/js/user_hub.js +0 -0
  212. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/vanillajs-datepicker/datepicker-bs5.min.css +0 -0
  213. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/static/vanillajs-datepicker/datepicker.min.js +0 -0
  214. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/tables.py +0 -0
  215. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/templates/bootstrap5/layout/field_file.html +0 -0
  216. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/templates/microsys/2fa/verify.html +0 -0
  217. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/templates/microsys/activitylog/activity_log.html +0 -0
  218. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/templates/microsys/activitylog/activity_log_detail_modal.html +0 -0
  219. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/templates/microsys/form_base.html +0 -0
  220. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/templates/microsys/forms/assets_head.html +0 -0
  221. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/templates/microsys/forms/assets_scripts.html +0 -0
  222. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/templates/microsys/forms/crispy_file_field.html +0 -0
  223. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/templates/microsys/forms/file_input.html +0 -0
  224. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/templates/microsys/forms/filter_assets_head.html +0 -0
  225. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/templates/microsys/forms/filter_assets_scripts.html +0 -0
  226. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/templates/microsys/helpers/dynamic_modal.html +0 -0
  227. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/templates/microsys/helpers/dynamic_modal_combined.html +0 -0
  228. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/templates/microsys/helpers/dynamic_modal_detail.html +0 -0
  229. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/templates/microsys/helpers/dynamic_modal_form.html +0 -0
  230. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/templates/microsys/helpers/dynamic_modal_list.html +0 -0
  231. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/templates/microsys/helpers/micro_context_menu.html +0 -0
  232. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/templates/microsys/includes/font_previews.html +0 -0
  233. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/templates/microsys/includes/font_settings_matrix.html +0 -0
  234. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/templates/microsys/includes/language_catalog_editor.html +0 -0
  235. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/templates/microsys/includes/language_fonts_editor.html +0 -0
  236. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/templates/microsys/includes/language_previews.html +0 -0
  237. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/templates/microsys/includes/sidebar_builder.html +0 -0
  238. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/templates/microsys/includes/sidebar_density_previews.html +0 -0
  239. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/templates/microsys/includes/sidebar_items.html +0 -0
  240. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/templates/microsys/includes/system_names_editor.html +0 -0
  241. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/templates/microsys/includes/table_density_previews.html +0 -0
  242. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/templates/microsys/includes/theme_previews.html +0 -0
  243. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/templates/microsys/includes/titlebar.html +0 -0
  244. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/templates/microsys/includes/translation_matrix_editor.html +0 -0
  245. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/templates/microsys/includes/tutorial.html +0 -0
  246. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/templates/microsys/list_base.html +0 -0
  247. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/templates/microsys/registration/pending.html +0 -0
  248. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/templates/microsys/scopes/scope_actions.html +0 -0
  249. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/templates/microsys/scopes/scope_form.html +0 -0
  250. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/templates/microsys/scopes/scope_manager.html +0 -0
  251. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/templates/microsys/sections/manage_sections.html +0 -0
  252. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/templates/microsys/sections/subsection_select.html +0 -0
  253. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/templates/microsys/sidebar/auto.html +0 -0
  254. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/templates/microsys/tables/table.html +0 -0
  255. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/templates/microsys/users/grouped_permissions.html +0 -0
  256. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/templates/microsys/users/manage_users.html +0 -0
  257. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/templates/microsys/users/profile_image_widget.html +0 -0
  258. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/templates/microsys/users/user_detail_modal.html +0 -0
  259. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/templates/microsys/users/user_hub.html +0 -0
  260. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/templates/registration/email/verify_registration.txt +0 -0
  261. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/templates/registration/login.html +0 -0
  262. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/templates/registration/register.html +0 -0
  263. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/templates/registration/register_sent.html +0 -0
  264. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/templates/registration/register_verify.html +0 -0
  265. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/templatetags/__init__.py +0 -0
  266. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/templatetags/microsys_translation.py +0 -0
  267. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/templatetags/sidebar_tags.py +0 -0
  268. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/themes.py +0 -0
  269. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/views/activitylog.py +0 -0
  270. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/views/registration.py +0 -0
  271. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/views/scopes.py +0 -0
  272. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/views/sidebar.py +0 -0
  273. {django_microsys-2.2.3 → django_microsys-2.2.5}/microsys/widgets.py +0 -0
  274. {django_microsys-2.2.3 → django_microsys-2.2.5}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: django_microsys
3
- Version: 2.2.3
3
+ Version: 2.2.5
4
4
  Summary: Django microSYS (System Integration Service) - Multilingual Django Starter Pack, Packed with Features.
5
5
  Author-email: DeBeski <debeski1@gmail.com>
6
6
  License: NON-COMMERCIAL
@@ -8,6 +8,7 @@ Project-URL: Homepage, https://github.com/debeski/django-microsys
8
8
  Keywords: django,microsys,permissions,authentication
9
9
  Classifier: Framework :: Django
10
10
  Classifier: Framework :: Django :: 5
11
+ Classifier: Framework :: Django :: 6
11
12
  Classifier: Programming Language :: Python :: 3
12
13
  Classifier: Programming Language :: Python :: 3.11
13
14
  Classifier: Programming Language :: Python :: 3.12
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: django-microsys
3
- Version: 2.2.3
3
+ Version: 2.2.5
4
4
  Summary: Django microSYS (System Integration Service) - Multilingual Django Starter Pack, Packed with Features.
5
5
  Author-email: DeBeski <debeski1@gmail.com>
6
6
  License: NON-COMMERCIAL
@@ -8,6 +8,7 @@ Project-URL: Homepage, https://github.com/debeski/django-microsys
8
8
  Keywords: django,microsys,permissions,authentication
9
9
  Classifier: Framework :: Django
10
10
  Classifier: Framework :: Django :: 5
11
+ Classifier: Framework :: Django :: 6
11
12
  Classifier: Programming Language :: Python :: 3
12
13
  Classifier: Programming Language :: Python :: 3.11
13
14
  Classifier: Programming Language :: Python :: 3.12
@@ -26,6 +26,7 @@ microsys/guards.py
26
26
  microsys/managers.py
27
27
  microsys/middleware.py
28
28
  microsys/models.py
29
+ microsys/navbar.py
29
30
  microsys/patches.py
30
31
  microsys/registration.py
31
32
  microsys/scaffold.py
@@ -33,6 +34,7 @@ microsys/signals.py
33
34
  microsys/tables.py
34
35
  microsys/themes.py
35
36
  microsys/translations.py
37
+ microsys/trust.py
36
38
  microsys/urls.py
37
39
  microsys/utils.py
38
40
  microsys/widgets.py
@@ -43,6 +45,7 @@ microsys/formats/en/__init__.py
43
45
  microsys/formats/en/formats.py
44
46
  microsys/management/commands/__init__.py
45
47
  microsys/management/commands/microsys_check.py
48
+ microsys/management/commands/microsys_settings.py
46
49
  microsys/management/commands/microsys_setup.py
47
50
  microsys/management/commands/migrator.py
48
51
  microsys/management/commands/seed_activity_log.py
@@ -51,6 +54,8 @@ microsys/migrations/0002_public_registration.py
51
54
  microsys/migrations/0003_public_root_split.py
52
55
  microsys/migrations/0004_client_ip_and_trusted_devices.py
53
56
  microsys/migrations/0005_systemsettings_allow_user_font_override_and_more.py
57
+ microsys/migrations/0006_systemsettings_navbar_config.py
58
+ microsys/migrations/0007_systemsettings_prevent_multiple_active_sessions.py
54
59
  microsys/migrations/__init__.py
55
60
  microsys/scaffold_templates/app/README.md.tmpl
56
61
  microsys/scaffold_templates/app/__init__.py.tmpl
@@ -138,6 +143,7 @@ microsys/static/microsys/main/css/buttons.css
138
143
  microsys/static/microsys/main/css/dropdowns.css
139
144
  microsys/static/microsys/main/css/index_cards.css
140
145
  microsys/static/microsys/main/css/main.css
146
+ microsys/static/microsys/main/css/navbar.css
141
147
  microsys/static/microsys/main/css/options.css
142
148
  microsys/static/microsys/main/css/pagination.css
143
149
  microsys/static/microsys/main/css/selectors.css
@@ -147,6 +153,7 @@ microsys/static/microsys/main/css/template_cleanup.css
147
153
  microsys/static/microsys/main/css/titlebar.css
148
154
  microsys/static/microsys/main/js/base_head.js
149
155
  microsys/static/microsys/main/js/base_runtime.js
156
+ microsys/static/microsys/main/js/navbar.js
150
157
  microsys/static/microsys/main/js/options.js
151
158
  microsys/static/microsys/main/js/selectors.js
152
159
  microsys/static/microsys/main/js/system_setup.js
@@ -210,6 +217,9 @@ microsys/templates/microsys/includes/font_settings_matrix.html
210
217
  microsys/templates/microsys/includes/language_catalog_editor.html
211
218
  microsys/templates/microsys/includes/language_fonts_editor.html
212
219
  microsys/templates/microsys/includes/language_previews.html
220
+ microsys/templates/microsys/includes/navbar.html
221
+ microsys/templates/microsys/includes/navbar_builder.html
222
+ microsys/templates/microsys/includes/navbar_mode_previews.html
213
223
  microsys/templates/microsys/includes/options.html
214
224
  microsys/templates/microsys/includes/sidebar_builder.html
215
225
  microsys/templates/microsys/includes/sidebar_density_previews.html
@@ -0,0 +1 @@
1
+ 2.2.5
@@ -7,7 +7,7 @@ import json
7
7
  from datetime import date, datetime
8
8
  import logging
9
9
  # Project imports
10
- from .constants import SIDEBAR_DENSITY_VALUES, TABLE_DENSITY_VALUES, TABLE_PAGE_SIZE_VALUES
10
+ from .constants import NAVBAR_MODE_VALUES, SIDEBAR_DENSITY_VALUES, TABLE_DENSITY_VALUES, TABLE_PAGE_SIZE_VALUES
11
11
  from .utils import (
12
12
  get_effective_allowed_themes,
13
13
  get_system_config,
@@ -15,6 +15,7 @@ from .utils import (
15
15
  is_global_staff,
16
16
  is_scope_enabled,
17
17
  log_user_action,
18
+ normalize_navbar_config,
18
19
  normalize_sidebar_behavior,
19
20
  user_has_model_permission,
20
21
  )
@@ -208,6 +209,7 @@ def update_preferences(request):
208
209
  system_config = get_system_config()
209
210
  allowed_themes = set(get_effective_allowed_themes(system_config))
210
211
  sidebar_config = normalize_sidebar_behavior(system_config.get('sidebar', {}))
212
+ navbar_config = normalize_navbar_config(system_config.get('navbar', {}))
211
213
 
212
214
  language_preview_requested = bool(data.get('__language_preview'))
213
215
 
@@ -255,6 +257,14 @@ def update_preferences(request):
255
257
  if value not in SIDEBAR_DENSITY_VALUES:
256
258
  prefs.pop('sidebar_density', None)
257
259
  continue
260
+ if key == 'navbar_mode':
261
+ if (
262
+ not navbar_config.get('enabled', False)
263
+ or not navbar_config.get('allow_user_mode_override', True)
264
+ or value not in NAVBAR_MODE_VALUES
265
+ ):
266
+ prefs.pop('navbar_mode', None)
267
+ continue
258
268
  if key == 'table_page_size':
259
269
  try:
260
270
  coerced_value = int(value)
@@ -20,6 +20,12 @@ SIDEBAR_COLLAPSE_MODE_CHOICES = (
20
20
  ('locked_expanded', 'Locked Expanded'),
21
21
  )
22
22
  SIDEBAR_COLLAPSE_MODE_VALUES = {value for value, _label in SIDEBAR_COLLAPSE_MODE_CHOICES}
23
+ DEFAULT_NAVBAR_MODE = 'hierarchy'
24
+ NAVBAR_MODE_CHOICES = (
25
+ (DEFAULT_NAVBAR_MODE, 'Hierarchy'),
26
+ ('history', 'History'),
27
+ )
28
+ NAVBAR_MODE_VALUES = {value for value, _label in NAVBAR_MODE_CHOICES}
23
29
  TITLEBAR_HOME_SHAPE_CHOICES = (
24
30
  ('circle', 'Circle'),
25
31
  ('square', 'Square'),
@@ -1,11 +1,13 @@
1
1
  from urllib.parse import urlsplit
2
2
 
3
3
  from .constants import DEFAULT_TABLE_DENSITY, TABLE_DENSITY_CHOICES, TABLE_DENSITY_VALUES
4
+ from .navbar import resolve_navbar_mode, strip_navbar_mode_preference
4
5
  from .utils import (
5
6
  get_effective_allowed_themes,
6
7
  get_user_management_tier_state_for_user,
7
8
  has_section_models,
8
9
  is_scope_enabled,
10
+ normalize_navbar_config,
9
11
  normalize_sidebar_behavior,
10
12
  resolve_sidebar_collapsed_preference,
11
13
  resolve_sidebar_density_preference,
@@ -244,6 +246,8 @@ def microsys_context(request):
244
246
  if not allow_user_language_override and not request.session.get('ms_force_language_preview'):
245
247
  user_prefs = {key: value for key, value in user_prefs.items() if key != 'language'}
246
248
  user_prefs = resolve_user_theme_preference(user_prefs, final_config)
249
+ navbar_runtime_config = normalize_navbar_config(final_config.get('navbar', {}))
250
+ user_prefs = strip_navbar_mode_preference(user_prefs, navbar_runtime_config)
247
251
  default_table_density = final_config.get('default_table_density', DEFAULT_TABLE_DENSITY)
248
252
  if default_table_density not in TABLE_DENSITY_VALUES:
249
253
  default_table_density = DEFAULT_TABLE_DENSITY
@@ -318,6 +322,15 @@ def microsys_context(request):
318
322
  context['sidebar_reorder_enabled'],
319
323
  context['sidebar_has_sections_manager'],
320
324
  ])
325
+ current_route_name = getattr(getattr(request, 'resolver_match', None), 'url_name', '')
326
+ navbar_enabled = bool(navbar_runtime_config.get('enabled', False)) and current_route_name != 'system_setup'
327
+ context['navbar_enabled'] = navbar_enabled
328
+ context['navbar_mode'] = resolve_navbar_mode(user_prefs, navbar_runtime_config)
329
+ context['navbar'] = {
330
+ **navbar_runtime_config,
331
+ 'enabled': navbar_enabled,
332
+ 'mode': context['navbar_mode'],
333
+ }
321
334
 
322
335
  # 7. Sidebar State (Collapsed/Expanded)
323
336
  # Prioritize DB preference if available, else session, else default
@@ -177,6 +177,10 @@ def _route_name_tokens(value):
177
177
  return [token for token in re.split(r'[_:\-]+', (value or '').lower()) if token]
178
178
 
179
179
 
180
+ def _route_leaf(url_name):
181
+ return str(url_name or '').split(':')[-1]
182
+
183
+
180
184
  def _plain_text(value, fallback=''):
181
185
  if value is None:
182
186
  return fallback
@@ -214,7 +218,7 @@ def _normalize_permissions(value):
214
218
 
215
219
 
216
220
  def _is_configurable_system_url(url_name):
217
- return isinstance(url_name, str) and url_name in CONFIGURABLE_SYSTEM_ROUTE_NAMES
221
+ return isinstance(url_name, str) and _route_leaf(url_name) in CONFIGURABLE_SYSTEM_ROUTE_NAMES
218
222
 
219
223
 
220
224
  def _infer_model(pattern):
@@ -251,8 +255,9 @@ def _infer_group_key(url_name, model, callback):
251
255
  callback_app = _infer_callback_app_label(callback)
252
256
  if callback_app:
253
257
  return callback_app
254
- if url_name in SYSTEM_ROUTE_META:
255
- return SYSTEM_ROUTE_META[url_name]['group_key']
258
+ leaf = _route_leaf(url_name)
259
+ if leaf in SYSTEM_ROUTE_META:
260
+ return SYSTEM_ROUTE_META[leaf]['group_key']
256
261
  if ':' in url_name:
257
262
  return url_name.split(':')[0]
258
263
  return 'general'
@@ -283,13 +288,13 @@ def _infer_label(url_name, strings, model=None, callback=None):
283
288
  if explicit:
284
289
  return _plain_text(explicit)
285
290
 
286
- leaf = url_name.split(':')[-1]
291
+ leaf = _route_leaf(url_name)
287
292
  namespace = url_name.split(':')[0] if ':' in url_name else ''
288
293
  group_key = _infer_group_key(url_name, model, callback)
289
294
  group_label = _group_label(group_key, strings)
290
295
 
291
- if url_name in SYSTEM_ROUTE_META:
292
- return _plain_text(strings.get(SYSTEM_ROUTE_META[url_name]['label_key'], _humanize(leaf)))
296
+ if leaf in SYSTEM_ROUTE_META:
297
+ return _plain_text(strings.get(SYSTEM_ROUTE_META[leaf]['label_key'], _humanize(leaf)))
293
298
 
294
299
  candidates = [
295
300
  f'view_{leaf}',
@@ -329,8 +334,9 @@ def _infer_permissions(url_name, model, callback):
329
334
  if explicit:
330
335
  return explicit, True
331
336
 
332
- if url_name in SYSTEM_ROUTE_META:
333
- perms = list(SYSTEM_ROUTE_META[url_name].get('permissions', []))
337
+ leaf = _route_leaf(url_name)
338
+ if leaf in SYSTEM_ROUTE_META:
339
+ perms = list(SYSTEM_ROUTE_META[leaf].get('permissions', []))
334
340
  return perms, True
335
341
 
336
342
  if model is not None:
@@ -386,7 +392,7 @@ def _infer_permissions(url_name, model, callback):
386
392
  def _is_hidden_sidebar_url(url_name, allow_system_items=False):
387
393
  if not url_name or not isinstance(url_name, str):
388
394
  return False
389
- if url_name in SYSTEM_ROUTE_META:
395
+ if _route_leaf(url_name) in SYSTEM_ROUTE_META:
390
396
  if allow_system_items and _is_configurable_system_url(url_name):
391
397
  return False
392
398
  return True
@@ -766,6 +772,43 @@ def _is_active_path(request_path, url):
766
772
  return request_path == url or request_path.startswith(url.rstrip('/') + '/')
767
773
 
768
774
 
775
+ def _normalized_active_path(value):
776
+ value = str(value or '').split('?', 1)[0].strip()
777
+ if not value:
778
+ return ''
779
+ return value.rstrip('/') or '/'
780
+
781
+
782
+ def _iter_render_sidebar_items(entries):
783
+ for entry in entries if isinstance(entries, list) else []:
784
+ if not isinstance(entry, dict):
785
+ continue
786
+ if entry.get('kind') == 'group':
787
+ yield from _iter_render_sidebar_items(entry.get('items'))
788
+ continue
789
+ yield entry
790
+
791
+
792
+ def _apply_sidebar_active_state(entries, request_path, open_accordions):
793
+ items = list(_iter_render_sidebar_items(entries))
794
+ current_path = _normalized_active_path(request_path)
795
+ exact_match = any(_normalized_active_path(item.get('url')) == current_path for item in items)
796
+ for item in items:
797
+ item_url = item.get('url')
798
+ item['active'] = (
799
+ _normalized_active_path(item_url) == current_path
800
+ if exact_match
801
+ else _is_active_path(request_path, item_url)
802
+ )
803
+
804
+ open_ids = set(open_accordions or [])
805
+ for entry in entries if isinstance(entries, list) else []:
806
+ if isinstance(entry, dict) and entry.get('kind') == 'group':
807
+ has_active = any(item.get('active') for item in entry.get('items', []))
808
+ entry['has_active'] = has_active
809
+ entry['is_open'] = entry.get('id') in open_ids or has_active
810
+
811
+
769
812
  def build_sidebar_navigation(lang_code=None, sidebar_override=None, user=None, request_path='', open_accordions=None):
770
813
  """
771
814
  Transform sidebar JSON config into a single render-ready sidebar tree.
@@ -810,11 +853,9 @@ def build_sidebar_navigation(lang_code=None, sidebar_override=None, user=None, r
810
853
  for raw_item in entry.get('items', []):
811
854
  resolved_item = _resolve_sidebar_item(raw_item, catalog)
812
855
  if resolved_item and _user_has_sidebar_permission(user, resolved_item.get('permissions'), resolved_item.get('permissions_explicit', False)):
813
- resolved_item['active'] = _is_active_path(request_path, resolved_item.get('url'))
814
856
  items.append(resolved_item)
815
857
  if items:
816
858
  group_id = entry.get('id') or f"group-{len(render_entries) + 1}"
817
- has_active = any(item.get('active') for item in items)
818
859
  inferred_group_label = next((item.get('group_label') for item in items if item.get('group_label')), None)
819
860
  inferred_group_icon = next((item.get('group_icon') for item in items if item.get('group_icon')), None)
820
861
  render_entries.append({
@@ -825,22 +866,23 @@ def build_sidebar_navigation(lang_code=None, sidebar_override=None, user=None, r
825
866
  'url': _resolve_group_url(entry),
826
867
  'url_name': entry.get('url_name'),
827
868
  'items': items,
828
- 'has_active': has_active,
829
- 'is_open': (group_id in open_accordions) or has_active,
869
+ 'has_active': False,
870
+ 'is_open': group_id in open_accordions,
830
871
  'raw_name': entry.get('id') or group_id,
831
872
  })
832
873
  continue
833
874
 
834
875
  resolved = _resolve_sidebar_item(entry, catalog)
835
876
  if resolved and _user_has_sidebar_permission(user, resolved.get('permissions'), resolved.get('permissions_explicit', False)):
836
- resolved['active'] = _is_active_path(request_path, resolved.get('url'))
837
877
  render_entries.append(resolved)
838
878
  return render_entries
839
879
 
840
880
  render_entries = render_sidebar_entries(sidebar.get('entries', []) if isinstance(sidebar, dict) else [])
881
+ _apply_sidebar_active_state(render_entries, request_path, open_accordions)
841
882
  if override_sidebar and override_sidebar.get('entries') and not render_entries and base_sidebar.get('entries'):
842
883
  sidebar = base_sidebar
843
884
  render_entries = render_sidebar_entries(base_sidebar.get('entries', []))
885
+ _apply_sidebar_active_state(render_entries, request_path, open_accordions)
844
886
 
845
887
  return {
846
888
  'entries': render_entries,