django-cfg 1.3.13__py3-none-any.whl → 1.4.3__py3-none-any.whl

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 (446) hide show
  1. django_cfg/__init__.py +1 -1
  2. django_cfg/apps/accounts/admin/user_admin.py +39 -16
  3. django_cfg/apps/accounts/serializers/profile.py +1 -1
  4. django_cfg/apps/accounts/services/otp_service.py +18 -11
  5. django_cfg/apps/accounts/signals.py +15 -24
  6. django_cfg/apps/accounts/utils/notifications.py +217 -358
  7. django_cfg/apps/accounts/views/otp.py +2 -2
  8. django_cfg/apps/accounts/views/webhook.py +1 -1
  9. django_cfg/apps/agents/core/django_agent.py +1 -1
  10. django_cfg/apps/agents/examples/__init__.py +3 -0
  11. django_cfg/apps/agents/examples/simple_example.py +161 -0
  12. django_cfg/apps/api/commands/views.py +66 -83
  13. django_cfg/apps/api/health/drf_views.py +269 -0
  14. django_cfg/apps/api/health/serializers.py +45 -0
  15. django_cfg/apps/api/health/urls.py +6 -1
  16. django_cfg/apps/knowbase/admin/actions/__init__.py +13 -0
  17. django_cfg/apps/knowbase/admin/actions/visibility_actions.py +56 -0
  18. django_cfg/apps/knowbase/admin/document_admin.py +136 -270
  19. django_cfg/apps/knowbase/admin/helpers/__init__.py +17 -0
  20. django_cfg/apps/knowbase/admin/helpers/configs.py +72 -0
  21. django_cfg/apps/knowbase/admin/helpers/display_helpers.py +156 -0
  22. django_cfg/apps/knowbase/admin/helpers/statistics.py +108 -0
  23. django_cfg/apps/knowbase/config/constance_fields.py +1 -1
  24. django_cfg/apps/knowbase/config/settings.py +2 -2
  25. django_cfg/apps/knowbase/examples/__init__.py +3 -0
  26. django_cfg/apps/knowbase/examples/external_data_usage.py +191 -0
  27. django_cfg/apps/knowbase/mixins/__init__.py +19 -2
  28. django_cfg/apps/knowbase/mixins/config/__init__.py +14 -0
  29. django_cfg/apps/knowbase/mixins/config/defaults.py +75 -0
  30. django_cfg/apps/knowbase/mixins/config/meta_config.py +120 -0
  31. django_cfg/apps/knowbase/mixins/creator.py +10 -10
  32. django_cfg/apps/knowbase/mixins/examples/vehicle_model_example.py +199 -0
  33. django_cfg/apps/knowbase/mixins/external_data_mixin.py +105 -403
  34. django_cfg/apps/knowbase/mixins/generators/__init__.py +16 -0
  35. django_cfg/apps/knowbase/mixins/generators/content_generator.py +218 -0
  36. django_cfg/apps/knowbase/mixins/generators/field_analyzer.py +76 -0
  37. django_cfg/apps/knowbase/mixins/generators/metadata_generator.py +124 -0
  38. django_cfg/apps/knowbase/mixins/service.py +2 -2
  39. django_cfg/apps/knowbase/services/archive/__init__.py +1 -0
  40. django_cfg/apps/knowbase/services/archive/analyzers/__init__.py +17 -0
  41. django_cfg/apps/knowbase/services/archive/analyzers/complexity_analyzer.py +33 -0
  42. django_cfg/apps/knowbase/services/archive/analyzers/purpose_detector.py +36 -0
  43. django_cfg/apps/knowbase/services/archive/analyzers/quality_analyzer.py +39 -0
  44. django_cfg/apps/knowbase/services/archive/analyzers/tag_generator.py +103 -0
  45. django_cfg/apps/knowbase/services/archive/chunking/__init__.py +19 -0
  46. django_cfg/apps/knowbase/services/archive/chunking/base.py +81 -0
  47. django_cfg/apps/knowbase/services/archive/chunking/json_chunker.py +62 -0
  48. django_cfg/apps/knowbase/services/archive/chunking/markdown_chunker.py +107 -0
  49. django_cfg/apps/knowbase/services/archive/chunking/python_chunker.py +248 -0
  50. django_cfg/apps/knowbase/services/archive/chunking/text_chunker.py +70 -0
  51. django_cfg/apps/knowbase/services/archive/chunking_service.py +110 -729
  52. django_cfg/apps/knowbase/services/archive/context/__init__.py +14 -0
  53. django_cfg/apps/knowbase/services/archive/context/builders.py +220 -0
  54. django_cfg/apps/knowbase/services/archive/context/models.py +38 -0
  55. django_cfg/apps/knowbase/services/embedding/models.py +18 -14
  56. django_cfg/apps/knowbase/services/embedding/processors.py +6 -3
  57. django_cfg/apps/knowbase/tasks/document_processing.py +11 -3
  58. django_cfg/apps/leads/tests.py +1 -1
  59. django_cfg/apps/payments/admin/api_keys_admin.py +1 -1
  60. django_cfg/apps/payments/admin/balance_admin.py +1 -1
  61. django_cfg/apps/payments/admin/currencies_admin.py +1 -1
  62. django_cfg/apps/payments/admin/payments_admin.py +1 -1
  63. django_cfg/apps/payments/admin/subscriptions_admin.py +1 -1
  64. django_cfg/apps/payments/admin_interface/templates/payments/base.html +59 -126
  65. django_cfg/apps/payments/admin_interface/views/api/payments.py +1 -1
  66. django_cfg/apps/payments/admin_interface/views/api/stats.py +1 -1
  67. django_cfg/apps/payments/admin_interface/views/api/users.py +1 -1
  68. django_cfg/apps/payments/admin_interface/views/api/webhook_admin.py +1 -1
  69. django_cfg/apps/payments/admin_interface/views/api/webhook_public.py +1 -1
  70. django_cfg/apps/payments/admin_interface/views/base.py +29 -2
  71. django_cfg/apps/payments/apps.py +1 -1
  72. django_cfg/apps/payments/config/django_cfg_integration.py +2 -2
  73. django_cfg/apps/payments/config/helpers.py +3 -2
  74. django_cfg/apps/payments/management/commands/cleanup_expired_data.py +1 -1
  75. django_cfg/apps/payments/management/commands/currency_stats.py +1 -1
  76. django_cfg/apps/payments/management/commands/manage_currencies.py +1 -1
  77. django_cfg/apps/payments/management/commands/manage_providers.py +1 -1
  78. django_cfg/apps/payments/management/commands/process_pending_payments.py +1 -1
  79. django_cfg/apps/payments/management/commands/test_providers.py +1 -1
  80. django_cfg/apps/payments/middleware/api_access.py +1 -1
  81. django_cfg/apps/payments/middleware/rate_limiting.py +1 -1
  82. django_cfg/apps/payments/middleware/usage_tracking.py +1 -1
  83. django_cfg/apps/payments/models/balance.py +2 -2
  84. django_cfg/apps/payments/models/managers/api_key_managers.py +1 -1
  85. django_cfg/apps/payments/models/managers/balance_managers.py +1 -1
  86. django_cfg/apps/payments/models/managers/currency_managers.py +1 -1
  87. django_cfg/apps/payments/models/managers/payment_managers.py +1 -1
  88. django_cfg/apps/payments/models/managers/subscription_managers.py +1 -1
  89. django_cfg/apps/payments/models/payments.py +2 -2
  90. django_cfg/apps/payments/services/cache_service/__init__.py +1 -1
  91. django_cfg/apps/payments/services/cache_service/simple_cache.py +10 -5
  92. django_cfg/apps/payments/services/core/base.py +1 -1
  93. django_cfg/apps/payments/services/core/currency/__init__.py +13 -0
  94. django_cfg/apps/payments/services/core/currency/currency_converter.py +57 -0
  95. django_cfg/apps/payments/services/core/currency/currency_validator.py +61 -0
  96. django_cfg/apps/payments/services/core/operations/__init__.py +15 -0
  97. django_cfg/apps/payments/services/core/operations/payment_canceller.py +100 -0
  98. django_cfg/apps/payments/services/core/operations/payment_creator.py +196 -0
  99. django_cfg/apps/payments/services/core/operations/status_checker.py +100 -0
  100. django_cfg/apps/payments/services/core/payment_service.py +124 -612
  101. django_cfg/apps/payments/services/core/providers/__init__.py +13 -0
  102. django_cfg/apps/payments/services/core/providers/provider_client.py +132 -0
  103. django_cfg/apps/payments/services/core/providers/status_mapper.py +89 -0
  104. django_cfg/apps/payments/services/core/utils/__init__.py +13 -0
  105. django_cfg/apps/payments/services/core/utils/data_converter.py +48 -0
  106. django_cfg/apps/payments/services/core/utils/statistics_calculator.py +69 -0
  107. django_cfg/apps/payments/services/providers/base.py +1 -1
  108. django_cfg/apps/payments/services/providers/nowpayments/__init__.py +3 -3
  109. django_cfg/apps/payments/services/providers/nowpayments/parsers/__init__.py +9 -0
  110. django_cfg/apps/payments/services/providers/nowpayments/parsers/data/__init__.py +23 -0
  111. django_cfg/apps/payments/services/providers/nowpayments/parsers/data/constants.py +23 -0
  112. django_cfg/apps/payments/services/providers/nowpayments/parsers/data/currency_names.py +244 -0
  113. django_cfg/apps/payments/services/providers/nowpayments/parsers/data/patterns.py +511 -0
  114. django_cfg/apps/payments/services/providers/nowpayments/parsers/parser.py +168 -0
  115. django_cfg/apps/payments/services/providers/nowpayments/provider.py +1 -1
  116. django_cfg/apps/payments/services/providers/nowpayments/sync.py +1 -1
  117. django_cfg/apps/payments/services/providers/registry.py +1 -1
  118. django_cfg/apps/payments/services/providers/sync_service.py +1 -1
  119. django_cfg/apps/payments/signals/__init__.py +1 -1
  120. django_cfg/apps/payments/signals/api_key_signals.py +1 -1
  121. django_cfg/apps/payments/signals/balance_signals.py +1 -1
  122. django_cfg/apps/payments/signals/payment_signals.py +1 -1
  123. django_cfg/apps/payments/signals/subscription_signals.py +1 -1
  124. django_cfg/apps/payments/views/api/api_keys.py +1 -1
  125. django_cfg/apps/payments/views/api/balances.py +1 -1
  126. django_cfg/apps/payments/views/api/base.py +1 -1
  127. django_cfg/apps/payments/views/api/currencies.py +1 -1
  128. django_cfg/apps/payments/views/api/payments.py +1 -1
  129. django_cfg/apps/payments/views/api/subscriptions.py +1 -1
  130. django_cfg/apps/payments/views/api/webhooks.py +1 -1
  131. django_cfg/apps/payments/views/serializers/api_keys.py +1 -1
  132. django_cfg/apps/payments/views/serializers/balances.py +1 -1
  133. django_cfg/apps/payments/views/serializers/currencies.py +1 -1
  134. django_cfg/apps/payments/views/serializers/payments.py +1 -1
  135. django_cfg/apps/payments/views/serializers/subscriptions.py +1 -1
  136. django_cfg/apps/payments/views/serializers/webhooks.py +1 -1
  137. django_cfg/apps/support/admin/support_admin.py +21 -13
  138. django_cfg/apps/support/templates/support/chat/access_denied.html +21 -27
  139. django_cfg/apps/support/templates/support/chat/ticket_chat.html +183 -254
  140. django_cfg/apps/support/utils/support_email_service.py +1 -1
  141. django_cfg/apps/tasks/templates/tasks/layout/base.html +20 -115
  142. django_cfg/apps/tasks/utils/simulator.py +1 -1
  143. django_cfg/apps/tasks/views/dashboard.py +33 -3
  144. django_cfg/apps/urls.py +5 -1
  145. django_cfg/cli/README.md +57 -471
  146. django_cfg/cli/commands/create_project.py +140 -529
  147. django_cfg/cli/main.py +13 -10
  148. django_cfg/core/__init__.py +63 -6
  149. django_cfg/core/base/__init__.py +5 -0
  150. django_cfg/core/base/config_model.py +652 -0
  151. django_cfg/core/builders/__init__.py +11 -0
  152. django_cfg/core/builders/apps_builder.py +258 -0
  153. django_cfg/core/builders/middleware_builder.py +115 -0
  154. django_cfg/core/builders/security_builder.py +96 -0
  155. django_cfg/core/config.py +20 -892
  156. django_cfg/core/constants.py +69 -0
  157. django_cfg/core/environment/__init__.py +9 -0
  158. django_cfg/core/exceptions.py +45 -298
  159. django_cfg/core/generation/__init__.py +51 -0
  160. django_cfg/core/generation/core_generators/__init__.py +0 -0
  161. django_cfg/core/generation/core_generators/settings.py +90 -0
  162. django_cfg/core/generation/core_generators/static.py +82 -0
  163. django_cfg/core/generation/core_generators/templates.py +141 -0
  164. django_cfg/core/generation/data_generators/__init__.py +15 -0
  165. django_cfg/core/generation/data_generators/cache.py +132 -0
  166. django_cfg/core/generation/data_generators/database.py +117 -0
  167. django_cfg/core/generation/generation.py +92 -0
  168. django_cfg/core/generation/integration_generators/__init__.py +21 -0
  169. django_cfg/core/generation/integration_generators/api.py +237 -0
  170. django_cfg/core/generation/integration_generators/sessions.py +65 -0
  171. django_cfg/core/generation/integration_generators/tailwind.py +54 -0
  172. django_cfg/core/generation/integration_generators/tasks.py +92 -0
  173. django_cfg/core/generation/integration_generators/third_party.py +144 -0
  174. django_cfg/core/generation/orchestrator.py +285 -0
  175. django_cfg/core/generation/protocols.py +30 -0
  176. django_cfg/core/generation/security_generators/__init__.py +0 -0
  177. django_cfg/core/generation/utility_generators/__init__.py +24 -0
  178. django_cfg/core/generation/utility_generators/email.py +58 -0
  179. django_cfg/core/generation/utility_generators/i18n.py +66 -0
  180. django_cfg/core/generation/utility_generators/limits.py +58 -0
  181. django_cfg/core/generation/utility_generators/logging.py +66 -0
  182. django_cfg/core/generation/utility_generators/security.py +101 -0
  183. django_cfg/core/generation/utils/__init__.py +0 -0
  184. django_cfg/core/generation/utils/helpers.py +32 -0
  185. django_cfg/core/integration/__init__.py +18 -25
  186. django_cfg/core/integration/display/startup.py +146 -133
  187. django_cfg/core/integration/url_integration.py +13 -2
  188. django_cfg/core/services/__init__.py +5 -0
  189. django_cfg/core/services/config_service.py +121 -0
  190. django_cfg/core/state/__init__.py +9 -0
  191. django_cfg/core/state/registry.py +84 -0
  192. django_cfg/core/types/__init__.py +15 -0
  193. django_cfg/core/types/aliases.py +15 -0
  194. django_cfg/core/types/enums.py +49 -0
  195. django_cfg/dashboard/DEBUG_README.md +105 -0
  196. django_cfg/dashboard/REFACTORING_SUMMARY.md +237 -0
  197. django_cfg/dashboard/__init__.py +24 -0
  198. django_cfg/dashboard/components.py +308 -0
  199. django_cfg/dashboard/debug.py +176 -0
  200. django_cfg/dashboard/management/__init__.py +0 -0
  201. django_cfg/dashboard/management/commands/__init__.py +0 -0
  202. django_cfg/dashboard/management/commands/debug_dashboard.py +109 -0
  203. django_cfg/dashboard/sections/__init__.py +1 -0
  204. django_cfg/dashboard/sections/base.py +128 -0
  205. django_cfg/dashboard/sections/commands.py +32 -0
  206. django_cfg/dashboard/sections/overview.py +394 -0
  207. django_cfg/dashboard/sections/stats.py +48 -0
  208. django_cfg/dashboard/sections/system.py +73 -0
  209. django_cfg/management/commands/check_settings.py +6 -2
  210. django_cfg/management/commands/clear_constance.py +6 -1
  211. django_cfg/management/commands/create_token.py +5 -4
  212. django_cfg/management/commands/generate.py +5 -0
  213. django_cfg/management/commands/list_urls.py +7 -2
  214. django_cfg/management/commands/migrate_all.py +6 -2
  215. django_cfg/management/commands/migrator.py +6 -1
  216. django_cfg/management/commands/rundramatiq.py +6 -1
  217. django_cfg/management/commands/rundramatiq_simulator.py +11 -4
  218. django_cfg/management/commands/runserver_ngrok.py +9 -7
  219. django_cfg/management/commands/script.py +25 -21
  220. django_cfg/management/commands/show_config.py +6 -1
  221. django_cfg/management/commands/show_urls.py +8 -3
  222. django_cfg/management/commands/superuser.py +5 -4
  223. django_cfg/management/commands/task_clear.py +8 -3
  224. django_cfg/management/commands/task_status.py +8 -3
  225. django_cfg/management/commands/test_email.py +6 -1
  226. django_cfg/management/commands/test_telegram.py +6 -1
  227. django_cfg/management/commands/test_twilio.py +6 -1
  228. django_cfg/management/commands/tree.py +7 -4
  229. django_cfg/models/__init__.py +88 -3
  230. django_cfg/models/api/__init__.py +27 -0
  231. django_cfg/models/{api.py → api/config.py} +1 -1
  232. django_cfg/models/api/drf/__init__.py +21 -0
  233. django_cfg/models/api/drf/config.py +101 -0
  234. django_cfg/models/api/drf/redoc.py +31 -0
  235. django_cfg/models/api/drf/spectacular.py +129 -0
  236. django_cfg/models/api/drf/swagger.py +59 -0
  237. django_cfg/models/{api_keys.py → api/keys.py} +16 -6
  238. django_cfg/models/{limits.py → api/limits.py} +0 -1
  239. django_cfg/models/base/__init__.py +14 -0
  240. django_cfg/models/django/__init__.py +16 -0
  241. django_cfg/models/{constance.py → django/constance.py} +1 -1
  242. django_cfg/models/{environment.py → django/environment.py} +1 -1
  243. django_cfg/models/infrastructure/__init__.py +17 -0
  244. django_cfg/models/{cache.py → infrastructure/cache.py} +3 -2
  245. django_cfg/models/infrastructure/database/__init__.py +22 -0
  246. django_cfg/models/infrastructure/database/config.py +265 -0
  247. django_cfg/models/infrastructure/database/converters.py +91 -0
  248. django_cfg/models/infrastructure/database/parsers.py +96 -0
  249. django_cfg/models/infrastructure/database/routing.py +85 -0
  250. django_cfg/models/infrastructure/database/validators.py +170 -0
  251. django_cfg/models/{logging.py → infrastructure/logging.py} +1 -1
  252. django_cfg/models/{security.py → infrastructure/security.py} +2 -2
  253. django_cfg/models/ngrok/__init__.py +11 -0
  254. django_cfg/models/ngrok/auth.py +37 -0
  255. django_cfg/models/ngrok/config.py +77 -0
  256. django_cfg/models/ngrok/tunnel.py +35 -0
  257. django_cfg/models/payments/__init__.py +20 -0
  258. django_cfg/models/payments/api_keys.py +57 -0
  259. django_cfg/models/{payments.py → payments/config.py} +56 -154
  260. django_cfg/models/payments/providers/__init__.py +15 -0
  261. django_cfg/models/payments/providers/base.py +25 -0
  262. django_cfg/models/payments/providers/nowpayments.py +48 -0
  263. django_cfg/models/services/__init__.py +18 -0
  264. django_cfg/models/services/base.py +65 -0
  265. django_cfg/models/{email.py → services/email.py} +1 -1
  266. django_cfg/models/services/telegram.py +172 -0
  267. django_cfg/models/tasks/__init__.py +51 -0
  268. django_cfg/models/tasks/backends.py +250 -0
  269. django_cfg/models/tasks/config.py +314 -0
  270. django_cfg/models/tasks/utils.py +174 -0
  271. django_cfg/modules/base.py +18 -3
  272. django_cfg/modules/django_admin/decorators/actions.py +1 -1
  273. django_cfg/modules/django_admin/decorators/display.py +1 -1
  274. django_cfg/modules/django_admin/mixins/standalone_actions_mixin.py +1 -1
  275. django_cfg/modules/django_currency/examples/__init__.py +3 -0
  276. django_cfg/modules/django_currency/examples/example_database_usage.py +144 -0
  277. django_cfg/modules/django_drf_theme/CHANGELOG.md +210 -0
  278. django_cfg/modules/django_drf_theme/EXAMPLE.md +465 -0
  279. django_cfg/modules/django_drf_theme/IMPLEMENTATION.md +232 -0
  280. django_cfg/modules/django_drf_theme/README.md +207 -0
  281. django_cfg/modules/django_drf_theme/TAILWIND_CDN_GUIDE.md +274 -0
  282. django_cfg/modules/django_drf_theme/__init__.py +23 -0
  283. django_cfg/modules/django_drf_theme/apps.py +15 -0
  284. django_cfg/modules/django_drf_theme/renderers.py +58 -0
  285. django_cfg/modules/django_drf_theme/templates/rest_framework/tailwind/api.html +375 -0
  286. django_cfg/modules/django_drf_theme/templates/rest_framework/tailwind/base.html +938 -0
  287. django_cfg/modules/django_drf_theme/templates/rest_framework/tailwind/forms/filter_form.html +132 -0
  288. django_cfg/modules/django_drf_theme/templates/rest_framework/tailwind/forms/raw_data_form.html +123 -0
  289. django_cfg/modules/django_drf_theme/templatetags/__init__.py +1 -0
  290. django_cfg/modules/django_drf_theme/templatetags/tailwind_tags.py +57 -0
  291. django_cfg/modules/django_email/__init__.py +14 -0
  292. django_cfg/modules/{django_email.py → django_email/service.py} +78 -113
  293. django_cfg/modules/django_email/utils.py +40 -0
  294. django_cfg/modules/django_health/__init__.py +9 -0
  295. django_cfg/modules/{django_health.py → django_health/service.py} +23 -21
  296. django_cfg/modules/django_ipc_client/README.md +346 -0
  297. django_cfg/modules/django_ipc_client/__init__.py +51 -0
  298. django_cfg/modules/django_ipc_client/client.py +540 -0
  299. django_cfg/modules/django_ipc_client/config.py +207 -0
  300. django_cfg/modules/django_ipc_client/dashboard/README.md +517 -0
  301. django_cfg/modules/django_ipc_client/dashboard/UNFOLD_INTEGRATION.md +439 -0
  302. django_cfg/modules/django_ipc_client/dashboard/__init__.py +11 -0
  303. django_cfg/modules/django_ipc_client/dashboard/apps.py +22 -0
  304. django_cfg/modules/django_ipc_client/dashboard/monitor.py +435 -0
  305. django_cfg/modules/django_ipc_client/dashboard/static/django_ipc_dashboard/js/dashboard.js +373 -0
  306. django_cfg/modules/django_ipc_client/dashboard/templates/django_ipc_dashboard/base.html +76 -0
  307. django_cfg/modules/django_ipc_client/dashboard/templates/django_ipc_dashboard/dashboard.html +200 -0
  308. django_cfg/modules/django_ipc_client/dashboard/urls.py +22 -0
  309. django_cfg/modules/django_ipc_client/dashboard/urls_admin.py +9 -0
  310. django_cfg/modules/django_ipc_client/dashboard/views.py +251 -0
  311. django_cfg/modules/django_ipc_client/exceptions.py +201 -0
  312. django_cfg/modules/django_llm/llm/client.py +155 -550
  313. django_cfg/modules/django_llm/llm/embeddings/__init__.py +13 -0
  314. django_cfg/modules/django_llm/llm/embeddings/mock_embedder.py +106 -0
  315. django_cfg/modules/django_llm/llm/embeddings/openai_embedder.py +79 -0
  316. django_cfg/modules/django_llm/llm/models_api/__init__.py +9 -0
  317. django_cfg/modules/django_llm/llm/models_api/models_query.py +163 -0
  318. django_cfg/modules/django_llm/llm/providers/__init__.py +15 -0
  319. django_cfg/modules/django_llm/llm/providers/config_builder.py +103 -0
  320. django_cfg/modules/django_llm/llm/providers/provider_manager.py +148 -0
  321. django_cfg/modules/django_llm/llm/providers/provider_selector.py +60 -0
  322. django_cfg/modules/django_llm/llm/requests/__init__.py +15 -0
  323. django_cfg/modules/django_llm/llm/requests/cache_manager.py +170 -0
  324. django_cfg/modules/django_llm/llm/requests/chat_handler.py +199 -0
  325. django_cfg/modules/django_llm/llm/requests/embedding_handler.py +113 -0
  326. django_cfg/modules/django_llm/llm/responses/__init__.py +9 -0
  327. django_cfg/modules/django_llm/llm/responses/response_builder.py +131 -0
  328. django_cfg/modules/django_llm/llm/stats/__init__.py +9 -0
  329. django_cfg/modules/django_llm/llm/stats/stats_manager.py +107 -0
  330. django_cfg/modules/django_llm/translator/detectors/__init__.py +13 -0
  331. django_cfg/modules/django_llm/translator/detectors/language_detector.py +90 -0
  332. django_cfg/modules/django_llm/translator/detectors/script_detector.py +153 -0
  333. django_cfg/modules/django_llm/translator/stats/__init__.py +11 -0
  334. django_cfg/modules/django_llm/translator/stats/stats_tracker.py +85 -0
  335. django_cfg/modules/django_llm/translator/translator.py +150 -603
  336. django_cfg/modules/django_llm/translator/translators/__init__.py +15 -0
  337. django_cfg/modules/django_llm/translator/translators/json_translator.py +316 -0
  338. django_cfg/modules/django_llm/translator/translators/text_translator.py +139 -0
  339. django_cfg/modules/django_llm/translator/utils/__init__.py +13 -0
  340. django_cfg/modules/django_llm/translator/utils/prompt_builder.py +110 -0
  341. django_cfg/modules/django_llm/translator/utils/text_utils.py +114 -0
  342. django_cfg/modules/django_logging/FIXES_SUMMARY.md +276 -0
  343. django_cfg/modules/django_logging/LOGGING_GUIDE.md +504 -0
  344. django_cfg/modules/django_logging/__init__.py +14 -0
  345. django_cfg/modules/{django_logger.py → django_logging/django_logger.py} +13 -13
  346. django_cfg/modules/{logger.py → django_logging/logger.py} +14 -4
  347. django_cfg/modules/django_ngrok/__init__.py +39 -0
  348. django_cfg/modules/{django_ngrok.py → django_ngrok/service.py} +14 -42
  349. django_cfg/modules/django_rpc_old/POETRY.md +344 -0
  350. django_cfg/modules/django_rpc_old/README.md +397 -0
  351. django_cfg/modules/django_rpc_old/TESTING.md +358 -0
  352. django_cfg/modules/django_rpc_old/__init__.py +39 -0
  353. django_cfg/modules/django_rpc_old/client.py +531 -0
  354. django_cfg/modules/django_rpc_old/config.py +279 -0
  355. django_cfg/modules/django_rpc_old/exceptions.py +172 -0
  356. django_cfg/modules/django_tailwind/README.md +478 -0
  357. django_cfg/modules/django_tailwind/__init__.py +7 -0
  358. django_cfg/modules/django_tailwind/apps.py +10 -0
  359. django_cfg/modules/django_tailwind/templates/django_tailwind/app.html +5 -0
  360. django_cfg/modules/django_tailwind/templates/django_tailwind/base.html +117 -0
  361. django_cfg/modules/django_tailwind/templates/django_tailwind/components/navbar.html +124 -0
  362. django_cfg/modules/django_tailwind/templates/django_tailwind/components/theme_toggle.html +54 -0
  363. django_cfg/modules/django_tailwind/templates/django_tailwind/components/user_menu.html +116 -0
  364. django_cfg/modules/django_tailwind/templates/django_tailwind/simple.html +46 -0
  365. django_cfg/modules/django_tailwind/templatetags/__init__.py +1 -0
  366. django_cfg/modules/django_tailwind/templatetags/tailwind_info.py +185 -0
  367. django_cfg/modules/django_tasks/__init__.py +29 -0
  368. django_cfg/modules/django_tasks/factory.py +127 -0
  369. django_cfg/modules/{django_tasks.py → django_tasks/service.py} +45 -274
  370. django_cfg/modules/django_tasks/settings.py +107 -0
  371. django_cfg/modules/django_telegram/__init__.py +29 -0
  372. django_cfg/modules/{django_telegram.py → django_telegram/service.py} +45 -113
  373. django_cfg/modules/django_telegram/utils.py +62 -0
  374. django_cfg/modules/django_twilio/__init__.py +54 -107
  375. django_cfg/modules/django_twilio/_imports.py +30 -0
  376. django_cfg/modules/django_twilio/base.py +192 -0
  377. django_cfg/modules/django_twilio/email_otp.py +227 -0
  378. django_cfg/modules/django_twilio/sendgrid_service.py +1 -1
  379. django_cfg/modules/django_twilio/simple_service.py +1 -2
  380. django_cfg/modules/django_twilio/sms.py +94 -0
  381. django_cfg/modules/django_twilio/twilio_service.py +2 -3
  382. django_cfg/modules/django_twilio/unified.py +310 -0
  383. django_cfg/modules/django_twilio/utils.py +190 -0
  384. django_cfg/modules/django_twilio/whatsapp.py +137 -0
  385. django_cfg/modules/django_unfold/callbacks/base.py +198 -7
  386. django_cfg/modules/django_unfold/callbacks/main.py +102 -10
  387. django_cfg/modules/django_unfold/dashboard.py +65 -43
  388. django_cfg/modules/django_unfold/models/config.py +13 -12
  389. django_cfg/modules/django_unfold/models/navigation.py +8 -3
  390. django_cfg/modules/django_unfold/models/tabs.py +2 -2
  391. django_cfg/modules/django_unfold/templates/unfold/helpers/app_list.html +102 -0
  392. django_cfg/registry/core.py +24 -26
  393. django_cfg/registry/modules.py +5 -2
  394. django_cfg/registry/services.py +20 -3
  395. django_cfg/registry/third_party.py +8 -8
  396. django_cfg/static/admin/css/dashboard.css +260 -0
  397. django_cfg/static/admin/js/commands.js +171 -0
  398. django_cfg/static/admin/js/dashboard.js +126 -0
  399. django_cfg/templates/admin/components/management_commands.js +375 -0
  400. django_cfg/templates/admin/components/progress_bar.html +18 -23
  401. django_cfg/templates/admin/examples/component_class_example.html +156 -0
  402. django_cfg/templates/admin/index.html +48 -20
  403. django_cfg/templates/admin/index_new.html +106 -0
  404. django_cfg/templates/admin/layouts/base_dashboard.html +60 -0
  405. django_cfg/templates/admin/layouts/dashboard_with_tabs.html +1 -20
  406. django_cfg/templates/admin/sections/commands_section.html +626 -0
  407. django_cfg/templates/admin/sections/overview_section.html +112 -0
  408. django_cfg/templates/admin/sections/stats_section.html +35 -0
  409. django_cfg/templates/admin/sections/system_section.html +99 -0
  410. django_cfg/templates/admin/snippets/components/CHARTS_GUIDE.md +322 -0
  411. django_cfg/templates/admin/snippets/components/activity_tracker.html +85 -47
  412. django_cfg/templates/admin/snippets/components/charts_section.html +154 -64
  413. django_cfg/templates/admin/snippets/components/django_commands.html +3 -3
  414. django_cfg/templates/admin/snippets/components/recent_activity_improved.html +25 -0
  415. django_cfg/templates/admin/snippets/components/recent_users_table.html +1 -1
  416. django_cfg/templates/admin/snippets/components/system_metrics.html +179 -93
  417. django_cfg/templates/admin/snippets/zones/zones_table.html +2 -2
  418. django_cfg/templatetags/django_cfg.py +7 -1
  419. django_cfg/utils/smart_defaults.py +4 -4
  420. django_cfg-1.4.3.dist-info/METADATA +533 -0
  421. {django_cfg-1.3.13.dist-info → django_cfg-1.4.3.dist-info}/RECORD +432 -195
  422. django_cfg/apps/accounts/utils/auth_email_service.py +0 -84
  423. django_cfg/apps/payments/services/providers/nowpayments/parsers.py +0 -879
  424. django_cfg/core/generation.py +0 -621
  425. django_cfg/management/commands/validate_config.py +0 -189
  426. django_cfg/models/database.py +0 -480
  427. django_cfg/models/drf.py +0 -272
  428. django_cfg/models/ngrok.py +0 -122
  429. django_cfg/models/services.py +0 -440
  430. django_cfg/models/tasks.py +0 -550
  431. django_cfg/modules/django_twilio/service.py +0 -942
  432. django_cfg/template_archive/django_sample.zip +0 -0
  433. django_cfg/templates/rest_framework/api.html +0 -12
  434. django_cfg/utils/toolkit.py +0 -703
  435. django_cfg-1.3.13.dist-info/METADATA +0 -1029
  436. /django_cfg/apps/accounts/management/commands/{test_otp.py → otp_test.py} +0 -0
  437. /django_cfg/core/{environment.py → environment/detector.py} +0 -0
  438. /django_cfg/models/{cors.py → api/cors.py} +0 -0
  439. /django_cfg/models/{jwt.py → api/jwt.py} +0 -0
  440. /django_cfg/models/{base.py → base/config.py} +0 -0
  441. /django_cfg/models/{cfg.py → base/module.py} +0 -0
  442. /django_cfg/models/{revolution.py → django/revolution.py} +0 -0
  443. /django_cfg/modules/{dramatiq_setup.py → django_tasks/dramatiq_setup.py} +0 -0
  444. {django_cfg-1.3.13.dist-info → django_cfg-1.4.3.dist-info}/WHEEL +0 -0
  445. {django_cfg-1.3.13.dist-info → django_cfg-1.4.3.dist-info}/entry_points.txt +0 -0
  446. {django_cfg-1.3.13.dist-info → django_cfg-1.4.3.dist-info}/licenses/LICENSE +0 -0
