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
@@ -1,281 +1,210 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Support Chat - {{ ticket.subject }}</title>
7
- <script src="https://cdn.tailwindcss.com"></script>
8
- <script>
9
- tailwind.config = {
10
- theme: {
11
- extend: {
12
- colors: {
13
- primary: {
14
- 50: '#f0f9ff',
15
- 500: '#3b82f6',
16
- 600: '#2563eb',
17
- 700: '#1d4ed8',
18
- }
19
- }
20
- }
21
- }
22
- }
23
- </script>
24
- </head>
25
- <body class="bg-gray-50 min-h-screen">
26
- <!-- Header -->
27
- <div class="bg-white shadow-sm border-b">
28
- <div class="max-w-4xl mx-auto px-4 py-4">
29
- <!-- Main Header Row -->
30
- <div class="flex items-start justify-between mb-3">
31
- <!-- Left: Ticket Title & Status -->
32
- <div class="flex-1 min-w-0">
33
- <div class="flex items-center space-x-3 mb-1">
34
- <!-- Status Badge -->
35
- <div class="flex items-center space-x-2">
36
- <div class="w-3 h-3 rounded-full {% if ticket.status == 'open' %}bg-green-500{% elif ticket.status == 'in_progress' %}bg-yellow-500{% else %}bg-gray-500{% endif %}"></div>
37
- <span class="text-sm font-medium text-gray-600">{{ ticket.get_status_display }}</span>
38
- </div>
39
-
40
- <!-- Ticket ID -->
41
- <span class="text-sm text-gray-500">Ticket #{{ ticket.uuid|slice:":8" }}</span>
42
- </div>
43
-
44
- <!-- Ticket Subject -->
45
- <h1 class="text-xl font-semibold text-gray-900 truncate pr-4">{{ ticket.subject }}</h1>
46
- </div>
1
+ {% extends 'django_tailwind/app.html' %}
2
+ {% load static %}
47
3
 
