django-cfg 1.3.7__py3-none-any.whl → 1.3.11__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 (246) hide show
  1. django_cfg/__init__.py +1 -1
  2. django_cfg/apps/accounts/admin/__init__.py +24 -8
  3. django_cfg/apps/accounts/admin/activity_admin.py +146 -0
  4. django_cfg/apps/accounts/admin/filters.py +98 -22
  5. django_cfg/apps/accounts/admin/group_admin.py +86 -0
  6. django_cfg/apps/accounts/admin/inlines.py +42 -13
  7. django_cfg/apps/accounts/admin/otp_admin.py +115 -0
  8. django_cfg/apps/accounts/admin/registration_admin.py +173 -0
  9. django_cfg/apps/accounts/admin/resources.py +123 -19
  10. django_cfg/apps/accounts/admin/twilio_admin.py +327 -0
  11. django_cfg/apps/accounts/admin/user_admin.py +362 -0
  12. django_cfg/apps/agents/admin/__init__.py +17 -4
  13. django_cfg/apps/agents/admin/execution_admin.py +204 -183
  14. django_cfg/apps/agents/admin/registry_admin.py +230 -255
  15. django_cfg/apps/agents/admin/toolsets_admin.py +274 -321
  16. django_cfg/apps/agents/core/__init__.py +1 -1
  17. django_cfg/apps/agents/core/django_agent.py +221 -0
  18. django_cfg/apps/agents/core/exceptions.py +14 -0
  19. django_cfg/apps/agents/core/orchestrator.py +18 -3
  20. django_cfg/apps/knowbase/admin/__init__.py +1 -1
  21. django_cfg/apps/knowbase/admin/archive_admin.py +352 -640
  22. django_cfg/apps/knowbase/admin/chat_admin.py +258 -192
  23. django_cfg/apps/knowbase/admin/document_admin.py +269 -262
  24. django_cfg/apps/knowbase/admin/external_data_admin.py +271 -489
  25. django_cfg/apps/knowbase/config/settings.py +21 -4
  26. django_cfg/apps/knowbase/views/chat_views.py +3 -0
  27. django_cfg/apps/leads/admin/__init__.py +3 -1
  28. django_cfg/apps/leads/admin/leads_admin.py +235 -35
  29. django_cfg/apps/maintenance/admin/__init__.py +2 -2
  30. django_cfg/apps/maintenance/admin/api_key_admin.py +125 -63
  31. django_cfg/apps/maintenance/admin/log_admin.py +143 -61
  32. django_cfg/apps/maintenance/admin/scheduled_admin.py +212 -301
  33. django_cfg/apps/maintenance/admin/site_admin.py +213 -352
  34. django_cfg/apps/newsletter/admin/__init__.py +29 -2
  35. django_cfg/apps/newsletter/admin/newsletter_admin.py +531 -193
  36. django_cfg/apps/payments/admin/__init__.py +18 -27
  37. django_cfg/apps/payments/admin/api_keys_admin.py +179 -546
  38. django_cfg/apps/payments/admin/balance_admin.py +166 -632
  39. django_cfg/apps/payments/admin/currencies_admin.py +235 -607
  40. django_cfg/apps/payments/admin/endpoint_groups_admin.py +127 -0
  41. django_cfg/apps/payments/admin/filters.py +83 -3
  42. django_cfg/apps/payments/admin/networks_admin.py +269 -0
  43. django_cfg/apps/payments/admin/payments_admin.py +183 -460
  44. django_cfg/apps/payments/admin/subscriptions_admin.py +119 -636
  45. django_cfg/apps/payments/admin/tariffs_admin.py +248 -0
  46. django_cfg/apps/payments/admin_interface/serializers/payment_serializers.py +153 -34
  47. django_cfg/apps/payments/admin_interface/templates/payments/components/payment_card.html +121 -0
  48. django_cfg/apps/payments/admin_interface/templates/payments/components/payment_qr_code.html +95 -0
  49. django_cfg/apps/payments/admin_interface/templates/payments/components/progress_bar.html +37 -0
  50. django_cfg/apps/payments/admin_interface/templates/payments/components/provider_stats.html +60 -0
  51. django_cfg/apps/payments/admin_interface/templates/payments/components/status_badge.html +41 -0
  52. django_cfg/apps/payments/admin_interface/templates/payments/components/status_overview.html +83 -0
  53. django_cfg/apps/payments/admin_interface/templates/payments/payment_detail.html +363 -0
  54. django_cfg/apps/payments/admin_interface/templates/payments/payment_form.html +43 -17
  55. django_cfg/apps/payments/admin_interface/views/__init__.py +2 -0
  56. django_cfg/apps/payments/admin_interface/views/api/payments.py +102 -0
  57. django_cfg/apps/payments/admin_interface/views/api/webhook_admin.py +109 -63
  58. django_cfg/apps/payments/admin_interface/views/forms.py +5 -1
  59. django_cfg/apps/payments/config/__init__.py +14 -15
  60. django_cfg/apps/payments/config/django_cfg_integration.py +59 -1
  61. django_cfg/apps/payments/config/helpers.py +8 -13
  62. django_cfg/apps/payments/management/commands/manage_currencies.py +236 -274
  63. django_cfg/apps/payments/management/commands/manage_providers.py +4 -1
  64. django_cfg/apps/payments/middleware/api_access.py +32 -6
  65. django_cfg/apps/payments/migrations/0001_initial.py +33 -46
  66. django_cfg/apps/payments/migrations/0002_rename_payments_un_user_id_7f6e79_idx_payments_un_user_id_8ce187_idx_and_more.py +46 -0
  67. django_cfg/apps/payments/migrations/0003_universalpayment_status_changed_at.py +25 -0
  68. django_cfg/apps/payments/models/balance.py +12 -0
  69. django_cfg/apps/payments/models/currencies.py +106 -32
  70. django_cfg/apps/payments/models/managers/currency_managers.py +65 -0
  71. django_cfg/apps/payments/models/managers/payment_managers.py +142 -25
  72. django_cfg/apps/payments/models/payments.py +94 -0
  73. django_cfg/apps/payments/services/core/base.py +4 -4
  74. django_cfg/apps/payments/services/core/currency_service.py +35 -28
  75. django_cfg/apps/payments/services/core/payment_service.py +266 -39
  76. django_cfg/apps/payments/services/providers/__init__.py +3 -0
  77. django_cfg/apps/payments/services/providers/base.py +303 -41
  78. django_cfg/apps/payments/services/providers/models/__init__.py +42 -0
  79. django_cfg/apps/payments/services/providers/models/base.py +145 -0
  80. django_cfg/apps/payments/services/providers/models/providers.py +87 -0
  81. django_cfg/apps/payments/services/providers/models/universal.py +48 -0
  82. django_cfg/apps/payments/services/providers/nowpayments/__init__.py +31 -0
  83. django_cfg/apps/payments/services/providers/nowpayments/config.py +70 -0
  84. django_cfg/apps/payments/services/providers/nowpayments/models.py +150 -0
  85. django_cfg/apps/payments/services/providers/nowpayments/parsers.py +879 -0
  86. django_cfg/apps/payments/services/providers/nowpayments/provider.py +557 -0
  87. django_cfg/apps/payments/services/providers/nowpayments/sync.py +196 -0
  88. django_cfg/apps/payments/services/providers/registry.py +9 -37
  89. django_cfg/apps/payments/services/providers/sync_service.py +277 -0
  90. django_cfg/apps/payments/services/types/requests.py +19 -7
  91. django_cfg/apps/payments/signals/payment_signals.py +31 -2
  92. django_cfg/apps/payments/static/payments/js/api-client.js +29 -6
  93. django_cfg/apps/payments/static/payments/js/payment-detail.js +167 -0
  94. django_cfg/apps/payments/static/payments/js/payment-form.js +98 -32
  95. django_cfg/apps/payments/tasks/__init__.py +39 -0
  96. django_cfg/apps/payments/tasks/types.py +73 -0
  97. django_cfg/apps/payments/tasks/usage_tracking.py +308 -0
  98. django_cfg/apps/payments/templates/admin/payments/_components/dashboard_header.html +23 -0
  99. django_cfg/apps/payments/templates/admin/payments/_components/stats_card.html +25 -0
  100. django_cfg/apps/payments/templates/admin/payments/_components/stats_grid.html +16 -0
  101. django_cfg/apps/payments/templates/admin/payments/apikey/change_list.html +39 -0
  102. django_cfg/apps/payments/templates/admin/payments/balance/change_list.html +50 -0
  103. django_cfg/apps/payments/templates/admin/payments/currency/change_list.html +40 -0
  104. django_cfg/apps/payments/templates/admin/payments/payment/change_list.html +48 -0
  105. django_cfg/apps/payments/templates/admin/payments/subscription/change_list.html +48 -0
  106. django_cfg/apps/payments/templatetags/payment_tags.py +8 -0
  107. django_cfg/apps/payments/urls.py +3 -2
  108. django_cfg/apps/payments/urls_admin.py +1 -1
  109. django_cfg/apps/payments/views/api/currencies.py +8 -5
  110. django_cfg/apps/payments/views/overview/services.py +2 -2
  111. django_cfg/apps/payments/views/serializers/currencies.py +22 -8
  112. django_cfg/apps/support/admin/__init__.py +10 -1
  113. django_cfg/apps/support/admin/support_admin.py +338 -141
  114. django_cfg/apps/tasks/admin/__init__.py +11 -0
  115. django_cfg/apps/tasks/admin/tasks_admin.py +430 -0
  116. django_cfg/apps/tasks/static/tasks/css/dashboard.css +68 -217
  117. django_cfg/apps/tasks/static/tasks/js/api.js +40 -84
  118. django_cfg/apps/tasks/static/tasks/js/components/DataManager.js +24 -0
  119. django_cfg/apps/tasks/static/tasks/js/components/TabManager.js +85 -0
  120. django_cfg/apps/tasks/static/tasks/js/components/TaskRenderer.js +216 -0
  121. django_cfg/apps/tasks/static/tasks/js/dashboard/main.mjs +245 -0
  122. django_cfg/apps/tasks/static/tasks/js/dashboard/overview.mjs +123 -0
  123. django_cfg/apps/tasks/static/tasks/js/dashboard/queues.mjs +120 -0
  124. django_cfg/apps/tasks/static/tasks/js/dashboard/tasks.mjs +350 -0
  125. django_cfg/apps/tasks/static/tasks/js/dashboard/workers.mjs +169 -0
  126. django_cfg/apps/tasks/tasks/__init__.py +10 -0
  127. django_cfg/apps/tasks/tasks/demo_tasks.py +133 -0
  128. django_cfg/apps/tasks/templates/tasks/components/management_actions.html +42 -45
  129. django_cfg/apps/tasks/templates/tasks/components/{status_cards.html → overview_content.html} +30 -11
  130. django_cfg/apps/tasks/templates/tasks/components/queues_content.html +19 -0
  131. django_cfg/apps/tasks/templates/tasks/components/tab_navigation.html +16 -10
  132. django_cfg/apps/tasks/templates/tasks/components/tasks_content.html +51 -0
  133. django_cfg/apps/tasks/templates/tasks/components/workers_content.html +30 -0
  134. django_cfg/apps/tasks/templates/tasks/layout/base.html +117 -0
  135. django_cfg/apps/tasks/templates/tasks/pages/dashboard.html +82 -0
  136. django_cfg/apps/tasks/templates/tasks/partials/task_row_template.html +40 -0
  137. django_cfg/apps/tasks/templates/tasks/widgets/task_filters.html +37 -0
  138. django_cfg/apps/tasks/templates/tasks/widgets/task_footer.html +41 -0
  139. django_cfg/apps/tasks/templates/tasks/widgets/task_table.html +50 -0
  140. django_cfg/apps/tasks/urls.py +2 -2
  141. django_cfg/apps/tasks/urls_admin.py +2 -2
  142. django_cfg/apps/tasks/utils/__init__.py +1 -0
  143. django_cfg/apps/tasks/utils/simulator.py +356 -0
  144. django_cfg/apps/tasks/views/__init__.py +16 -0
  145. django_cfg/apps/tasks/views/api.py +569 -0
  146. django_cfg/apps/tasks/views/dashboard.py +58 -0
  147. django_cfg/config.py +1 -1
  148. django_cfg/core/config.py +10 -5
  149. django_cfg/core/generation.py +1 -1
  150. django_cfg/core/integration/__init__.py +21 -0
  151. django_cfg/management/commands/__init__.py +13 -1
  152. django_cfg/management/commands/migrate_all.py +9 -3
  153. django_cfg/management/commands/migrator.py +11 -6
  154. django_cfg/management/commands/rundramatiq.py +3 -2
  155. django_cfg/management/commands/rundramatiq_simulator.py +430 -0
  156. django_cfg/middleware/__init__.py +0 -2
  157. django_cfg/models/api_keys.py +115 -0
  158. django_cfg/models/constance.py +0 -11
  159. django_cfg/models/payments.py +137 -3
  160. django_cfg/modules/django_admin/__init__.py +64 -0
  161. django_cfg/modules/django_admin/decorators/__init__.py +13 -0
  162. django_cfg/modules/django_admin/decorators/actions.py +106 -0
  163. django_cfg/modules/django_admin/decorators/display.py +106 -0
  164. django_cfg/modules/django_admin/mixins/__init__.py +14 -0
  165. django_cfg/modules/django_admin/mixins/display_mixin.py +81 -0
  166. django_cfg/modules/django_admin/mixins/optimization_mixin.py +41 -0
  167. django_cfg/modules/django_admin/mixins/standalone_actions_mixin.py +202 -0
  168. django_cfg/modules/django_admin/models/__init__.py +20 -0
  169. django_cfg/modules/django_admin/models/action_models.py +33 -0
  170. django_cfg/modules/django_admin/models/badge_models.py +20 -0
  171. django_cfg/modules/django_admin/models/base.py +26 -0
  172. django_cfg/modules/django_admin/models/display_models.py +31 -0
  173. django_cfg/modules/django_admin/utils/badges.py +159 -0
  174. django_cfg/modules/django_admin/utils/displays.py +247 -0
  175. django_cfg/modules/django_currency/__init__.py +2 -2
  176. django_cfg/modules/django_currency/clients/__init__.py +2 -2
  177. django_cfg/modules/django_currency/clients/hybrid_client.py +587 -0
  178. django_cfg/modules/django_currency/core/converter.py +12 -12
  179. django_cfg/modules/django_currency/database/__init__.py +2 -2
  180. django_cfg/modules/django_currency/database/database_loader.py +93 -42
  181. django_cfg/modules/django_llm/llm/client.py +10 -2
  182. django_cfg/modules/django_tasks.py +54 -21
  183. django_cfg/modules/django_unfold/callbacks/actions.py +1 -1
  184. django_cfg/modules/django_unfold/callbacks/statistics.py +1 -1
  185. django_cfg/modules/django_unfold/dashboard.py +14 -13
  186. django_cfg/modules/django_unfold/models/config.py +1 -1
  187. django_cfg/registry/core.py +7 -9
  188. django_cfg/registry/third_party.py +2 -2
  189. django_cfg/template_archive/django_sample.zip +0 -0
  190. {django_cfg-1.3.7.dist-info → django_cfg-1.3.11.dist-info}/METADATA +2 -1
  191. {django_cfg-1.3.7.dist-info → django_cfg-1.3.11.dist-info}/RECORD +198 -160
  192. django_cfg/apps/accounts/admin/activity.py +0 -96
  193. django_cfg/apps/accounts/admin/group.py +0 -17
  194. django_cfg/apps/accounts/admin/otp.py +0 -59
  195. django_cfg/apps/accounts/admin/registration_source.py +0 -97
  196. django_cfg/apps/accounts/admin/twilio_response.py +0 -227
  197. django_cfg/apps/accounts/admin/user.py +0 -300
  198. django_cfg/apps/agents/core/agent.py +0 -281
  199. django_cfg/apps/payments/admin_interface/old/payments/base.html +0 -175
  200. django_cfg/apps/payments/admin_interface/old/payments/components/dev_tool_card.html +0 -125
  201. django_cfg/apps/payments/admin_interface/old/payments/components/loading_spinner.html +0 -16
  202. django_cfg/apps/payments/admin_interface/old/payments/components/ngrok_status_card.html +0 -113
  203. django_cfg/apps/payments/admin_interface/old/payments/components/notification.html +0 -27
  204. django_cfg/apps/payments/admin_interface/old/payments/components/provider_card.html +0 -86
  205. django_cfg/apps/payments/admin_interface/old/payments/components/status_card.html +0 -35
  206. django_cfg/apps/payments/admin_interface/old/payments/currency_converter.html +0 -382
  207. django_cfg/apps/payments/admin_interface/old/payments/payment_dashboard.html +0 -309
  208. django_cfg/apps/payments/admin_interface/old/payments/payment_form.html +0 -303
  209. django_cfg/apps/payments/admin_interface/old/payments/payment_list.html +0 -382
  210. django_cfg/apps/payments/admin_interface/old/payments/payment_status.html +0 -500
  211. django_cfg/apps/payments/admin_interface/old/payments/webhook_dashboard.html +0 -518
  212. django_cfg/apps/payments/admin_interface/old/static/payments/css/components.css +0 -619
  213. django_cfg/apps/payments/admin_interface/old/static/payments/css/dashboard.css +0 -188
  214. django_cfg/apps/payments/admin_interface/old/static/payments/js/components.js +0 -545
  215. django_cfg/apps/payments/admin_interface/old/static/payments/js/ngrok-status.js +0 -163
  216. django_cfg/apps/payments/admin_interface/old/static/payments/js/utils.js +0 -412
  217. django_cfg/apps/payments/config/constance/__init__.py +0 -22
  218. django_cfg/apps/payments/config/constance/config_service.py +0 -123
  219. django_cfg/apps/payments/config/constance/fields.py +0 -69
  220. django_cfg/apps/payments/config/constance/settings.py +0 -160
  221. django_cfg/apps/payments/services/providers/nowpayments.py +0 -478
  222. django_cfg/apps/tasks/admin.py +0 -320
  223. django_cfg/apps/tasks/static/tasks/js/dashboard.js +0 -614
  224. django_cfg/apps/tasks/static/tasks/js/modals.js +0 -452
  225. django_cfg/apps/tasks/static/tasks/js/notifications.js +0 -144
  226. django_cfg/apps/tasks/static/tasks/js/task-monitor.js +0 -454
  227. django_cfg/apps/tasks/static/tasks/js/theme.js +0 -77
  228. django_cfg/apps/tasks/templates/tasks/base.html +0 -96
  229. django_cfg/apps/tasks/templates/tasks/components/info_cards.html +0 -85
  230. django_cfg/apps/tasks/templates/tasks/components/overview_tab.html +0 -22
  231. django_cfg/apps/tasks/templates/tasks/components/queues_tab.html +0 -19
  232. django_cfg/apps/tasks/templates/tasks/components/task_details_modal.html +0 -103
  233. django_cfg/apps/tasks/templates/tasks/components/tasks_tab.html +0 -32
  234. django_cfg/apps/tasks/templates/tasks/components/workers_tab.html +0 -29
  235. django_cfg/apps/tasks/templates/tasks/dashboard.html +0 -29
  236. django_cfg/apps/tasks/views.py +0 -461
  237. django_cfg/management/commands/auto_generate.py +0 -486
  238. django_cfg/middleware/static_nocache.py +0 -55
  239. django_cfg/modules/django_currency/clients/yahoo_client.py +0 -157
  240. /django_cfg/modules/{django_unfold → django_admin}/icons/README.md +0 -0
  241. /django_cfg/modules/{django_unfold → django_admin}/icons/__init__.py +0 -0
  242. /django_cfg/modules/{django_unfold → django_admin}/icons/constants.py +0 -0
  243. /django_cfg/modules/{django_unfold → django_admin}/icons/generate_icons.py +0 -0
  244. {django_cfg-1.3.7.dist-info → django_cfg-1.3.11.dist-info}/WHEEL +0 -0
  245. {django_cfg-1.3.7.dist-info → django_cfg-1.3.11.dist-info}/entry_points.txt +0 -0
  246. {django_cfg-1.3.7.dist-info → django_cfg-1.3.11.dist-info}/licenses/LICENSE +0 -0