@@ -3,27 +3,217 @@ Base utilities and helper functions for callbacks.
3
3
  """
4
4
 
5
5
  import logging
6
- from typing import Dict, Any, List
6
+ import inspect
7
+ from typing import Dict, Any, List, Set, Optional
7
8
  from django.contrib.auth import get_user_model
8
9
  from django.core.management import get_commands
10
+ from django.core.management.base import BaseCommand
9
11
  import importlib
10
12
 
11
13
  logger = logging.getLogger(__name__)
12
14
 
13
15
 
16
+ # Keywords in docstring/code that indicate command should not be in web UI
17
+ DANGEROUS_KEYWORDS: Set[str] = {
18
+ 'questionary', 'input(', 'stdin', 'interactive', # Requires user input
19
+ 'destructive', 'dangerous', 'irreversible', # Explicitly marked as dangerous
20
+ 'runserver', 'testserver', # Dev servers
21
+ }
22
+
23
+ # Commands that should NEVER appear (absolute blacklist)
24
+ ABSOLUTE_BLACKLIST: Set[str] = {
25
+ # Destructive database commands
26
+ 'flush', 'sqlflush', 'dbshell',
27
+
28
+ # Shell access (security risk)
29
+ 'shell', 'shell_plus',
30
+
31
+ # Development server (not for web execution)
32
+ 'runserver', 'testserver', 'runserver_ngrok',
33
+
34
+ # Project generation (not applicable in running app)
35
+ 'startapp', 'startproject',
36
+
37
+ # SQL commands (direct SQL, potentially dangerous)
38
+ 'sqlmigrate', 'sqlsequencereset',
39
+ }
40
+
41
+
42
+ def analyze_command_safety(command_class: BaseCommand, command_name: str) -> Dict[str, Any]:
43
+ """
44
+ Analyze command to determine if it's safe for web execution.
45
+
46
+ Checks:
47
+ 1. Explicit metadata (web_executable, requires_input, is_destructive)
48
+ 2. Docstring analysis for dangerous keywords
49
+ 3. Source code analysis for interactive input
50
+ 4. Required arguments analysis
51
+
52
+ Returns:
53
+ Dict with safety analysis results
54
+ """
55
+ analysis = {
56
+ 'is_safe': True,
57
+ 'reasons': [],
58
+ 'requires_input': False,
59
+ 'is_destructive': False,
60
+ 'web_executable': None,
61
+ }
62
+
63
+ # Check explicit metadata (highest priority)
64
+ if hasattr(command_class, 'web_executable'):
65
+ analysis['web_executable'] = command_class.web_executable
66
+ if not command_class.web_executable:
67
+ analysis['is_safe'] = False
68
+ analysis['reasons'].append('Command explicitly marked as not web-executable')
69
+ return analysis
70
+
71
+ if hasattr(command_class, 'requires_input'):
72
+ analysis['requires_input'] = command_class.requires_input
73
+ if command_class.requires_input:
74
+ analysis['is_safe'] = False
75
+ analysis['reasons'].append('Command requires interactive input')
76
+ return analysis
77
+
78
+ if hasattr(command_class, 'is_destructive'):
79
+ analysis['is_destructive'] = command_class.is_destructive
80
+ if command_class.is_destructive:
81
+ analysis['is_safe'] = False
82
+ analysis['reasons'].append('Command is marked as destructive')
83
+ return analysis
84
+
85
+ # Analyze docstring for dangerous keywords
86
+ docstring = (inspect.getdoc(command_class) or '').lower()
87
+ for keyword in DANGEROUS_KEYWORDS:
88
+ if keyword in docstring:
89
+ analysis['is_safe'] = False
90
+ analysis['reasons'].append(f'Docstring contains dangerous keyword: {keyword}')
91
+ return analysis
92
+
93
+ # Analyze source code for interactive input
94
+ try:
95
+ source = inspect.getsource(command_class)
96
+ if 'questionary' in source or 'input(' in source:
97
+ analysis['is_safe'] = False
98
+ analysis['requires_input'] = True
99
+ analysis['reasons'].append('Command requires interactive user input')
100
+ return analysis
101
+ except Exception:
102
+ # Can't analyze source, be safe
103
+ pass
104
+
105
+ return analysis
106
+
107
+
108
+ def is_command_allowed(command_name: str, app_name: str) -> bool:
109
+ """
110
+ Check if command should be displayed in web interface.
111
+
112
+ Priority:
113
+ 1. Custom blacklist from settings (DJANGO_CFG_COMMANDS_BLACKLIST)
114
+ 2. Absolute blacklist - always exclude
115
+ 3. Custom whitelist from settings (DJANGO_CFG_COMMANDS_WHITELIST)
116
+ 4. Command metadata analysis (web_executable, requires_input, etc.)
117
+ 5. django_cfg apps - analyze each command
118
+ 6. Django core - be selective (only safe utility commands)
119
+ 7. Third party - only if explicitly whitelisted
120
+
121
+ You can customize filtering in settings.py:
122
+
123
+ DJANGO_CFG_COMMANDS_BLACKLIST = {'my_dangerous_command'}
124
+ DJANGO_CFG_COMMANDS_WHITELIST = {'my_safe_command'}
125
+
126
+ Or add metadata to your Command class:
127
+
128
+ class Command(BaseCommand):
129
+ web_executable = True # Allow in web UI
130
+ requires_input = False # Doesn't need interactive input
131
+ is_destructive = False # Not destructive
132
+ """
133
+ from django.conf import settings
134
+
135
+ # Custom blacklist from settings (highest priority)
136
+ custom_blacklist = getattr(settings, 'DJANGO_CFG_COMMANDS_BLACKLIST', set())
137
+ if command_name in custom_blacklist:
138
+ return False
139
+
140
+ # Absolute blacklist
141
+ if command_name in ABSOLUTE_BLACKLIST:
142
+ return False
143
+
144
+ # Custom whitelist from settings
145
+ custom_whitelist = getattr(settings, 'DJANGO_CFG_COMMANDS_WHITELIST', set())
146
+ if command_name in custom_whitelist:
147
+ return True
148
+
149
+ # Load and analyze command
150
+ try:
151
+ # Determine module path
152
+ if app_name == 'django_cfg':
153
+ module_path = f'django_cfg.management.commands.{command_name}'
154
+ elif app_name.startswith('django.'):
155
+ module_path = f'{app_name}.management.commands.{command_name}'
156
+ else:
157
+ module_path = f'{app_name}.management.commands.{command_name}'
158
+
159
+ command_module = importlib.import_module(module_path)
160
+ if hasattr(command_module, 'Command'):
161
+ command_class = command_module.Command
162
+
163
+ # Analyze command safety
164
+ analysis = analyze_command_safety(command_class, command_name)
165
+
166
+ # If command has explicit web_executable metadata, use it
167
+ if analysis['web_executable'] is not None:
168
+ return analysis['web_executable']
169
+
170
+ # If analysis says it's unsafe, exclude
171
+ if not analysis['is_safe']:
172
+ logger.debug(f"Command {command_name} excluded: {', '.join(analysis['reasons'])}")
173
+ return False
174
+ except Exception as e:
175
+ # Can't load/analyze command
176
+ logger.debug(f"Could not analyze command {command_name}: {e}")
177
+ # Be conservative - if we can't analyze, exclude unless from trusted source
178
+ pass
179
+
180
+ # Django CFG commands - include if analysis passed
181
+ if app_name == 'django_cfg':
182
+ return True
183
+
184
+ # Safe Django core commands (utility/read-only)
185
+ safe_django_core = {
186
+ 'check', 'diffsettings', 'showmigrations',
187
+ 'createcachetable', 'sendtestemail',
188
+ }
189
+ if app_name.startswith('django.') and command_name in safe_django_core:
190
+ return True
191
+
192
+ # Exclude other Django core by default
193
+ if app_name.startswith('django.'):
194
+ return False
195
+
196
+ # Third-party apps - only whitelisted
197
+ return False
198
+
199
+
14
200
  def get_available_commands():
15
- """Get all available Django management commands."""
201
+ """Get all available Django management commands (filtered for safety)."""
16
202
  commands_dict = get_commands()
17
203
  commands_list = []
18
-
204
+
19
205
  for command_name, app_name in commands_dict.items():
206
+ # Filter out unsafe/unwanted commands
207
+ if not is_command_allowed(command_name, app_name):
208
+ continue
209
+
20
210
  try:
21
211
  # Try to get command description
22
212
  if app_name == 'django_cfg':
23
213
  module_path = f'django_cfg.management.commands.{command_name}'
24
214
  else:
25
215
  module_path = f'{app_name}.management.commands.{command_name}'
26
-
216
+
27
217
  try:
28
218
  command_module = importlib.import_module(module_path)
29
219
  if hasattr(command_module, 'Command'):
@@ -33,7 +223,7 @@ def get_available_commands():
33
223
  description = f'{command_name} command'
34
224
  except ImportError:
35
225
  description = f'{command_name} command'
36
-
226
+
37
227
  commands_list.append({
38
228
  'name': command_name,
39
229
  'app': app_name,
@@ -41,10 +231,11 @@ def get_available_commands():
41
231
  'is_core': app_name.startswith('django.'),
42
232
  'is_custom': app_name == 'django_cfg',
43
233
  })
44
- except Exception:
234
+ except Exception as e:
45
235
  # Skip problematic commands
236
+ logger.debug(f"Skipping command {command_name}: {e}")
46
237
  continue
47
-
238
+
48
239
  return commands_list
49
240
 
50
241
 
@@ -9,10 +9,10 @@ import json
9
9
  from typing import Dict, Any
10
10
 
11
11
  from django.utils import timezone
12
- from django.conf import settings
13
12
 
14
13
  from ...base import BaseCfgModule
15
14
  from ..models.dashboard import DashboardData
15
+ from django_cfg.core.state import get_current_config
16
16
 
17
17
  from .statistics import StatisticsCallbacks
18
18
  from .system import SystemCallbacks
@@ -23,6 +23,13 @@ from .revolution import RevolutionCallbacks
23
23
  from .users import UsersCallbacks
24
24
  from .base import get_user_admin_urls
25
25
 
26
+ # Import new dashboard sections
27
+ from django_cfg.dashboard.sections.overview import OverviewSection
28
+ from django_cfg.dashboard.sections.stats import StatsSection
29
+ from django_cfg.dashboard.sections.system import SystemSection
30
+ from django_cfg.dashboard.sections.commands import CommandsSection
31
+ from django_cfg.dashboard.debug import save_section_render
32
+
26
33
  logger = logging.getLogger(__name__)
27
34
 
28
35
 
@@ -50,13 +57,95 @@ class UnfoldCallbacks(
50
57
  Returns all dashboard data as Pydantic models for type safety.
51
58
  """