48
- <!-- Right: Admin Actions -->
49
- {% if is_staff %}
50
- <div class="flex-shrink-0">
51
- <a href="{% url 'admin:django_cfg_support_ticket_change' ticket.pk %}"
52
- class="inline-flex items-center px-3 py-1.5 border border-gray-300 shadow-sm text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500">
53
- <svg class="w-4 h-4 mr-1.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
54
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"></path>
55
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path>
56
- </svg>
57
- Admin Panel
58
- </a>
59
- </div>
60
- {% endif %}
61
- </div>
4
+ {% block title %}Support Chat - {{ ticket.subject }}{% endblock %}
5
+
6
+ {# Navbar with Support title - full width #}
7
+ {% block header %}
8
+ {% include 'django_tailwind/components/navbar.html' with title="Support Chat" icon='💬' full_width=True %}
9
+ {% endblock %}
10
+
11
+ {% block container_class %}w-full px-0 py-0{% endblock %}
12
+
13
+ {% block content %}
14
+ <!-- Chat Container -->
15
+ <div class="max-w-5xl mx-auto px-4 sm:px-6 lg:px-8 py-6">
16
+ <div class="bg-white dark:bg-gray-800 rounded-xl shadow-lg border border-gray-200 dark:border-gray-700 overflow-hidden flex flex-col" style="height: calc(100vh - 400px); min-height: 500px;">
17
+
18
+ <!-- Messages Area -->
19
+ <div id="messages-container" class="flex-1 overflow-y-auto p-6 space-y-4 bg-gray-50 dark:bg-gray-900">
20
+ {% for message in messages %}
21
+ <div class="flex {% if message.sender == user %}justify-end{% else %}justify-start{% endif %} animate-fade-in">
22
+ <div class="flex {% if message.sender == user %}flex-row-reverse{% else %}flex-row{% endif %} items-end space-x-2 {% if message.sender == user %}space-x-reverse{% endif %} max-w-xl">
62
23
 
63
- <!-- User Info Row -->
64
- <div class="flex items-center justify-between pt-3 border-t border-gray-100">
65
- <!-- Customer Info -->
66
- <div class="flex items-center space-x-3">
67
24
  <!-- Avatar -->
68
25
  <div class="flex-shrink-0">
69
- {% if ticket.user.avatar %}
70
- <img src="{{ ticket.user.avatar.url }}"
71
- alt="{{ ticket.user.get_full_name }}"
26
+ {% if message.sender.avatar %}
27
+ <img src="{{ message.sender.avatar.url }}"
28
+ alt="{{ message.sender.get_full_name }}"
72
29
  class="w-8 h-8 rounded-full object-cover">
73
30
  {% else %}
74
- <div class="w-8 h-8 rounded-full bg-gray-400 flex items-center justify-center text-white text-sm font-medium">
75
- {{ ticket.user.get_full_name|default:ticket.user.username|slice:":2"|upper }}
31
+ <div class="w-8 h-8 rounded-full {% if message.sender == user %}bg-gradient-to-br from-blue-500 to-blue-600{% else %}bg-gradient-to-br from-gray-500 to-gray-600{% endif %} flex items-center justify-center text-white text-xs font-bold shadow-sm">
32
+ {{ message.sender.get_full_name|default:message.sender.username|slice:":2"|upper }}
76
33
  </div>
77
34
  {% endif %}
78
35
  </div>
79
-
80
- <!-- User Details -->
81
- <div class="flex flex-col">
82
- <div class="flex items-center space-x-2">
83
- <span class="text-sm font-medium text-gray-900">{{ ticket.user.get_full_name|default:ticket.user.username }}</span>
84
- {% if ticket.user.is_staff %}
85
- <span class="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-blue-100 text-blue-800">Staff</span>
36
+
37
+ <!-- Message Bubble -->
38
+ <div class="flex flex-col {% if message.sender == user %}items-end{% else %}items-start{% endif %} space-y-1">
39
+ <div class="px-4 py-3 rounded-2xl shadow-sm {% if message.sender == user %}bg-blue-600 text-white rounded-br-sm{% else %}bg-white dark:bg-gray-800 text-gray-900 dark:text-white border border-gray-200 dark:border-gray-700 rounded-bl-sm{% endif %}">
40
+ <p class="text-sm leading-relaxed whitespace-pre-wrap break-words">{{ message.text }}</p>
41
+ </div>
42
+ <div class="flex items-center space-x-2 text-xs {% if message.sender == user %}text-gray-500 dark:text-gray-400{% else %}text-gray-500 dark:text-gray-400{% endif %} px-1">
43
+ <span class="font-medium">{{ message.sender.get_full_name|default:message.sender.username }}</span>
44
+ <span>•</span>
45
+ <span>{{ message.created_at|date:"M d, H:i" }}</span>
46
+ {% if message.sender.is_staff %}
47
+ <span class="bg-blue-100 dark:bg-blue-900/30 text-blue-700 dark:text-blue-400 px-1.5 py-0.5 rounded text-xs font-medium">Staff</span>
86
48
  {% endif %}
87
49
  </div>
88
- <span class="text-xs text-gray-500">{{ ticket.user.email }}</span>
89
50
  </div>
90
51
  </div>
91
-
92
- <!-- Ticket Meta -->
93
- <div class="flex items-center space-x-4 text-xs text-gray-500">
94
- <span>Created {{ ticket.created_at|date:"M d, Y H:i" }}</span>
95
- {% if ticket.updated_at != ticket.created_at %}
96
- <span>•</span>
97
- <span>Updated {{ ticket.updated_at|date:"M d, Y H:i" }}</span>
98
- {% endif %}
99
- </div>
100
52
  </div>
53
+ {% empty %}
54
+ <div class="text-center py-16">
55
+ <div class="text-6xl mb-4">💬</div>
56
+ <p class="text-lg text-gray-500 dark:text-gray-400 font-medium">No messages yet</p>
57
+ <p class="text-sm text-gray-400 dark:text-gray-500">Start the conversation below!</p>
58
+ </div>
59
+ {% endfor %}
101
60
  </div>
102
- </div>
103
-
104
- <!-- Chat Container -->
105
- <div class="max-w-4xl mx-auto px-4 py-6">
106
- <div class="bg-white rounded-lg shadow-sm border h-[600px] flex flex-col">
107
-
108
- <!-- Messages Area -->
109
- <div id="messages-container" class="flex-1 overflow-y-auto p-6 space-y-4">
110
- {% for message in messages %}
111
- <div class="flex {% if message.sender == user %}justify-end{% else %}justify-start{% endif %} mb-4">
112
- <div class="flex {% if message.sender == user %}flex-row-reverse{% else %}flex-row{% endif %} items-end space-x-2 max-w-xs lg:max-w-md">
113
-
114
- <!-- Avatar -->
115
- <div class="flex-shrink-0">
116
- {% if message.sender.avatar %}
117
- <img src="{{ message.sender.avatar.url }}"
118
- alt="{{ message.sender.get_full_name }}"
119
- class="w-8 h-8 rounded-full object-cover">
120
- {% else %}
121
- <div class="w-8 h-8 rounded-full {% if message.sender == user %}bg-primary-500{% else %}bg-gray-500{% endif %} flex items-center justify-center text-white text-sm font-medium">
122
- {{ message.sender.get_full_name|default:message.sender.username|slice:":2"|upper }}
123
- </div>
124
- {% endif %}
125
- </div>
126
61
 
127
- <!-- Message Bubble -->
128
- <div class="flex flex-col {% if message.sender == user %}items-end{% else %}items-start{% endif %}">
129
- <div class="px-4 py-2 rounded-lg {% if message.sender == user %}bg-primary-500 text-white{% else %}bg-gray-100 text-gray-900{% endif %}">
130
- <p class="text-sm whitespace-pre-wrap">{{ message.text }}</p>
131
- </div>
132
- <div class="flex items-center mt-1 space-x-1 text-xs text-gray-500">
133
- <span>{{ message.sender.get_full_name|default:message.sender.username }}</span>
134
- <span class="text-gray-400">({{ message.sender.email }})</span>
135
- <span>•</span>
136
- <span>{{ message.created_at|date:"M d, H:i" }}</span>
137
- {% if message.sender.is_staff %}
138
- <span class="bg-blue-100 text-blue-800 px-1.5 py-0.5 rounded text-xs font-medium">Staff</span>
139
- {% endif %}
140
- </div>
141
- </div>
142
- </div>
143
- </div>
144
- {% empty %}
145
- <div class="text-center py-12">
146
- <div class="text-gray-400 text-lg mb-2">💬</div>
147
- <p class="text-gray-500">No messages yet. Start the conversation!</p>
62
+ <!-- Message Input -->
63
+ <div class="border-t border-gray-200 dark:border-gray-700 p-4 bg-white dark:bg-gray-800">
64
+ <form id="message-form" class="flex space-x-3">
65
+ <div class="flex-1">
66
+ <textarea id="message-input"
67
+ placeholder="Type your message... (Press Enter to send, Shift+Enter for new line)"
68
+ rows="2"
69
+ class="w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white placeholder-gray-500 dark:placeholder-gray-400 focus:ring-2 focus:ring-blue-500 focus:border-transparent resize-none transition-shadow"
70
+ required></textarea>
148
71
  </div>
149
- {% endfor %}
150
- </div>
151
-
152
- <!-- Message Input -->
153
- <div class="border-t p-4">
154
- <form id="message-form" class="flex space-x-3">
155
- <div class="flex-1">
156
- <textarea id="message-input"
157
- placeholder="Type your message..."
158
- rows="2"
159
- class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary-500 focus:border-transparent resize-none"
160
- required></textarea>
161
- </div>
162
- <button type="submit"
163
- class="px-6 py-2 bg-primary-500 text-white rounded-lg hover:bg-primary-600 focus:ring-2 focus:ring-primary-500 focus:ring-offset-2 transition-colors font-medium">
164
- Send
165
- </button>
166
- </form>
167
- </div>
72
+ <button type="submit"
73
+ class="px-6 py-3 bg-blue-600 hover:bg-blue-700 text-white rounded-lg focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 dark:focus:ring-offset-gray-800 transition-all font-medium shadow-sm hover:shadow-md disabled:opacity-50 disabled:cursor-not-allowed">
74
+ <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
75
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 19l9 2-9-18-9 18 9-2zm0 0v-8"/>
76
+ </svg>
77
+ </button>
78
+ </form>
168
79
  </div>
169
80
  </div>
170
-
171
- <!-- JavaScript -->
172
- <script>
173
- const messageForm = document.getElementById('message-form');
174
- const messageInput = document.getElementById('message-input');
175
- const messagesContainer = document.getElementById('messages-container');
176
-
177
- // Auto-scroll to bottom
178
- function scrollToBottom() {
179
- messagesContainer.scrollTop = messagesContainer.scrollHeight;
81
+ </div>
82
+ {% endblock %}
83
+
84
+ {% block extra_head %}
85
+ {{ block.super }}
86
+ <style>
87
+ @keyframes fade-in {
88
+ from {
89
+ opacity: 0;
90
+ transform: translateY(10px);
180
91
  }
181
-
182
- // Initial scroll
183
- scrollToBottom();
184
-
185
- // Handle form submission
186
- messageForm.addEventListener('submit', async (e) => {
187
- e.preventDefault();
188
-
189
- const text = messageInput.value.trim();
190
- if (!text) return;
191
-
192
- // Disable form
193
- messageInput.disabled = true;
194
- const submitBtn = messageForm.querySelector('button[type="submit"]');
195
- const originalText = submitBtn.textContent;
196
- submitBtn.textContent = 'Sending...';
197
- submitBtn.disabled = true;
198
-
199
- try {
200
- const response = await fetch(`{% url 'cfg_support:send-message-ajax' ticket_uuid=ticket.uuid %}`, {
201
- method: 'POST',
202
- headers: {
203
- 'Content-Type': 'application/json',
204
- 'X-CSRFToken': '{{ csrf_token }}',
205
- },
206
- body: JSON.stringify({ text })
207
- });
208
-
209
- const data = await response.json();
210
-
211
- if (data.success) {
212
- // Clear input
213
- messageInput.value = '';
214
-
215
- // Add message to chat
216
- addMessageToChat(data.message);
217
-
218
- // Scroll to bottom
219
- scrollToBottom();
220
- } else {
221
- alert('Error: ' + data.error);
222
- }
223
- } catch (error) {
224
- console.error('Error sending message:', error);
225
- alert('Failed to send message. Please try again.');
226
- } finally {
227
- // Re-enable form
228
- messageInput.disabled = false;
229
- submitBtn.textContent = originalText;
230
- submitBtn.disabled = false;
231
- messageInput.focus();
92
+ to {
93
+ opacity: 1;
94
+ transform: translateY(0);
95
+ }
96
+ }
97
+
98
+ .animate-fade-in {
99
+ animation: fade-in 0.3s ease-out;
100
+ }
101
+ </style>
102
+ {% endblock %}
103
+
104
+ {% block extra_js %}
105
+ <script>
106
+ const messageForm = document.getElementById('message-form');
107
+ const messageInput = document.getElementById('message-input');
108
+ const messagesContainer = document.getElementById('messages-container');
109
+
110
+ // Auto-scroll to bottom
111
+ function scrollToBottom() {
112
+ messagesContainer.scrollTop = messagesContainer.scrollHeight;
113
+ }
114
+
115
+ // Initial scroll
116
+ scrollToBottom();
117
+
118
+ // Handle form submission
119
+ messageForm.addEventListener('submit', async (e) => {
120
+ e.preventDefault();
121
+
122
+ const text = messageInput.value.trim();
123
+ if (!text) return;
124
+
125
+ // Disable form
126
+ messageInput.disabled = true;
127
+ const submitBtn = messageForm.querySelector('button[type="submit"]');
128
+ submitBtn.disabled = true;
129
+ submitBtn.innerHTML = '<svg class="w-5 h-5 animate-spin" fill="none" stroke="currentColor" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path></svg>';
130
+
131
+ try {
132
+ const response = await fetch(`{% url 'cfg_support:send-message-ajax' ticket_uuid=ticket.uuid %}`, {
133
+ method: 'POST',
134
+ headers: {
135
+ 'Content-Type': 'application/json',
136
+ 'X-CSRFToken': '{{ csrf_token }}',
137
+ },
138
+ body: JSON.stringify({ text })
139
+ });
140
+
141
+ const data = await response.json();
142
+
143
+ if (data.success) {
144
+ // Clear input
145
+ messageInput.value = '';
146
+
147
+ // Add message to chat
148
+ addMessageToChat(data.message);
149
+
150
+ // Scroll to bottom
151
+ setTimeout(scrollToBottom, 100);
152
+ } else {
153
+ alert('Error: ' + data.error);
232
154
  }
233
- });
155
+ } catch (error) {
156
+ console.error('Error sending message:', error);
157
+ alert('Failed to send message. Please try again.');
158
+ } finally {
159
+ // Re-enable form
160
+ messageInput.disabled = false;
161
+ submitBtn.disabled = false;
162
+ submitBtn.innerHTML = '<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 19l9 2-9-18-9 18 9-2zm0 0v-8"/></svg>';
163
+ messageInput.focus();
164
+ }
165
+ });
166
+
167
+ // Add message to chat UI
168
+ function addMessageToChat(message) {
169
+ const isCurrentUser = message.sender.id === {{ user.id }};
170
+ const messageHtml = `
171
+ <div class="flex ${isCurrentUser ? 'justify-end' : 'justify-start'} animate-fade-in">
172
+ <div class="flex ${isCurrentUser ? 'flex-row-reverse' : 'flex-row'} items-end space-x-2 ${isCurrentUser ? 'space-x-reverse' : ''} max-w-xl">
173
+ <!-- Avatar -->
174
+ <div class="flex-shrink-0">
175
+ ${message.sender.avatar ?
176
+ `<img src="${message.sender.avatar}" alt="${message.sender.full_name}" class="w-8 h-8 rounded-full object-cover">` :
177
+ `<div class="w-8 h-8 rounded-full ${isCurrentUser ? 'bg-gradient-to-br from-blue-500 to-blue-600' : 'bg-gradient-to-br from-gray-500 to-gray-600'} flex items-center justify-center text-white text-xs font-bold shadow-sm">
178
+ ${message.sender.initials}
179
+ </div>`
180
+ }
181
+ </div>
234
182
 
235
- // Add message to chat UI
236
- function addMessageToChat(message) {
237
- const isCurrentUser = message.sender.id === {{ user.id }};
238
- const messageHtml = `
239
- <div class="flex ${isCurrentUser ? 'justify-end' : 'justify-start'} mb-4">
240
- <div class="flex ${isCurrentUser ? 'flex-row-reverse' : 'flex-row'} items-end space-x-2 max-w-xs lg:max-w-md">
241
-
242
- <!-- Avatar -->
243
- <div class="flex-shrink-0">
244
- ${message.sender.avatar ?
245
- `<img src="${message.sender.avatar}" alt="${message.sender.full_name}" class="w-8 h-8 rounded-full object-cover">` :
246
- `<div class="w-8 h-8 rounded-full ${isCurrentUser ? 'bg-primary-500' : 'bg-gray-500'} flex items-center justify-center text-white text-sm font-medium">
247
- ${message.sender.initials}
248
- </div>`
249
- }
183
+ <!-- Message Bubble -->
184
+ <div class="flex flex-col ${isCurrentUser ? 'items-end' : 'items-start'} space-y-1">
185
+ <div class="px-4 py-3 rounded-2xl shadow-sm ${isCurrentUser ? 'bg-blue-600 text-white rounded-br-sm' : 'bg-white dark:bg-gray-800 text-gray-900 dark:text-white border border-gray-200 dark:border-gray-700 rounded-bl-sm'}">
186
+ <p class="text-sm leading-relaxed whitespace-pre-wrap break-words">${message.text}</p>
250
187
  </div>
251
-
252
- <!-- Message Bubble -->
253
- <div class="flex flex-col ${isCurrentUser ? 'items-end' : 'items-start'}">
254
- <div class="px-4 py-2 rounded-lg ${isCurrentUser ? 'bg-primary-500 text-white' : 'bg-gray-100 text-gray-900'}">
255
- <p class="text-sm whitespace-pre-wrap">${message.text}</p>
256
- </div>
257
- <div class="flex items-center mt-1 space-x-1 text-xs text-gray-500">
258
- <span>${message.sender.full_name}</span>
259
- <span class="text-gray-400">(${message.sender.email})</span>
260
- <span>•</span>
261
- <span>Just now</span>
262
- ${message.sender.is_staff ? '<span class="bg-blue-100 text-blue-800 px-1.5 py-0.5 rounded text-xs font-medium">Staff</span>' : ''}
263
- </div>
188
+ <div class="flex items-center space-x-2 text-xs text-gray-500 dark:text-gray-400 px-1">
189
+ <span class="font-medium">${message.sender.full_name}</span>
190
+ <span>•</span>
191
+ <span>Just now</span>
192
+ ${message.sender.is_staff ? '<span class="bg-blue-100 dark:bg-blue-900/30 text-blue-700 dark:text-blue-400 px-1.5 py-0.5 rounded text-xs font-medium">Staff</span>' : ''}
264
193
  </div>
265
194
  </div>
266
195
  </div>
267
- `;
268
-
269
- messagesContainer.insertAdjacentHTML('beforeend', messageHtml);
270
- }
196
+ </div>
197
+ `;
271
198
 
272
- // Handle Enter key (Shift+Enter for new line)
273
- messageInput.addEventListener('keydown', (e) => {
274
- if (e.key === 'Enter' && !e.shiftKey) {
275
- e.preventDefault();
276
- messageForm.dispatchEvent(new Event('submit'));
277
- }
278
- });
279
- </script>
280
- </body>
281
- </html>
199
+ messagesContainer.insertAdjacentHTML('beforeend', messageHtml);
200
+ }
201
+
202
+ // Handle Enter key (Shift+Enter for new line)
203
+ messageInput.addEventListener('keydown', (e) => {
204
+ if (e.key === 'Enter' && !e.shiftKey) {
205
+ e.preventDefault();
206
+ messageForm.dispatchEvent(new Event('submit'));
207
+ }
208
+ });
209
+ </script>
210
+ {% endblock %}
@@ -19,7 +19,7 @@ class SupportEmailService:
19
19
  def _get_ticket_url(self, ticket_uuid: str) -> str:
20
20
  """Get ticket URL from configuration."""
21
21
  try:
22
- from django_cfg.core.config import get_current_config
22
+ from django_cfg.core.state import get_current_config
23
23
  config = get_current_config()
24
24
  if config and hasattr(config, 'get_ticket_url'):
25
25
  return config.get_ticket_url(str(ticket_uuid))
@@ -1,117 +1,22 @@
1
- <!DOCTYPE html>
2
- <html lang="en" class="h-full">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>{% block title %}Tasks Dashboard{% endblock %} - Django CFG</title>
7
-
8
- <!-- Tailwind CSS -->
9
- <script src="https://cdn.tailwindcss.com"></script>
10
- <script>
11
- tailwind.config = {
12
- darkMode: 'class',
13
- theme: {
14
- extend: {
15
- colors: {
16
- primary: {
17
- 50: '#eff6ff',
18
- 100: '#dbeafe',
19
- 200: '#bfdbfe',
20
- 300: '#93c5fd',
21
- 400: '#60a5fa',
22
- 500: '#3b82f6',
23
- 600: '#2563eb',
24
- 700: '#1d4ed8',
25
- 800: '#1e40af',
26
- 900: '#1e3a8a',
27
- }
28
- }
29
- }
30
- }
31
- }
32
- </script>
33
-
34
- <!-- Material Icons -->
35
- <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
36
-
37
- <!-- Custom CSS -->
38
- {% load static %}
39
- <link rel="stylesheet" href="{% static 'tasks/css/dashboard.css' %}">
40
-
41
- {% block extra_css %}{% endblock %}
42
- </head>
43
- <body class="h-full bg-gray-50 dark:bg-gray-900">
44
- <!-- Navigation -->
45
- <nav class="bg-white dark:bg-gray-800 shadow-sm border-b border-gray-200 dark:border-gray-700">
46
- <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
47
- <div class="flex justify-between h-16">
48
- <!-- Logo & Title -->
49
- <div class="flex items-center">
50
- <div class="flex-shrink-0 flex items-center">
51
- <span class="material-icons text-2xl text-primary-600 dark:text-primary-400 mr-3">dashboard</span>
52
- <h1 class="text-xl font-semibold text-gray-900 dark:text-white">
53
- {% block page_title %}Tasks Dashboard{% endblock %}
54
- </h1>
55
- </div>
56
- </div>
57
-
58
- <!-- Actions -->
59
- <div class="flex items-center space-x-3">
60
- {% block header_actions %}
61
- <a href="/admin/django_dramatiq/task/"
62
- class="inline-flex items-center px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md text-sm font-medium text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600 transition-colors duration-200">
63
- <span class="material-icons text-sm mr-2">history</span>
64
- Task History
65
- </a>
66
- <a href="/admin/constance/config/"
67
- class="inline-flex items-center px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md text-sm font-medium text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600 transition-colors duration-200">
68
- <span class="material-icons text-sm mr-2">admin_panel_settings</span>
69
- Settings
70
- </a>
71
- <button id="theme-toggle"
72
- class="group inline-flex items-center justify-center px-3 py-2 rounded-md bg-white dark:bg-gray-700 border border-gray-300 dark:border-gray-600 hover:bg-gray-50 dark:hover:bg-gray-600 transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-primary-500 focus:ring-offset-2">
73
- <span class="material-icons text-gray-600 dark:text-yellow-400 group-hover:text-primary-600 dark:group-hover:text-yellow-300 transition-colors duration-200">light_mode</span>
74
- </button>
75
- {% endblock %}
76
- </div>
77
- </div>
78
- </div>
79
- </nav>
1
+ {% extends 'django_tailwind/app.html' %}
2
+ {% load static %}
80
3
 
81
- <!-- Main Content -->
82
- <main class="max-w-7xl mx-auto py-6 px-4 sm:px-6 lg:px-8">
83
- {% block content %}{% endblock %}
84
- </main>
4
+ {% block title %}{% block page_title_text %}Tasks Dashboard{% endblock %} - Django CFG{% endblock %}
85
5
 
86
- <!-- Scripts -->
87
- <script>
88
- // Theme toggle functionality
89
- const themeToggle = document.getElementById('theme-toggle');
90
- const themeIcon = themeToggle?.querySelector('.material-icons');
91
- const html = document.documentElement;
92
-
93
- // Update theme icon
94
- function updateThemeIcon(isDark) {
95
- if (themeIcon) {
96
- themeIcon.textContent = isDark ? 'dark_mode' : 'light_mode';
97
- }
98
- }
99
-
100
- // Check for saved theme or default to light
101
- const currentTheme = localStorage.getItem('theme') || 'light';
102
- const isDark = currentTheme === 'dark';
103
- html.classList.toggle('dark', isDark);
104
- updateThemeIcon(isDark);
105
-
106
- themeToggle?.addEventListener('click', () => {
107
- const wasDark = html.classList.contains('dark');
108
- html.classList.toggle('dark');
109
- const nowDark = html.classList.contains('dark');
110
- localStorage.setItem('theme', nowDark ? 'dark' : 'light');
111
- updateThemeIcon(nowDark);
112
- });
113
- </script>
114
-
115
- {% block extra_js %}{% endblock %}
116
- </body>
117
- </html>
6
+ {# Navbar configuration #}
7
+ {% block header %}
8
+ {% with navbar_items=tasks_nav_items %}
9
+ {% include 'django_tailwind/components/navbar.html' with title=page_title|default:"Tasks Dashboard" icon='<span class="material-icons text-2xl text-primary-600 dark:text-primary-400">dashboard</span>' nav_items=navbar_items %}
10
+ {% endwith %}
11
+ {% endblock %}
12
+
13
+ {% block extra_head %}
14
+ {{ block.super }}
15
+ <!-- Material Icons -->
16
+ <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
17
+
18
+ <!-- Custom CSS -->
19
+ <link rel="stylesheet" href="{% static 'tasks/css/dashboard.css' %}">
20
+
21
+ {% block extra_css %}{% endblock %}
22
+ {% endblock %}
@@ -25,7 +25,7 @@ class TaskSimulator:
25
25
 
26
26
  def __init__(self):
27
27
  """Initialize with Redis connection for real Dramatiq data."""
28
- self.queues = ['critical', 'high', 'default', 'low', 'background', 'payments', 'agents']
28
+ self.queues = ['critical', 'high', 'default', 'low', 'background', 'payments', 'agents', 'knowbase']
29
29
  self._redis_client = None
30
30
  self._setup_redis_connection()
31
31