@@ -1,16 +1,29 @@
1
1
  """
2
- Django admin interfaces for Django Orchestrator.
2
+ Agents admin interfaces using Django Admin Utilities.
3
+
4
+ Modern, clean admin interfaces with Material Icons and consistent styling.
3
5
  """
4
6
 
5
- from .registry_admin import AgentDefinitionAdmin, AgentTemplateAdmin
7
+ from django.contrib import admin
8
+
9
+ # Import all admin classes
6
10
  from .execution_admin import AgentExecutionAdmin, WorkflowExecutionAdmin
11
+ from .registry_admin import AgentDefinitionAdmin, AgentTemplateAdmin
7
12
  from .toolsets_admin import ToolExecutionAdmin, ApprovalLogAdmin, ToolsetConfigurationAdmin
8
13
 
14
+ # All models are registered in their respective admin files using @admin.register
15
+ # This provides:
16
+ # - Clean separation of concerns
17
+ # - Material Icons integration
18
+ # - Type-safe configurations
19
+ # - Performance optimizations
20
+ # - Consistent styling with django_admin module
21
+
9
22
  __all__ = [
10
- 'AgentDefinitionAdmin',
11
- 'AgentTemplateAdmin',
12
23
  'AgentExecutionAdmin',
13
24
  'WorkflowExecutionAdmin',
25
+ 'AgentDefinitionAdmin',
26
+ 'AgentTemplateAdmin',
14
27
  'ToolExecutionAdmin',
15
28
  'ApprovalLogAdmin',
16
29
  'ToolsetConfigurationAdmin',
@@ -1,9 +1,10 @@
1
1
  """
2
- Execution admin interfaces with Unfold optimization.
2
+ Execution admin interfaces using Django Admin Utilities.
3
+
4
+ Enhanced execution management with Material Icons and optimized queries.
3
5
  """
4
6
 
5
7
  from django.contrib import admin, messages
6
- from django.utils.html import format_html
7
8
  from django.urls import reverse
8
9
  from django.utils.safestring import mark_safe
9
10
  from django.db import models
@@ -13,21 +14,32 @@ from django.db.models.fields.json import JSONField
13
14
  from datetime import timedelta
14
15
  from django_json_widget.widgets import JSONEditorWidget
15
16
  from unfold.admin import ModelAdmin, TabularInline
16
- from unfold.decorators import display, action
17
- from unfold.enums import ActionVariant
18
17
  from unfold.contrib.filters.admin import AutocompleteSelectFilter, AutocompleteSelectMultipleFilter
19
18
  from unfold.contrib.forms.widgets import WysiwygWidget
20
19
  from django_cfg import ExportMixin, ExportForm
21
20
 
21
+ from django_cfg.modules.django_admin import (
22
+ OptimizedModelAdmin,
23
+ DisplayMixin,
24
+ MoneyDisplayConfig,
25
+ StatusBadgeConfig,
26
+ DateTimeDisplayConfig,
27
+ Icons,
28
+ ActionVariant,
29
+ display,
30
+ action
31
+ )
32
+ from django_cfg.modules.django_admin.utils.badges import StatusBadge
33
+
22
34
  from ..models.execution import AgentExecution, WorkflowExecution
23
35
 
24
36
 
25
37
  class AgentExecutionInlineForWorkflow(TabularInline):
26
- """Inline for agent executions within workflow with Unfold styling."""
38
+ """Enhanced inline for agent executions within workflow."""
27
39
 
28
40
  model = AgentExecution
29
41
  verbose_name = "Agent Execution"
30
- verbose_name_plural = "🔗 Workflow Steps (Read-only)"
42
+ verbose_name_plural = "🔗 Workflow Steps"
31
43
  extra = 0
32
44
  max_num = 0
33
45
  can_delete = False
@@ -58,32 +70,33 @@ class AgentExecutionInlineForWorkflow(TabularInline):
58
70
  @display(description="Status")
59
71
  def status_badge_inline(self, obj):
60
72
  """Status badge for inline display."""
61
- colors = {
62
- 'pending': 'bg-yellow-100 text-yellow-800',
63
- 'running': 'bg-blue-100 text-blue-800',
64
- 'completed': 'bg-green-100 text-green-800',
65
- 'failed': 'bg-red-100 text-red-800',
66
- 'cancelled': 'bg-gray-100 text-gray-800'
67
- }
68
- color_class = colors.get(obj.status, 'bg-gray-100 text-gray-800')
69
- return format_html(
70
- '<span class="inline-flex items-center px-2 py-1 rounded-full text-xs font-medium {}">{}</span>',
71
- color_class, obj.get_status_display()
73
+ status_config = StatusBadgeConfig(
74
+ custom_mappings={
75
+ 'pending': 'warning',
76
+ 'running': 'info',
77
+ 'completed': 'success',
78
+ 'failed': 'danger',
79
+ 'cancelled': 'secondary'
80
+ },
81
+ show_icons=True,
82
+ icon=Icons.PLAY_ARROW
72
83
  )
84
+ return self.display_status_auto(obj, 'status', status_config)
73
85
 
74
86
  @display(description="Execution Time")
75
87
  def execution_time_display(self, obj):
76
88
  """Execution time display for inline."""
77
89
  if obj.execution_time:
78
90
  return f"{obj.execution_time:.2f}s"
79
- return "-"
91
+ return ""
80
92
 
81
93
  @display(description="Cost")
82
94
  def cost_display_inline(self, obj):
83
95
  """Cost display for inline."""
84
96
  if obj.cost:
85
- return f"${obj.cost:.4f}"
86
- return "-"
97
+ config = MoneyDisplayConfig(currency="USD", show_sign=False)
98
+ return self.display_money_amount(obj, 'cost', config)
99
+ return "—"
87
100
 
88
101
  def get_queryset(self, request):
89
102
  """Optimize queryset for inline display."""
@@ -91,29 +104,33 @@ class AgentExecutionInlineForWorkflow(TabularInline):
91
104
 
92
105
 
93
106
  @admin.register(AgentExecution)
94
- class AgentExecutionAdmin(ModelAdmin, ExportMixin):
95
- """Admin interface for AgentExecution with Unfold styling."""
107
+ class AgentExecutionAdmin(OptimizedModelAdmin, DisplayMixin, ModelAdmin, ExportMixin):
108
+ """Enhanced admin for AgentExecution model using Django Admin Utilities."""
109
+
110
+ # Performance optimization
111
+ select_related_fields = ['user', 'workflow_execution', 'agent_definition']
96
112
 
97
113
  # Export-only configuration
98
114
  export_form_class = ExportForm
99
115
 
100
116
  list_display = [
101
- 'id_display', 'agent_name_display', 'status_badge', 'user',
102
- 'execution_metrics', 'cost_display', 'cached_badge', 'created_at'
117
+ 'id_display', 'agent_name_display', 'status_display', 'user_display',
118
+ 'execution_time_display', 'tokens_display', 'cost_display', 'cached_display', 'created_at_display'
103
119
  ]
104
- ordering = ['-created_at']
120
+ list_display_links = ['id_display', 'agent_name_display']
105
121
  list_filter = [
106
122
  'status', 'cached', 'agent_name', 'created_at',
107
123
  ('user', AutocompleteSelectFilter),
108
124
  ('workflow_execution', AutocompleteSelectFilter)
109
125
  ]
110
126
  search_fields = ['agent_name', 'user__username', 'input_prompt', 'output_data']
111
- autocomplete_fields = ['user', 'workflow_execution']
127
+ autocomplete_fields = ['user', 'workflow_execution', 'agent_definition']
112
128
  readonly_fields = [
113
129
  'id', 'execution_time', 'tokens_used', 'cost', 'cached',
114
130
  'created_at', 'started_at', 'completed_at', 'duration_display',
115
131
  'input_preview', 'output_preview', 'error_preview'
116
132
  ]
133
+ ordering = ['-created_at']
117
134
 
118
135
  # Unfold form field overrides
119
136
  formfield_overrides = {
@@ -123,7 +140,7 @@ class AgentExecutionAdmin(ModelAdmin, ExportMixin):
123
140
 
124
141
  fieldsets = (
125
142
  ("🚀 Execution Info", {
126
- 'fields': ('id', 'agent_name', 'user', 'status'),
143
+ 'fields': ('id', 'agent_name', 'agent_definition', 'user', 'status'),
127
144
  'classes': ('tab',)
128
145
  }),
129
146
  ("📝 Input/Output", {
@@ -149,134 +166,139 @@ class AgentExecutionAdmin(ModelAdmin, ExportMixin):
149
166
  @display(description="ID")
150
167
  def id_display(self, obj):
151
168
  """Enhanced ID display."""
152
- return format_html(
153
- '<span class="font-mono text-sm text-gray-600">#{}</span>',
154
- str(obj.id)[:8]
169
+ config = StatusBadgeConfig(show_icons=True, icon=Icons.TAG)
170
+ return StatusBadge.create(
171
+ text=f"#{str(obj.id)[:8]}",
172
+ variant="secondary",
173
+ config=config
155
174
  )
156
175
 
157
176
  @display(description="Agent")
158
177
  def agent_name_display(self, obj):
159
178
  """Enhanced agent name display."""
160
- return format_html(
161
- '<div class="flex items-center space-x-2">'
162
- '<span class="text-blue-600 font-medium">{}</span>'
163
- '</div>',
164
- obj.agent_name
179
+ config = StatusBadgeConfig(show_icons=True, icon=Icons.SMART_TOY)
180
+ return StatusBadge.create(
181
+ text=obj.agent_name,
182
+ variant="primary",
183
+ config=config
165
184
  )
166
185
 
167
186
  @display(description="Status")
168
- def status_badge(self, obj):
169
- """Status badge with color coding."""
170
- colors = {
171
- 'pending': 'bg-yellow-100 text-yellow-800',
172
- 'running': 'bg-blue-100 text-blue-800',
173
- 'completed': 'bg-green-100 text-green-800',
174
- 'failed': 'bg-red-100 text-red-800',
175
- 'cancelled': 'bg-gray-100 text-gray-800'
176
- }
177
- color_class = colors.get(obj.status, 'bg-gray-100 text-gray-800')
178
- return format_html(
179
- '<span class="inline-flex items-center px-2 py-1 rounded-full text-xs font-medium {}">{}</span>',
180
- color_class, obj.get_status_display()
187
+ def status_display(self, obj):
188
+ """Status display with appropriate icons."""
189
+ status_config = StatusBadgeConfig(
190
+ custom_mappings={
191
+ 'pending': 'warning',
192
+ 'running': 'info',
193
+ 'completed': 'success',
194
+ 'failed': 'danger',
195
+ 'cancelled': 'secondary'
196
+ },
197
+ show_icons=True,
198
+ icon=Icons.PLAY_ARROW if obj.status == 'running' else Icons.CHECK_CIRCLE if obj.status == 'completed' else Icons.ERROR if obj.status == 'failed' else Icons.SCHEDULE
181
199
  )
200
+ return self.display_status_auto(obj, 'status', status_config)
182
201
 
183
- @display(description="Metrics")
184
- def execution_metrics(self, obj):
185
- """Combined execution metrics."""
186
- return format_html(
187
- '<div class="text-sm space-y-1">'
188
- '<div><span class="font-medium">Time:</span> {}</div>'
189
- '<div><span class="font-medium">Tokens:</span> {}</div>'
190
- '</div>',
191
- f"{obj.execution_time:.2f}s" if obj.execution_time else "-",
192
- f"{obj.tokens_used:,}" if obj.tokens_used else "-"
193
- )
202
+ @display(description="User")
203
+ def user_display(self, obj):
204
+ """User display with avatar."""
205
+ if not obj.user:
206
+ return ""
207
+ return self.display_user_simple(obj.user)
208
+
209
+ @display(description="Time")
210
+ def execution_time_display(self, obj):
211
+ """Execution time display."""
212
+ if obj.execution_time:
213
+ return f"{obj.execution_time:.2f}s"
214
+ return "—"
215
+
216
+ @display(description="Tokens")
217
+ def tokens_display(self, obj):
218
+ """Tokens display."""
219
+ if obj.tokens_used:
220
+ return f"{obj.tokens_used:,}"
221
+ return "—"
194
222
 
195
223
  @display(description="Cost")
196
224
  def cost_display(self, obj):
197
225
  """Cost display with formatting."""
198
226
  if obj.cost:
199
- return format_html(
200
- '<span class="font-mono text-green-600">${:.4f}</span>',
201
- obj.cost
227
+ config = MoneyDisplayConfig(
228
+ currency="USD",
229
+ show_sign=False,
230
+ smart_decimal_places=True
202
231
  )
203
- return "-"
232
+ return self.display_money_amount(obj, 'cost', config)
233
+ return "—"
204
234
 
205
235
  @display(description="Cached", boolean=True)
206
- def cached_badge(self, obj):
207
- """Cached status badge."""
236
+ def cached_display(self, obj):
237
+ """Cached status display."""
208
238
  return obj.cached
209
239
 
240
+ @display(description="Created")
241
+ def created_at_display(self, obj):
242
+ """Created time with relative display."""
243
+ config = DateTimeDisplayConfig(show_relative=True)
244
+ return self.display_datetime_relative(obj, 'created_at', config)
245
+
210
246
  @display(description="Duration")
211
247
  def duration_display(self, obj):
212
248
  """Display execution duration."""
213
249
  if obj.duration:
214
250
  return f"{obj.duration:.2f}s"
215
- return "-"
251
+ return ""
216
252
 
217
253
  @display(description="Input Preview")
218
254
  def input_preview(self, obj):
219
255
  """Preview of input prompt."""
220
256
  if not obj.input_prompt:
221
- return "-"
222
- preview = obj.input_prompt[:200] + "..." if len(obj.input_prompt) > 200 else obj.input_prompt
223
- return format_html(
224
- '<div class="text-sm text-gray-600 max-w-md">{}</div>',
225
- preview
226
- )
257
+ return ""
258
+ return obj.input_prompt[:200] + "..." if len(obj.input_prompt) > 200 else obj.input_prompt
227
259
 
228
260
  @display(description="Output Preview")
229
261
  def output_preview(self, obj):
230
262
  """Preview of output data."""
231
263
  if not obj.output_data:
232
- return "-"
233
- preview = str(obj.output_data)[:200] + "..." if len(str(obj.output_data)) > 200 else str(obj.output_data)
234
- return format_html(
235
- '<div class="text-sm text-gray-600 max-w-md">{}</div>',
236
- preview
237
- )
264
+ return ""
265
+ return str(obj.output_data)[:200] + "..." if len(str(obj.output_data)) > 200 else str(obj.output_data)
238
266
 
239
267
  @display(description="Error Preview")
240
268
  def error_preview(self, obj):
241
269
  """Preview of error message."""
242
270
  if not obj.error_message:
243
- return "-"
244
- preview = obj.error_message[:200] + "..." if len(obj.error_message) > 200 else obj.error_message
245
- return format_html(
246
- '<div class="text-sm text-red-600 max-w-md">{}</div>',
247
- preview
248
- )
271
+ return ""
272
+ return obj.error_message[:200] + "..." if len(obj.error_message) > 200 else obj.error_message
249
273
 
250
- @action(description="Retry failed executions", icon="refresh", variant=ActionVariant.WARNING)
274
+ @action(description="Retry failed executions", variant=ActionVariant.WARNING)
251
275
  def retry_failed_executions(self, request, queryset):
252
276
  """Retry failed executions."""
253
277
  failed_count = queryset.filter(status='failed').count()
254
278
  messages.warning(request, f"Retry functionality not implemented yet. {failed_count} failed executions selected.")
255
279
 
256
- @action(description="Clear cache", icon="clear", variant=ActionVariant.INFO)
280
+ @action(description="Clear cache", variant=ActionVariant.INFO)
257
281
  def clear_cache(self, request, queryset):
258
282
  """Clear cache for selected executions."""
259
283
  cached_count = queryset.filter(cached=True).count()
260
284
  messages.info(request, f"Cache clearing not implemented yet. {cached_count} cached executions selected.")
261
-
262
- def get_queryset(self, request):
263
- """Optimize queryset."""
264
- return super().get_queryset(request).select_related('user', 'workflow_execution')
265
285
 
266
286
 
267
287
  @admin.register(WorkflowExecution)
268
- class WorkflowExecutionAdmin(ModelAdmin, ExportMixin):
269
- """Admin interface for WorkflowExecution with Unfold styling."""
288
+ class WorkflowExecutionAdmin(OptimizedModelAdmin, DisplayMixin, ModelAdmin, ExportMixin):
289
+ """Enhanced admin for WorkflowExecution model using Django Admin Utilities."""
290
+
291
+ # Performance optimization
292
+ select_related_fields = ['user']
270
293
 
271
294
  # Export-only configuration
272
295
  export_form_class = ExportForm
273
296
 
274
297
  list_display = [
275
- 'id_display', 'name_display', 'pattern_badge', 'status_badge', 'user',
276
- 'progress_display', 'metrics_display', 'cost_display', 'created_at'
298
+ 'id_display', 'name_display', 'pattern_display', 'status_display', 'user_display',
299
+ 'progress_display', 'total_time_display', 'total_tokens_display', 'cost_display', 'created_at_display'
277
300
  ]
278
- ordering = ['-created_at']
279
- inlines = [AgentExecutionInlineForWorkflow]
301
+ list_display_links = ['id_display', 'name_display']
280
302
  list_filter = [
281
303
  'status', 'pattern', 'created_at',
282
304
  ('user', AutocompleteSelectFilter)
@@ -288,6 +310,8 @@ class WorkflowExecutionAdmin(ModelAdmin, ExportMixin):
288
310
  'created_at', 'started_at', 'completed_at', 'duration_display',
289
311
  'progress_percentage', 'input_preview', 'output_preview', 'error_preview'
290
312
  ]
313
+ ordering = ['-created_at']
314
+ inlines = [AgentExecutionInlineForWorkflow]
291
315
 
292
316
  # Unfold form field overrides
293
317
  formfield_overrides = {
@@ -327,141 +351,138 @@ class WorkflowExecutionAdmin(ModelAdmin, ExportMixin):
327
351
  @display(description="ID")
328
352
  def id_display(self, obj):
329
353
  """Enhanced ID display."""
330
- return format_html(
331
- '<span class="font-mono text-sm text-gray-600">#{}</span>',
332
- str(obj.id)[:8]
354
+ config = StatusBadgeConfig(show_icons=True, icon=Icons.TAG)
355
+ return StatusBadge.create(
356
+ text=f"#{str(obj.id)[:8]}",
357
+ variant="secondary",
358
+ config=config
333
359
  )
334
360
 
335
361
  @display(description="Workflow")
336
362
  def name_display(self, obj):
337
363
  """Enhanced workflow name display."""
338
- return format_html(
339
- '<div class="flex items-center space-x-2">'
340
- '<span class="text-indigo-600 font-medium">{}</span>'
341
- '</div>',
342
- obj.name
364
+ config = StatusBadgeConfig(show_icons=True, icon=Icons.ACCOUNT_TREE)
365
+ return StatusBadge.create(
366
+ text=obj.name,
367
+ variant="primary",
368
+ config=config
343
369
  )
344
370
 
345
371
  @display(description="Pattern")
346
- def pattern_badge(self, obj):
347
- """Pattern badge."""
348
- colors = {
349
- 'sequential': 'bg-blue-100 text-blue-800',
350
- 'parallel': 'bg-green-100 text-green-800',
351
- 'conditional': 'bg-purple-100 text-purple-800',
352
- 'loop': 'bg-orange-100 text-orange-800'
353
- }
354
- color_class = colors.get(obj.pattern, 'bg-gray-100 text-gray-800')
355
- return format_html(
356
- '<span class="inline-flex items-center px-2 py-1 rounded-full text-xs font-medium {}">{}</span>',
357
- color_class, obj.pattern.title() if obj.pattern else 'Unknown'
372
+ def pattern_display(self, obj):
373
+ """Pattern display with appropriate icons."""
374
+ pattern_config = StatusBadgeConfig(
375
+ custom_mappings={
376
+ 'sequential': 'info',
377
+ 'parallel': 'success',
378
+ 'conditional': 'warning',
379
+ 'loop': 'secondary'
380
+ },
381
+ show_icons=True,
382
+ icon=Icons.LINEAR_SCALE if obj.pattern == 'sequential' else Icons.CALL_SPLIT if obj.pattern == 'parallel' else Icons.DEVICE_HUB if obj.pattern == 'conditional' else Icons.LOOP
383
+ )
384
+ return self.display_status_auto(
385
+ type('obj', (), {'pattern': obj.pattern.title() if obj.pattern else 'Unknown'})(),
386
+ 'pattern',
387
+ pattern_config
358
388
  )
359
389
 
360
390
  @display(description="Status")
361
- def status_badge(self, obj):
362
- """Status badge with color coding."""
363
- colors = {
364
- 'pending': 'bg-yellow-100 text-yellow-800',
365
- 'running': 'bg-blue-100 text-blue-800',
366
- 'completed': 'bg-green-100 text-green-800',
367
- 'failed': 'bg-red-100 text-red-800',
368
- 'cancelled': 'bg-gray-100 text-gray-800'
369
- }
370
- color_class = colors.get(obj.status, 'bg-gray-100 text-gray-800')
371
- return format_html(
372
- '<span class="inline-flex items-center px-2 py-1 rounded-full text-xs font-medium {}">{}</span>',
373
- color_class, obj.get_status_display()
391
+ def status_display(self, obj):
392
+ """Status display with appropriate icons."""
393
+ status_config = StatusBadgeConfig(
394
+ custom_mappings={
395
+ 'pending': 'warning',
396
+ 'running': 'info',
397
+ 'completed': 'success',
398
+ 'failed': 'danger',
399
+ 'cancelled': 'secondary'
400
+ },
401
+ show_icons=True,
402
+ icon=Icons.PLAY_ARROW if obj.status == 'running' else Icons.CHECK_CIRCLE if obj.status == 'completed' else Icons.ERROR if obj.status == 'failed' else Icons.SCHEDULE
374
403
  )
404
+ return self.display_status_auto(obj, 'status', status_config)
405
+
406
+ @display(description="User")
407
+ def user_display(self, obj):
408
+ """User display with avatar."""
409
+ if not obj.user:
410
+ return "—"
411
+ return self.display_user_simple(obj.user)
375
412
 
376
413
  @display(description="Progress")
377
414
  def progress_display(self, obj):
378
- """Display progress as a progress bar."""
379
- percentage = obj.progress_percentage
380
- color_class = 'bg-green-500' if obj.status == 'completed' else 'bg-blue-500' if obj.status == 'running' else 'bg-red-500'
381
-
382
- return format_html(
383
- '<div class="w-24 bg-gray-200 rounded-full h-2">'
384
- '<div class="h-2 rounded-full {} flex items-center justify-center text-xs text-white" style="width: {}%;">'
385
- '</div>'
386
- '</div>'
387
- '<div class="text-xs text-gray-600 mt-1">{}%</div>',
388
- color_class, percentage, int(percentage)
389
- )
390
-
391
- @display(description="Metrics")
392
- def metrics_display(self, obj):
393
- """Combined metrics display."""
394
- return format_html(
395
- '<div class="text-sm space-y-1">'
396
- '<div><span class="font-medium">Time:</span> {}</div>'
397
- '<div><span class="font-medium">Tokens:</span> {}</div>'
398
- '</div>',
399
- f"{obj.total_execution_time:.2f}s" if obj.total_execution_time else "-",
400
- f"{obj.total_tokens_used:,}" if obj.total_tokens_used else "-"
401
- )
415
+ """Display progress percentage."""
416
+ return f"{int(obj.progress_percentage)}%"
417
+
418
+ @display(description="Time")
419
+ def total_time_display(self, obj):
420
+ """Total execution time display."""
421
+ if obj.total_execution_time:
422
+ return f"{obj.total_execution_time:.2f}s"
423
+ return "—"
424
+
425
+ @display(description="Tokens")
426
+ def total_tokens_display(self, obj):
427
+ """Total tokens display."""
428
+ if obj.total_tokens_used:
429
+ return f"{obj.total_tokens_used:,}"
430
+ return ""
402
431
 
403
432
  @display(description="Cost")
404
433
  def cost_display(self, obj):
405
434
  """Cost display with formatting."""
406
435
  if obj.total_cost:
407
- return format_html(
408
- '<span class="font-mono text-green-600">${:.4f}</span>',
409
- obj.total_cost
436
+ config = MoneyDisplayConfig(
437
+ currency="USD",
438
+ show_sign=False,
439
+ smart_decimal_places=True
410
440
  )
411
- return "-"
441
+ return self.display_money_amount(obj, 'total_cost', config)
442
+ return "—"
443
+
444
+ @display(description="Created")
445
+ def created_at_display(self, obj):
446
+ """Created time with relative display."""
447
+ config = DateTimeDisplayConfig(show_relative=True)
448
+ return self.display_datetime_relative(obj, 'created_at', config)
412
449
 
413
450
  @display(description="Duration")
414
451
  def duration_display(self, obj):
415
452
  """Display workflow duration."""
416
453
  if obj.duration:
417
454
  return f"{obj.duration:.2f}s"
418
- return "-"
455
+ return ""
419
456
 
420
457
  @display(description="Input Preview")
421
458
  def input_preview(self, obj):
422
459
  """Preview of input prompt."""
423
460
  if not obj.input_prompt:
424
- return "-"
425
- preview = obj.input_prompt[:200] + "..." if len(obj.input_prompt) > 200 else obj.input_prompt
426
- return format_html(
427
- '<div class="text-sm text-gray-600 max-w-md">{}</div>',
428
- preview
429
- )
461
+ return ""
462
+ return obj.input_prompt[:200] + "..." if len(obj.input_prompt) > 200 else obj.input_prompt
430
463
 
431
464
  @display(description="Output Preview")
432
465
  def output_preview(self, obj):
433
466
  """Preview of final output."""
434
467
  if not obj.final_output:
435
- return "-"
436
- preview = str(obj.final_output)[:200] + "..." if len(str(obj.final_output)) > 200 else str(obj.final_output)
437
- return format_html(
438
- '<div class="text-sm text-gray-600 max-w-md">{}</div>',
439
- preview
440
- )
468
+ return ""
469
+ return str(obj.final_output)[:200] + "..." if len(str(obj.final_output)) > 200 else str(obj.final_output)
441
470
 
442
471
  @display(description="Error Preview")
443
472
  def error_preview(self, obj):
444
473
  """Preview of error message."""
445
474
  if not obj.error_message:
446
- return "-"
447
- preview = obj.error_message[:200] + "..." if len(obj.error_message) > 200 else obj.error_message
448
- return format_html(
449
- '<div class="text-sm text-red-600 max-w-md">{}</div>',
450
- preview
451
- )
475
+ return ""
476
+ return obj.error_message[:200] + "..." if len(obj.error_message) > 200 else obj.error_message
452
477
 
453
- @action(description="Cancel running workflows", icon="stop", variant=ActionVariant.DANGER)
478
+ @action(description="Cancel running workflows", variant=ActionVariant.DANGER)
454
479
  def cancel_running_workflows(self, request, queryset):
455
480
  """Cancel running workflows."""
456
481
  running_count = queryset.filter(status='running').count()
457
482
  messages.warning(request, f"Cancel functionality not implemented yet. {running_count} running workflows selected.")
458
483
 
459
- @action(description="Retry failed workflows", icon="refresh", variant=ActionVariant.WARNING)
484
+ @action(description="Retry failed workflows", variant=ActionVariant.WARNING)
460
485
  def retry_failed_workflows(self, request, queryset):
461
486
  """Retry failed workflows."""
462
487
  failed_count = queryset.filter(status='failed').count()
463
- messages.warning(request, f"Retry functionality not implemented yet. {failed_count} failed workflows selected.")
464
-
465
- def get_queryset(self, request):
466
- """Optimize queryset."""
467
- return super().get_queryset(request).select_related('user')
488
+ messages.warning(request, f"Retry functionality not implemented yet. {failed_count} failed workflows selected.")