52
59
  try:
53
- # Get dashboard data using Pydantic models
60
+ # Get current config for debug and environment settings
61
+ config = get_current_config()
62
+
63
+ # Log debug status
64
+ debug_enabled = config and config.debug
65
+ logger.info(f"[DEBUG MODE] Dashboard rendering with debug={debug_enabled} (config.debug={getattr(config, 'debug', 'N/A')})")
66
+
67
+ # Get dashboard data first
54
68
  user_stats = self.get_user_statistics()
55
69
  support_stats = self.get_support_statistics()
56
70
  system_health = self.get_system_health()
57
71
  quick_actions = self.get_quick_actions()
58
-
59
- # Combine all stat cards
72
+
73
+ # Parse time range from query parameters (default: 7 days)
74
+ try:
75
+ time_range = int(request.GET.get('range', 7))
76
+ # Validate range
77
+ if time_range not in [7, 30, 90]:
78
+ time_range = 7
79
+ except (ValueError, TypeError):
80
+ time_range = 7
81
+
82
+ # Create navigation for time range filter
83
+ navigation = [
84
+ {
85
+ "title": "7 Days",
86
+ "link": "?range=7",
87
+ "active": time_range == 7,
88
+ "icon": "calendar_today"
89
+ },
90
+ {
91
+ "title": "30 Days",
92
+ "link": "?range=30",
93
+ "active": time_range == 30,
94
+ "icon": "date_range"
95
+ },
96
+ {
97
+ "title": "90 Days",
98
+ "link": "?range=90",
99
+ "active": time_range == 90,
100
+ "icon": "event"
101
+ },
102
+ ]
103
+
104
+ # Render new dashboard sections
105
+ try:
106
+ # Create overview section and pass quick_actions + time_range + navigation
107
+ overview_sec = OverviewSection(request)
108
+ # Add quick_actions, time_range, and navigation to render context
109
+ overview_section = overview_sec.render(
110
+ quick_actions=[action.model_dump() for action in quick_actions],
111
+ time_range=time_range,
112
+ navigation=navigation
113
+ )
114
+ # Debug: save render (only in debug mode)
115
+ if config and config.debug:
116
+ save_section_render('overview', overview_section)
117
+ except Exception as e:
118
+ logger.error(f"Failed to render overview section: {e}", exc_info=True)
119
+ overview_section = None
120
+
121
+ try:
122
+ stats_section = StatsSection(request).render()
123
+ # Debug: save render (only in debug mode)
124
+ if config and config.debug:
125
+ save_section_render('stats', stats_section)
126
+ except Exception as e:
127
+ logger.error(f"Failed to render stats section: {e}", exc_info=True)
128
+ stats_section = None
129
+
130
+ try:
131
+ system_section = SystemSection(request).render()
132
+ # Debug: save render (only in debug mode)
133
+ if config and config.debug:
134
+ save_section_render('system', system_section)
135
+ except Exception as e:
136
+ logger.error(f"Failed to render system section: {e}", exc_info=True)
137
+ system_section = None
138
+
139
+ try:
140
+ commands_section = CommandsSection(request).render()
141
+ # Debug: save render (only in debug mode)
142
+ if config and config.debug:
143
+ save_section_render('commands', commands_section)
144
+ except Exception as e:
145
+ logger.error(f"Failed to render commands section: {e}", exc_info=True)
146
+ commands_section = None
147
+
148
+ # Combine all stat cards (data already loaded above)
60
149
  all_stats = user_stats + support_stats
61
150
 
62
151
  dashboard_data = DashboardData(
@@ -64,27 +153,30 @@ class UnfoldCallbacks(
64
153
  system_health=system_health,
65
154
  quick_actions=quick_actions,
66
155
  last_updated=timezone.now().strftime("%Y-%m-%d %H:%M:%S"),
67
- environment=getattr(settings, "ENVIRONMENT", "development"),
156
+ environment=getattr(config.environment, 'name', 'development') if config and hasattr(config, 'environment') else "development",
68
157
  )
69
158
 
70
159
  # Convert to template context (using to_dict for Unfold compatibility)
71
160
  cards_data = [card.to_dict() for card in dashboard_data.stat_cards]
72
161
 
73
162
  context.update({
163
+ # New dashboard sections (rendered HTML)
164
+ "overview_section": overview_section,
165
+ "stats_section": stats_section,
166
+ "system_section": system_section,
167
+ "commands_section": commands_section,
168
+
74
169
  # Statistics cards
75
170
  "cards": cards_data,
76
171
  "user_stats": [card.to_dict() for card in user_stats],
77
172
  "support_stats": [card.to_dict() for card in support_stats],
78
-
173
+
79
174
  # System health (convert to dict for template)
80
175
  "system_health": {
81
176
  item.component + "_status": item.status
82
177
  for item in dashboard_data.system_health
83
178
  },
84
-
85
- # System metrics
86
- "system_metrics": self.get_system_metrics(),
87
-
179
+
88
180
  # Quick actions
89
181
  "quick_actions": [
90
182
  action.model_dump() for action in dashboard_data.quick_actions
@@ -19,16 +19,33 @@ class DashboardManager(BaseCfgModule):
19
19
  Dashboard configuration manager for Unfold.
20
20
  """
21
21
 
22
- def __init__(self):
22
+ def __init__(self, config=None):
23
23
  """Initialize dashboard manager."""
24
24
  super().__init__()
25
- self.config = self.get_config()
26
-
27
- def _get_default_dropdown_items(self) -> List[Dict[str, Any]]:
25
+ # Lazy load config to avoid circular import during settings generation
26
+ self._config = config
27
+ self._config_loaded = config is not None
28
+
29
+ @property
30
+ def config(self):
31
+ """Lazy load config on first access."""
32
+ if not self._config_loaded:
33
+ try:
34
+ self._config = self.get_config()
35
+ except Exception:
36
+ # Config cannot be loaded (e.g., during settings generation)
37
+ # Set to None and mark as loaded to avoid repeated attempts
38
+ self._config = None
39
+ finally:
40
+ self._config_loaded = True
41
+ return self._config
42
+
43
+ @staticmethod
44
+ def _get_default_dropdown_items() -> List[Dict[str, Any]]:
28
45
  """Get default dropdown menu items for Unfold admin (lazy import to avoid circular imports)."""
29
46
  from django_cfg.config import get_default_dropdown_items
30
47
  dropdown_items = get_default_dropdown_items()
31
-
48
+
32
49
  # Convert SiteDropdownItem objects to dictionaries for Unfold
33
50
  return [item.to_dict() for item in dropdown_items]
34
51
 
@@ -47,6 +64,37 @@ class DashboardManager(BaseCfgModule):
47
64
  ]
48
65
  ),
49
66
  ]
67
+
68
+ # Add Operations section (System & Monitoring tools)
69
+ operations_items = []
70
+
71
+ # RPC Dashboard (if enabled)
72
+ if self.is_rpc_enabled():
73
+ operations_items.append(
74
+ NavigationItem(title="RPC Dashboard", icon=Icons.MONITOR_HEART, link="/cfg/admin/rpc/")
75
+ )
76
+
77
+ # Background Tasks (if enabled)
78
+ if self.should_enable_tasks():
79
+ operations_items.extend([
80
+ NavigationItem(title="Background Tasks", icon=Icons.TASK, link="/admin/django_dramatiq/task/"),
81
+ NavigationItem(title="Task Dashboard", icon=Icons.SETTINGS_APPLICATIONS, link="/cfg/admin/django_cfg_tasks/admin/dashboard/"),
82
+ ])
83
+
84
+ # Maintenance Mode (if enabled)
85
+ if self.is_maintenance_enabled():
86
+ operations_items.append(
87
+ NavigationItem(title="Maintenance", icon=Icons.BUILD, link="/admin/maintenance/cloudflaresite/")
88
+ )
89
+
90
+ # Add Operations section if there are any items
91
+ if operations_items:
92
+ navigation_sections.append(NavigationSection(
93
+ title="Operations",
94
+ separator=True,
95
+ collapsible=True,
96
+ items=operations_items
97
+ ))
50
98
 
51
99
  # Add Accounts section if enabled
52
100
  if self.is_accounts_enabled():
@@ -134,46 +182,20 @@ class DashboardManager(BaseCfgModule):
134
182
  NavigationItem(title="Chat Messages", icon=Icons.MESSAGE, link="/admin/django_cfg_knowbase/chatmessage/"),
135
183
  ]
136
184
  ))
137
-
138
- # Add Tasks section if knowbase or agents are enabled
139
- if self.should_enable_tasks():
140
- navigation_sections.append(NavigationSection(
141
- title="Background Tasks",
142
- separator=True,
143
- collapsible=True,
144
- items=[
145
- NavigationItem(title="Task Queue", icon=Icons.QUEUE, link="/admin/django_dramatiq/task/"),
146
- NavigationItem(title="Task Dashboard", icon=Icons.SETTINGS_APPLICATIONS, link="/cfg/admin/django_cfg_tasks/admin/dashboard/"),
147
- ]
148
- ))
149
-
150
- # Add Maintenance section if enabled
151
- if self.is_maintenance_enabled():
152
- navigation_sections.append(NavigationSection(
153
- title="Maintenance Mode",
154
- separator=True,
155
- collapsible=True,
156
- items=[
157
- NavigationItem(title="Cloudflare Sites", icon=Icons.CLOUD, link="/admin/maintenance/cloudflaresite/"),
158
- NavigationItem(title="API Keys", icon=Icons.KEY, link="/admin/maintenance/cloudflareapikey/"),
159
- NavigationItem(title="Maintenance Logs", icon=Icons.HISTORY, link="/admin/maintenance/maintenancelog/"),
160
- NavigationItem(title="Scheduled Maintenance", icon=Icons.SCHEDULE, link="/admin/maintenance/scheduledmaintenance/"),
161
- ]
162
- ))
163
-
185
+
164
186
  # Add Payments section if enabled
165
187
  if self.is_payments_enabled():
166
188
  try:
167
189
  from django_cfg.models.payments import PaymentsConfig
168
190
  config = PaymentsConfig.get_current_config()
169
-
191
+
170
192
  payments_items = []
171
-
193
+
172
194
  # Main dashboard (always show if payments app enabled)
173
195
  payments_items.append(
174
196
  NavigationItem(title="Payment Dashboard", icon=Icons.DASHBOARD, link="/cfg/admin/django_cfg_payments/admin/")
175
197
  )
176
-
198
+
177
199
  # Always show basic admin models (even if payments functionality is disabled)
178
200
  payments_items.extend([
179
201
  NavigationItem(title="Universal Payments", icon=Icons.ACCOUNT_BALANCE, link="/admin/payments/universalpayment/"),
@@ -181,7 +203,7 @@ class DashboardManager(BaseCfgModule):
181
203
  NavigationItem(title="Networks", icon=Icons.LINK, link="/admin/payments/network/"),
182
204
  NavigationItem(title="Provider Currencies", icon=Icons.ACCOUNT_CIRCLE, link="/admin/payments/providercurrency/"),
183
205
  ])
184
-
206
+
185
207
  # Add advanced features only if payments functionality is enabled
186
208
  if config.enabled:
187
209
  # payments_items.append(
@@ -193,7 +215,7 @@ class DashboardManager(BaseCfgModule):
193
215
  # payments_items.append(
194
216
  # NavigationItem(title="Currency Converter", icon=Icons.CURRENCY_EXCHANGE, link="/cfg/admin/django_cfg_payments/admin/tools/converter/")
195
217
  # )
196
-
218
+
197
219
  # Show subscription features only if enabled
198
220
  if config.show_subscription_management():
199
221
  payments_items.extend([
@@ -201,39 +223,39 @@ class DashboardManager(BaseCfgModule):
201
223
  NavigationItem(title="Tariffs", icon=Icons.PRICE_CHANGE, link="/admin/payments/tariff/"),
202
224
  NavigationItem(title="Tariff Endpoint Groups", icon=Icons.GROUP, link="/admin/payments/tariffendpointgroup/"),
203
225
  ])
204
-
226
+
205
227
  # Show API management only if enabled
206
228
  if config.show_api_management():
207
229
  payments_items.extend([
208
230
  NavigationItem(title="API Keys", icon=Icons.KEY, link="/admin/payments/apikey/"),
209
231
  NavigationItem(title="Endpoint Groups", icon=Icons.GROUP, link="/admin/payments/endpointgroup/"),
210
232
  ])
211
-
233
+
212
234
  # Show balance/transaction features only if enabled
213
235
  if config.show_balance_management():
214
236
  payments_items.append(
215
237
  NavigationItem(title="Balances", icon=Icons.ACCOUNT_BALANCE_WALLET, link="/admin/payments/userbalance/")
216
238
  )
217
-
239
+
218
240
  if config.show_transaction_history():
219
241
  payments_items.append(
220
242
  NavigationItem(title="Transactions", icon=Icons.RECEIPT_LONG, link="/admin/payments/transaction/")
221
243
  )
222
-
244
+
223
245
  except Exception:
224
246
  # Fallback
225
247
  payments_items = [
226
248
  NavigationItem(title="Payment Dashboard", icon=Icons.DASHBOARD, link="/cfg/admin/django_cfg_payments/admin/"),
227
249
  NavigationItem(title="Universal Payments", icon=Icons.ACCOUNT_BALANCE, link="/admin/payments/universalpayment/"),
228
250
  ]
229
-
251
+
230
252
  navigation_sections.append(NavigationSection(
231
253
  title="Payments",
232
254
  separator=True,
233
255
  collapsible=True,
234
256
  items=payments_items
235
257
  ))
236
-
258
+
237
259
  # Convert all NavigationSection objects to dictionaries
238
260
  return [section.to_dict() for section in navigation_sections]
239
261
 
@@ -165,7 +165,7 @@ class UnfoldConfig(BaseModel):
165
165
 
166
166
  # Site branding
167
167
  site_title: str = Field(
168
- default="ConfigToolkit Admin",
168
+ default="Django-CFG Admin",
169
169
  description="Site title shown in admin"
170
170
  )
171
171
 
@@ -423,19 +423,21 @@ class UnfoldConfig(BaseModel):
423
423
  "show_all_applications": self.show_all_applications,
424
424
  }
425
425
 
426
- # Get default navigation from dashboard manager
426
+ # Get default navigation from dashboard manager first
427
+ nav_items = []
427
428
  try:
428
429
  from ..dashboard import DashboardManager
429
430
  dashboard = DashboardManager()
430
431
  nav_items = dashboard.get_navigation_config()
431
- except ImportError:
432
- nav_items = []
433
-
434
- # Add custom navigation from project (if defined)
432
+ except Exception as e:
433
+ # Catch all exceptions including circular imports during settings generation
434
+ # During settings generation, config discovery may fail - use empty nav
435
+ pass
436
+
437
+ # Add custom navigation from project (if defined) - appears after default
435
438
  if self.navigation:
436
- # Project has custom navigation - add it first
437
439
  nav_items.extend([group.to_dict() for group in self.navigation])
438
-
440
+
439
441
  # Add legacy navigation_items if configured
440
442
  if self.navigation_items:
441
443
  nav_items.extend(self.navigation_items)
@@ -445,13 +447,12 @@ class UnfoldConfig(BaseModel):
445
447
 
446
448
  # Add site dropdown - combine default from dashboard + project dropdown
447
449
  dropdown_items = []
448
-
450
+
449
451
  # First add default dropdown from dashboard manager
450
452
  try:
451
453
  from ..dashboard import DashboardManager
452
- dashboard = DashboardManager()
453
- dropdown_items.extend(dashboard._get_default_dropdown_items())
454
- except ImportError:
454
+ dropdown_items.extend(DashboardManager._get_default_dropdown_items())
455
+ except (ImportError, Exception):
455
456
  pass
456
457
 
457
458
  # Then add project-specific dropdown items
@@ -55,19 +55,24 @@ class NavigationItem(BaseModel):
55
55
  class NavigationSection(BaseModel):
56
56
  """Navigation section configuration."""
57
57
  model_config = ConfigDict(validate_assignment=True, extra="forbid")
58
-
58
+
59
59
  title: str = Field(..., min_length=1, description="Section title")
60
60
  separator: bool = Field(default=True, description="Show separator")
61
61
  collapsible: bool = Field(default=True, description="Section is collapsible")
62
+ open: bool = Field(default=False, description="Section is open by default")
62
63
  items: List[NavigationItem] = Field(default_factory=list, description="Navigation items")
63
-
64
+
64
65
  def to_dict(self) -> dict:
65
66
  """Convert to dictionary for Unfold admin."""
66
- return {
67
+ result = {
67
68
  "title": self.title,
68
69
  "separator": self.separator,
69
70
  "collapsible": self.collapsible,
70
71
  "items": [item.to_dict() for item in self.items],
71
72
  }
73
+ # Add open only if True (to avoid breaking existing navigation)
74
+ if self.open:
75
+ result["open"] = True
76
+ return result
72
77
 
73
78