django-cfg 1.4.62__py3-none-any.whl → 1.4.64__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.

Potentially problematic release.


This version of django-cfg might be problematic. Click here for more details.

Files changed (181) hide show
  1. django_cfg/__init__.py +1 -1
  2. django_cfg/apps/accounts/services/otp_service.py +3 -14
  3. django_cfg/apps/centrifugo/__init__.py +57 -0
  4. django_cfg/apps/centrifugo/admin/__init__.py +13 -0
  5. django_cfg/apps/centrifugo/admin/centrifugo_log.py +249 -0
  6. django_cfg/apps/centrifugo/admin/config.py +82 -0
  7. django_cfg/apps/centrifugo/apps.py +31 -0
  8. django_cfg/apps/centrifugo/codegen/IMPLEMENTATION_SUMMARY.md +475 -0
  9. django_cfg/apps/centrifugo/codegen/README.md +242 -0
  10. django_cfg/apps/centrifugo/codegen/USAGE.md +616 -0
  11. django_cfg/apps/centrifugo/codegen/__init__.py +19 -0
  12. django_cfg/apps/centrifugo/codegen/discovery.py +246 -0
  13. django_cfg/apps/centrifugo/codegen/generators/go_thin/__init__.py +5 -0
  14. django_cfg/apps/centrifugo/codegen/generators/go_thin/generator.py +174 -0
  15. django_cfg/apps/centrifugo/codegen/generators/go_thin/templates/README.md.j2 +182 -0
  16. django_cfg/apps/centrifugo/codegen/generators/go_thin/templates/client.go.j2 +64 -0
  17. django_cfg/apps/centrifugo/codegen/generators/go_thin/templates/go.mod.j2 +10 -0
  18. django_cfg/apps/centrifugo/codegen/generators/go_thin/templates/rpc_client.go.j2 +300 -0
  19. django_cfg/apps/centrifugo/codegen/generators/go_thin/templates/rpc_client.go.j2.old +267 -0
  20. django_cfg/apps/centrifugo/codegen/generators/go_thin/templates/types.go.j2 +16 -0
  21. django_cfg/apps/centrifugo/codegen/generators/python_thin/__init__.py +7 -0
  22. django_cfg/apps/centrifugo/codegen/generators/python_thin/generator.py +241 -0
  23. django_cfg/apps/centrifugo/codegen/generators/python_thin/templates/README.md.j2 +128 -0
  24. django_cfg/apps/centrifugo/codegen/generators/python_thin/templates/__init__.py.j2 +22 -0
  25. django_cfg/apps/centrifugo/codegen/generators/python_thin/templates/client.py.j2 +73 -0
  26. django_cfg/apps/centrifugo/codegen/generators/python_thin/templates/models.py.j2 +19 -0
  27. django_cfg/apps/centrifugo/codegen/generators/python_thin/templates/requirements.txt.j2 +8 -0
  28. django_cfg/apps/centrifugo/codegen/generators/python_thin/templates/rpc_client.py.j2 +193 -0
  29. django_cfg/apps/centrifugo/codegen/generators/typescript_thin/__init__.py +5 -0
  30. django_cfg/apps/centrifugo/codegen/generators/typescript_thin/generator.py +124 -0
  31. django_cfg/apps/centrifugo/codegen/generators/typescript_thin/templates/README.md.j2 +38 -0
  32. django_cfg/apps/centrifugo/codegen/generators/typescript_thin/templates/client.ts.j2 +25 -0
  33. django_cfg/apps/centrifugo/codegen/generators/typescript_thin/templates/index.ts.j2 +12 -0
  34. django_cfg/apps/centrifugo/codegen/generators/typescript_thin/templates/package.json.j2 +13 -0
  35. django_cfg/apps/centrifugo/codegen/generators/typescript_thin/templates/rpc-client.ts.j2 +137 -0
  36. django_cfg/apps/centrifugo/codegen/generators/typescript_thin/templates/tsconfig.json.j2 +14 -0
  37. django_cfg/apps/centrifugo/codegen/generators/typescript_thin/templates/types.ts.j2 +9 -0
  38. django_cfg/apps/centrifugo/codegen/utils/__init__.py +37 -0
  39. django_cfg/apps/centrifugo/codegen/utils/naming.py +155 -0
  40. django_cfg/apps/centrifugo/codegen/utils/type_converter.py +349 -0
  41. django_cfg/apps/centrifugo/decorators.py +137 -0
  42. django_cfg/apps/centrifugo/management/__init__.py +1 -0
  43. django_cfg/apps/centrifugo/management/commands/__init__.py +1 -0
  44. django_cfg/apps/centrifugo/management/commands/generate_centrifugo_clients.py +254 -0
  45. django_cfg/apps/centrifugo/managers/__init__.py +12 -0
  46. django_cfg/apps/centrifugo/managers/centrifugo_log.py +264 -0
  47. django_cfg/apps/centrifugo/migrations/0001_initial.py +164 -0
  48. django_cfg/apps/centrifugo/migrations/__init__.py +3 -0
  49. django_cfg/apps/centrifugo/models/__init__.py +11 -0
  50. django_cfg/apps/centrifugo/models/centrifugo_log.py +210 -0
  51. django_cfg/apps/centrifugo/registry.py +106 -0
  52. django_cfg/apps/centrifugo/router.py +125 -0
  53. django_cfg/apps/centrifugo/serializers/__init__.py +40 -0
  54. django_cfg/apps/centrifugo/serializers/admin_api.py +264 -0
  55. django_cfg/apps/centrifugo/serializers/channels.py +26 -0
  56. django_cfg/apps/centrifugo/serializers/health.py +17 -0
  57. django_cfg/apps/centrifugo/serializers/publishes.py +16 -0
  58. django_cfg/apps/centrifugo/serializers/stats.py +21 -0
  59. django_cfg/apps/centrifugo/services/__init__.py +12 -0
  60. django_cfg/apps/centrifugo/services/client/__init__.py +29 -0
  61. django_cfg/apps/centrifugo/services/client/client.py +582 -0
  62. django_cfg/apps/centrifugo/services/client/config.py +236 -0
  63. django_cfg/apps/centrifugo/services/client/exceptions.py +212 -0
  64. django_cfg/apps/centrifugo/services/config_helper.py +63 -0
  65. django_cfg/apps/centrifugo/services/dashboard_notifier.py +157 -0
  66. django_cfg/apps/centrifugo/services/logging.py +677 -0
  67. django_cfg/apps/centrifugo/static/django_cfg_centrifugo/css/dashboard.css +260 -0
  68. django_cfg/apps/centrifugo/static/django_cfg_centrifugo/js/dashboard/live_channels.mjs +313 -0
  69. django_cfg/apps/centrifugo/static/django_cfg_centrifugo/js/dashboard/live_testing.mjs +803 -0
  70. django_cfg/apps/centrifugo/static/django_cfg_centrifugo/js/dashboard/main.mjs +333 -0
  71. django_cfg/apps/centrifugo/static/django_cfg_centrifugo/js/dashboard/overview.mjs +432 -0
  72. django_cfg/apps/centrifugo/static/django_cfg_centrifugo/js/dashboard/testing.mjs +33 -0
  73. django_cfg/apps/centrifugo/static/django_cfg_centrifugo/js/dashboard/websocket.mjs +210 -0
  74. django_cfg/apps/centrifugo/templates/django_cfg_centrifugo/components/channels_content.html +46 -0
  75. django_cfg/apps/centrifugo/templates/django_cfg_centrifugo/components/live_channels_content.html +123 -0
  76. django_cfg/apps/centrifugo/templates/django_cfg_centrifugo/components/overview_content.html +45 -0
  77. django_cfg/apps/centrifugo/templates/django_cfg_centrifugo/components/publishes_content.html +84 -0
  78. django_cfg/apps/{ipc/templates/django_cfg_ipc → centrifugo/templates/django_cfg_centrifugo}/components/stat_cards.html +23 -20
  79. django_cfg/apps/centrifugo/templates/django_cfg_centrifugo/components/system_status.html +91 -0
  80. django_cfg/apps/{ipc/templates/django_cfg_ipc → centrifugo/templates/django_cfg_centrifugo}/components/tab_navigation.html +15 -15
  81. django_cfg/apps/centrifugo/templates/django_cfg_centrifugo/components/testing_tools.html +415 -0
  82. django_cfg/apps/centrifugo/templates/django_cfg_centrifugo/layout/base.html +61 -0
  83. django_cfg/apps/centrifugo/templates/django_cfg_centrifugo/pages/dashboard.html +58 -0
  84. django_cfg/apps/centrifugo/templates/django_cfg_centrifugo/tags/connection_script.html +48 -0
  85. django_cfg/apps/centrifugo/templatetags/__init__.py +1 -0
  86. django_cfg/apps/centrifugo/templatetags/centrifugo_tags.py +81 -0
  87. django_cfg/apps/centrifugo/urls.py +31 -0
  88. django_cfg/apps/{ipc → centrifugo}/urls_admin.py +4 -4
  89. django_cfg/apps/centrifugo/views/__init__.py +15 -0
  90. django_cfg/apps/centrifugo/views/admin_api.py +380 -0
  91. django_cfg/apps/centrifugo/views/dashboard.py +15 -0
  92. django_cfg/apps/centrifugo/views/monitoring.py +286 -0
  93. django_cfg/apps/centrifugo/views/testing_api.py +422 -0
  94. django_cfg/apps/support/utils/support_email_service.py +5 -18
  95. django_cfg/apps/tasks/templates/tasks/layout/base.html +0 -2
  96. django_cfg/apps/urls.py +5 -5
  97. django_cfg/core/base/config_model.py +4 -44
  98. django_cfg/core/builders/apps_builder.py +2 -2
  99. django_cfg/core/generation/integration_generators/third_party.py +8 -8
  100. django_cfg/core/utils/__init__.py +5 -0
  101. django_cfg/core/utils/url_helpers.py +73 -0
  102. django_cfg/modules/base.py +7 -7
  103. django_cfg/modules/django_client/core/__init__.py +2 -1
  104. django_cfg/modules/django_client/core/config/config.py +8 -0
  105. django_cfg/modules/django_client/core/generator/__init__.py +42 -2
  106. django_cfg/modules/django_client/core/generator/go/__init__.py +14 -0
  107. django_cfg/modules/django_client/core/generator/go/client_generator.py +124 -0
  108. django_cfg/modules/django_client/core/generator/go/files_generator.py +133 -0
  109. django_cfg/modules/django_client/core/generator/go/generator.py +203 -0
  110. django_cfg/modules/django_client/core/generator/go/models_generator.py +304 -0
  111. django_cfg/modules/django_client/core/generator/go/naming.py +193 -0
  112. django_cfg/modules/django_client/core/generator/go/operations_generator.py +134 -0
  113. django_cfg/modules/django_client/core/generator/go/templates/Makefile.j2 +38 -0
  114. django_cfg/modules/django_client/core/generator/go/templates/README.md.j2 +55 -0
  115. django_cfg/modules/django_client/core/generator/go/templates/client.go.j2 +122 -0
  116. django_cfg/modules/django_client/core/generator/go/templates/enums.go.j2 +49 -0
  117. django_cfg/modules/django_client/core/generator/go/templates/errors.go.j2 +182 -0
  118. django_cfg/modules/django_client/core/generator/go/templates/go.mod.j2 +6 -0
  119. django_cfg/modules/django_client/core/generator/go/templates/main_client.go.j2 +60 -0
  120. django_cfg/modules/django_client/core/generator/go/templates/middleware.go.j2 +388 -0
  121. django_cfg/modules/django_client/core/generator/go/templates/models.go.j2 +28 -0
  122. django_cfg/modules/django_client/core/generator/go/templates/operations_client.go.j2 +142 -0
  123. django_cfg/modules/django_client/core/generator/go/templates/validation.go.j2 +217 -0
  124. django_cfg/modules/django_client/core/generator/go/type_mapper.py +380 -0
  125. django_cfg/modules/django_client/management/commands/generate_client.py +53 -3
  126. django_cfg/modules/django_client/system/generate_mjs_clients.py +3 -1
  127. django_cfg/modules/django_client/system/schema_parser.py +5 -1
  128. django_cfg/modules/django_tailwind/templates/django_tailwind/base.html +1 -0
  129. django_cfg/modules/django_twilio/sendgrid_service.py +7 -4
  130. django_cfg/modules/django_unfold/dashboard.py +25 -19
  131. django_cfg/pyproject.toml +1 -1
  132. django_cfg/registry/core.py +2 -0
  133. django_cfg/registry/modules.py +2 -2
  134. django_cfg/static/js/api/centrifugo/client.mjs +164 -0
  135. django_cfg/static/js/api/centrifugo/index.mjs +13 -0
  136. django_cfg/static/js/api/index.mjs +5 -5
  137. django_cfg/static/js/api/types.mjs +89 -26
  138. {django_cfg-1.4.62.dist-info → django_cfg-1.4.64.dist-info}/METADATA +1 -1
  139. {django_cfg-1.4.62.dist-info → django_cfg-1.4.64.dist-info}/RECORD +142 -70
  140. django_cfg/apps/ipc/README.md +0 -346
  141. django_cfg/apps/ipc/RPC_LOGGING.md +0 -321
  142. django_cfg/apps/ipc/TESTING.md +0 -539
  143. django_cfg/apps/ipc/__init__.py +0 -60
  144. django_cfg/apps/ipc/admin.py +0 -232
  145. django_cfg/apps/ipc/apps.py +0 -98
  146. django_cfg/apps/ipc/migrations/0001_initial.py +0 -137
  147. django_cfg/apps/ipc/migrations/0002_rpclog_is_event.py +0 -23
  148. django_cfg/apps/ipc/migrations/__init__.py +0 -0
  149. django_cfg/apps/ipc/models.py +0 -229
  150. django_cfg/apps/ipc/serializers/__init__.py +0 -29
  151. django_cfg/apps/ipc/serializers/serializers.py +0 -343
  152. django_cfg/apps/ipc/services/__init__.py +0 -7
  153. django_cfg/apps/ipc/services/client/__init__.py +0 -23
  154. django_cfg/apps/ipc/services/client/client.py +0 -621
  155. django_cfg/apps/ipc/services/client/config.py +0 -214
  156. django_cfg/apps/ipc/services/client/exceptions.py +0 -201
  157. django_cfg/apps/ipc/services/logging.py +0 -239
  158. django_cfg/apps/ipc/services/monitor.py +0 -466
  159. django_cfg/apps/ipc/services/rpc_log_consumer.py +0 -330
  160. django_cfg/apps/ipc/static/django_cfg_ipc/js/dashboard/main.mjs +0 -269
  161. django_cfg/apps/ipc/static/django_cfg_ipc/js/dashboard/overview.mjs +0 -259
  162. django_cfg/apps/ipc/static/django_cfg_ipc/js/dashboard/testing.mjs +0 -375
  163. django_cfg/apps/ipc/static/django_cfg_ipc/js/dashboard.mjs.old +0 -441
  164. django_cfg/apps/ipc/templates/django_cfg_ipc/components/methods_content.html +0 -22
  165. django_cfg/apps/ipc/templates/django_cfg_ipc/components/notifications_content.html +0 -9
  166. django_cfg/apps/ipc/templates/django_cfg_ipc/components/overview_content.html +0 -9
  167. django_cfg/apps/ipc/templates/django_cfg_ipc/components/requests_content.html +0 -23
  168. django_cfg/apps/ipc/templates/django_cfg_ipc/components/system_status.html +0 -47
  169. django_cfg/apps/ipc/templates/django_cfg_ipc/components/testing_tools.html +0 -184
  170. django_cfg/apps/ipc/templates/django_cfg_ipc/layout/base.html +0 -71
  171. django_cfg/apps/ipc/templates/django_cfg_ipc/pages/dashboard.html +0 -56
  172. django_cfg/apps/ipc/urls.py +0 -23
  173. django_cfg/apps/ipc/views/__init__.py +0 -13
  174. django_cfg/apps/ipc/views/dashboard.py +0 -15
  175. django_cfg/apps/ipc/views/monitoring.py +0 -251
  176. django_cfg/apps/ipc/views/testing.py +0 -285
  177. django_cfg/static/js/api/ipc/client.mjs +0 -114
  178. django_cfg/static/js/api/ipc/index.mjs +0 -13
  179. {django_cfg-1.4.62.dist-info → django_cfg-1.4.64.dist-info}/WHEEL +0 -0
  180. {django_cfg-1.4.62.dist-info → django_cfg-1.4.64.dist-info}/entry_points.txt +0 -0
  181. {django_cfg-1.4.62.dist-info → django_cfg-1.4.64.dist-info}/licenses/LICENSE +0 -0
@@ -1,441 +0,0 @@
1
- /**
2
- * RPC Dashboard JavaScript Module
3
- *
4
- * Uses generated MJS API client for all API calls
5
- *
6
- * Handles:
7
- * - Tab switching
8
- * - Auto-refresh
9
- * - Live data updates
10
- * - API communication via generated client
11
- */
12
-
13
- import { ipcAPI } from '/static/js/api/ipc/index.mjs';
14
-
15
- class RPCDashboard {
16
- constructor() {
17
- this.autoRefresh = true;
18
- this.refreshInterval = 5000; // 5 seconds
19
- this.intervalId = null;
20
- this.currentTab = 'overview';
21
-
22
- // Use the pre-instantiated API client
23
- this.api = ipcAPI;
24
-
25
- this.init();
26
- }
27
-
28
- init() {
29
- console.log('🚀 RPC Dashboard initializing...');
30
-
31
- // Setup tab switching
32
- this.setupTabs();
33
-
34
- // Setup auto-refresh toggle
35
- this.setupAutoRefresh();
36
-
37
- // Initial data load
38
- this.loadAllData();
39
-
40
- // Start auto-refresh
41
- this.startAutoRefresh();
42
-
43
- console.log('✅ RPC Dashboard initialized');
44
- }
45
-
46
- setupTabs() {
47
- const tabButtons = document.querySelectorAll('.tab-button');
48
-
49
- tabButtons.forEach(button => {
50
- button.addEventListener('click', (e) => {
51
- const tabName = e.target.dataset.tab;
52
- this.switchTab(tabName);
53
- });
54
- });
55
- }
56
-
57
- switchTab(tabName) {
58
- // Update buttons
59
- document.querySelectorAll('.tab-button').forEach(btn => {
60
- if (btn.dataset.tab === tabName) {
61
- btn.classList.add('active', 'text-blue-600', 'dark:text-blue-400', 'border-blue-600', 'dark:border-blue-400');
62
- btn.classList.remove('text-gray-600', 'dark:text-gray-400', 'border-transparent');
63
- } else {
64
- btn.classList.remove('active', 'text-blue-600', 'dark:text-blue-400', 'border-blue-600', 'dark:border-blue-400');
65
- btn.classList.add('text-gray-600', 'dark:text-gray-400', 'border-transparent');
66
- }
67
- });
68
-
69
- // Update panels
70
- document.querySelectorAll('.tab-panel').forEach(panel => {
71
- panel.classList.add('hidden');
72
- });
73
-
74
- const activePanel = document.getElementById(`${tabName}-tab`);
75
- if (activePanel) {
76
- activePanel.classList.remove('hidden');
77
- }
78
-
79
- this.currentTab = tabName;
80
-
81
- // Load tab-specific data
82
- this.loadTabData(tabName);
83
- }
84
-
85
- setupAutoRefresh() {
86
- const toggle = document.getElementById('auto-refresh-toggle');
87
-
88
- if (toggle) {
89
- toggle.checked = this.autoRefresh;
90
-
91
- toggle.addEventListener('change', (e) => {
92
- this.autoRefresh = e.target.checked;
93
-
94
- if (this.autoRefresh) {
95
- this.startAutoRefresh();
96
- } else {
97
- this.stopAutoRefresh();
98
- }
99
- });
100
- }
101
- }
102
-
103
- startAutoRefresh() {
104
- if (this.intervalId) {
105
- clearInterval(this.intervalId);
106
- }
107
-
108
- this.intervalId = setInterval(() => {
109
- if (this.autoRefresh) {
110
- this.loadAllData();
111
- }
112
- }, this.refreshInterval);
113
- }
114
-
115
- stopAutoRefresh() {
116
- if (this.intervalId) {
117
- clearInterval(this.intervalId);
118
- this.intervalId = null;
119
- }
120
- }
121
-
122
- async loadAllData() {
123
- try {
124
- await Promise.all([
125
- this.loadOverviewStats(),
126
- this.loadHealthStatus()
127
- ]);
128
- await this.loadTabData(this.currentTab);
129
- this.updateLastUpdate();
130
- } catch (error) {
131
- console.error('Error loading data:', error);
132
- this.showError('Failed to load data');
133
- }
134
- }
135
-
136
- async loadTabData(tabName) {
137
- switch (tabName) {
138
- case 'overview':
139
- // Already loaded in loadOverviewStats
140
- break;
141
- case 'requests':
142
- await this.loadRecentRequests();
143
- break;
144
- case 'notifications':
145
- await this.loadNotificationStats();
146
- break;
147
- case 'methods':
148
- await this.loadMethodStats();
149
- break;
150
- }
151
- }
152
-
153
- async loadOverviewStats() {
154
- try {
155
- const stats = await this.api.ipcAdminApiMonitorOverviewRetrieve();
156
-
157
- if (stats) {
158
- // Update stats cards
159
- this.updateElement('total-requests', stats.total_requests_today || 0);
160
- this.updateElement('active-methods-count', stats.active_methods?.length || 0);
161
- this.updateElement('avg-response-time', (stats.avg_response_time_ms || 0).toFixed(0));
162
- this.updateElement('success-rate', (stats.success_rate || 0).toFixed(1));
163
-
164
- // Update top method (XSS-safe)
165
- if (stats.top_method) {
166
- const topMethodElement = document.getElementById('top-method');
167
- if (topMethodElement) {
168
- const code = document.createElement('code');
169
- code.className = 'bg-gray-100 dark:bg-gray-700 px-2 py-1 rounded text-blue-600 dark:text-blue-300';
170
- code.textContent = stats.top_method; // Safe from XSS
171
- topMethodElement.innerHTML = '';
172
- topMethodElement.appendChild(code);
173
- }
174
- }
175
- }
176
- } catch (error) {
177
- console.error('Error loading overview stats:', error);
178
- }
179
- }
180
-
181
- async loadHealthStatus() {
182
- try {
183
- const health = await this.api.ipcAdminApiMonitorHealthRetrieve();
184
-
185
- if (health) {
186
- // Update health indicator
187
- const indicator = document.getElementById('health-indicator');
188
- if (indicator) {
189
- const isHealthy = health.redis_connected && health.stream_exists;
190
- indicator.innerHTML = `
191
- <span class="pulse-dot w-2 h-2 ${isHealthy ? 'bg-green-500' : 'bg-red-500'} rounded-full"></span>
192
- <span class="text-sm text-gray-700 dark:text-gray-300">${isHealthy ? 'Connected' : 'Disconnected'}</span>
193
- `;
194
- }
195
-
196
- // Update system status section
197
- this.updateSystemStatus(health);
198
- }
199
- } catch (error) {
200
- console.error('Error loading health status:', error);
201
- }
202
- }
203
-
204
- updateSystemStatus(health) {
205
- const statusContainer = document.getElementById('system-status');
206
- if (!statusContainer) return;
207
-
208
- statusContainer.innerHTML = `
209
- <!-- Redis Status -->
210
- <div class="flex items-start gap-3">
211
- <span class="material-icons flex-shrink-0 text-2xl ${health.redis_connected ? 'text-green-500' : 'text-red-500'}">
212
- ${health.redis_connected ? 'check_circle' : 'cancel'}
213
- </span>
214
- <div class="min-w-0">
215
- <p class="text-sm font-medium text-gray-900 dark:text-white">Redis</p>
216
- <p class="text-xs text-gray-600 dark:text-gray-400">
217
- ${health.redis_connected ? 'Connected (DB 2)' : 'Disconnected'}
218
- </p>
219
- </div>
220
- </div>
221
-
222
- <!-- Stream Status -->
223
- <div class="flex items-start gap-3">
224
- <span class="material-icons flex-shrink-0 text-2xl ${health.stream_exists ? 'text-green-500' : 'text-gray-500'}">
225
- ${health.stream_exists ? 'stream' : 'stream_off'}
226
- </span>
227
- <div class="min-w-0">
228
- <p class="text-sm font-medium text-gray-900 dark:text-white">Request Stream</p>
229
- <p class="text-xs text-gray-600 dark:text-gray-400">
230
- ${health.stream_exists ? `${health.stream_length} entries` : 'Not initialized'}
231
- </p>
232
- </div>
233
- </div>
234
-
235
- <!-- Activity Status -->
236
- <div class="flex items-start gap-3">
237
- <span class="material-icons flex-shrink-0 text-2xl ${health.recent_activity ? 'text-green-500' : 'text-yellow-500'}">
238
- ${health.recent_activity ? 'notifications_active' : 'notifications_paused'}
239
- </span>
240
- <div class="min-w-0">
241
- <p class="text-sm font-medium text-gray-900 dark:text-white">Recent Activity</p>
242
- <p class="text-xs text-gray-600 dark:text-gray-400">
243
- ${health.recent_activity ? 'Active (last 5 min)' : 'No recent activity'}
244
- </p>
245
- </div>
246
- </div>
247
- `;
248
- }
249
-
250
- async loadRecentRequests() {
251
- try {
252
- const data = await this.api.ipcAdminApiMonitorRequestsRetrieve({ count: 50 });
253
-
254
- if (data) {
255
- const requests = data.requests || [];
256
- this.renderRequestsTable(requests);
257
- }
258
- } catch (error) {
259
- console.error('Error loading recent requests:', error);
260
- }
261
- }
262
-
263
- renderRequestsTable(requests) {
264
- const tbody = document.getElementById('requests-table-body');
265
- if (!tbody) return;
266
-
267
- if (requests.length === 0) {
268
- tbody.innerHTML = `
269
- <tr>
270
- <td colspan="4" class="px-4 py-8 text-center text-gray-500 dark:text-gray-400">
271
- No recent requests found
272
- </td>
273
- </tr>
274
- `;
275
- return;
276
- }
277
-
278
- tbody.innerHTML = requests.map(req => `
279
- <tr class="hover:bg-gray-50 dark:hover:bg-gray-700">
280
- <td class="px-4 py-3 text-sm">
281
- ${this.formatTimestamp(req.timestamp)}
282
- </td>
283
- <td class="px-4 py-3">
284
- <code class="text-sm bg-gray-100 dark:bg-gray-700 px-2 py-1 rounded">${this.escapeHtml(req.method || 'unknown')}</code>
285
- </td>
286
- <td class="px-4 py-3 text-sm font-mono">
287
- ${this.escapeHtml((req.correlation_id || '').substring(0, 8))}...
288
- </td>
289
- <td class="px-4 py-3 text-sm">
290
- <details class="cursor-pointer">
291
- <summary class="text-blue-600 dark:text-blue-400 hover:underline">View</summary>
292
- <pre class="mt-2 text-xs bg-gray-100 dark:bg-gray-900 p-2 rounded overflow-auto max-h-40">${this.escapeHtml(JSON.stringify(req.params || {}, null, 2))}</pre>
293
- </details>
294
- </td>
295
- </tr>
296
- `).join('');
297
- }
298
-
299
- async loadNotificationStats() {
300
- try {
301
- const stats = await this.api.ipcAdminApiMonitorNotificationsRetrieve();
302
-
303
- if (stats) {
304
- this.renderNotificationStats(stats);
305
- }
306
- } catch (error) {
307
- console.error('Error loading notification stats:', error);
308
- }
309
- }
310
-
311
- renderNotificationStats(stats) {
312
- const container = document.getElementById('notification-stats-content');
313
- if (!container) return;
314
-
315
- const byType = stats.by_type || {};
316
- const total = stats.total_sent || 0;
317
-
318
- container.innerHTML = `
319
- <div class="space-y-4">
320
- <div class="flex items-center justify-between p-4 bg-gray-50 dark:bg-gray-700 rounded">
321
- <span>Total Sent</span>
322
- <span class="text-2xl font-bold">${total}</span>
323
- </div>
324
- <div class="flex items-center justify-between p-4 bg-gray-50 dark:bg-gray-700 rounded">
325
- <span>Delivery Rate</span>
326
- <span class="text-2xl font-bold text-green-600 dark:text-green-400">${stats.delivery_rate || 0}%</span>
327
- </div>
328
- <div>
329
- <h4 class="text-md font-semibold mb-3">By Type</h4>
330
- <div class="space-y-2">
331
- ${Object.entries(byType).map(([type, count]) => `
332
- <div class="flex items-center justify-between p-3 bg-gray-50 dark:bg-gray-700 rounded">
333
- <span>${this.escapeHtml(type)}</span>
334
- <span class="font-medium">${count}</span>
335
- </div>
336
- `).join('') || '<p class="text-gray-500 dark:text-gray-400">No data available</p>'}
337
- </div>
338
- </div>
339
- ${stats.recent && stats.recent.length > 0 ? `
340
- <div>
341
- <h4 class="text-md font-semibold mb-3">Recent Notifications</h4>
342
- <div class="space-y-2">
343
- ${stats.recent.slice(0, 5).map(notif => `
344
- <div class="p-3 bg-gray-50 dark:bg-gray-700 rounded">
345
- <div class="flex justify-between items-start">
346
- <span class="text-sm">${this.escapeHtml(notif.type || 'unknown')}</span>
347
- <span class="text-xs text-gray-500 dark:text-gray-400">${this.formatTimestamp(notif.timestamp)}</span>
348
- </div>
349
- ${notif.message ? `<p class="text-xs text-gray-600 dark:text-gray-400 mt-1">${this.escapeHtml(notif.message)}</p>` : ''}
350
- </div>
351
- `).join('')}
352
- </div>
353
- </div>
354
- ` : ''}
355
- </div>
356
- `;
357
- }
358
-
359
- async loadMethodStats() {
360
- try {
361
- const data = await this.api.ipcAdminApiMonitorMethodsRetrieve();
362
-
363
- if (data) {
364
- const methods = data.methods || [];
365
- this.renderMethodsTable(methods);
366
- }
367
- } catch (error) {
368
- console.error('Error loading method stats:', error);
369
- }
370
- }
371
-
372
- renderMethodsTable(methods) {
373
- const tbody = document.getElementById('methods-table-body');
374
- if (!tbody) return;
375
-
376
- if (methods.length === 0) {
377
- tbody.innerHTML = `
378
- <tr>
379
- <td colspan="4" class="px-4 py-8 text-center text-gray-500 dark:text-gray-400">
380
- No method data available
381
- </td>
382
- </tr>
383
- `;
384
- return;
385
- }
386
-
387
- tbody.innerHTML = methods.map(method => `
388
- <tr class="hover:bg-gray-50 dark:hover:bg-gray-700">
389
- <td class="px-4 py-3">
390
- <code class="text-sm bg-gray-100 dark:bg-gray-700 px-2 py-1 rounded">${this.escapeHtml(method.method)}</code>
391
- </td>
392
- <td class="px-4 py-3 text-sm font-medium">${method.count}</td>
393
- <td class="px-4 py-3 text-sm">${method.percentage}%</td>
394
- <td class="px-4 py-3 text-sm">${method.avg_time_ms || method.avg_time || 0}ms</td>
395
- </tr>
396
- `).join('');
397
- }
398
-
399
- updateElement(id, value) {
400
- const element = document.getElementById(id);
401
- if (element) {
402
- element.textContent = value;
403
- }
404
- }
405
-
406
- formatTimestamp(isoString) {
407
- try {
408
- const date = new Date(isoString);
409
- return date.toLocaleTimeString();
410
- } catch {
411
- return 'N/A';
412
- }
413
- }
414
-
415
- escapeHtml(unsafe) {
416
- const div = document.createElement('div');
417
- div.textContent = unsafe;
418
- return div.innerHTML;
419
- }
420
-
421
- updateLastUpdate() {
422
- const element = document.getElementById('last-update');
423
- if (element) {
424
- const now = new Date();
425
- element.textContent = `Last updated: ${now.toLocaleTimeString()}`;
426
- }
427
- }
428
-
429
- showError(message) {
430
- console.error('Dashboard error:', message);
431
- // Could show a toast notification here
432
- }
433
- }
434
-
435
- // Initialize dashboard when DOM is ready
436
- document.addEventListener('DOMContentLoaded', () => {
437
- window.rpcDashboard = new RPCDashboard();
438
- });
439
-
440
- // Export for debugging
441
- export default RPCDashboard;
@@ -1,22 +0,0 @@
1
- <!-- Methods Tab -->
2
- <div id="methods-tab" class="tab-panel hidden">
3
- <div class="bg-white dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700 overflow-hidden">
4
- <table class="w-full">
5
- <thead class="bg-gray-50 dark:bg-gray-900">
6
- <tr>
7
- <th class="px-4 py-3 text-left text-xs font-medium text-gray-700 dark:text-gray-400 uppercase">Method</th>
8
- <th class="px-4 py-3 text-left text-xs font-medium text-gray-700 dark:text-gray-400 uppercase">Count</th>
9
- <th class="px-4 py-3 text-left text-xs font-medium text-gray-700 dark:text-gray-400 uppercase">Percentage</th>
10
- <th class="px-4 py-3 text-left text-xs font-medium text-gray-700 dark:text-gray-400 uppercase">Avg Time</th>
11
- </tr>
12
- </thead>
13
- <tbody id="methods-table-body" class="divide-y divide-gray-200 dark:divide-gray-700">
14
- <tr>
15
- <td colspan="4" class="px-4 py-8 text-center text-gray-600 dark:text-gray-400">
16
- Loading...
17
- </td>
18
- </tr>
19
- </tbody>
20
- </table>
21
- </div>
22
- </div>
@@ -1,9 +0,0 @@
1
- <!-- Notifications Tab -->
2
- <div id="notifications-tab" class="tab-panel hidden">
3
- <div class="bg-white dark:bg-gray-800 rounded-lg p-6 border border-gray-200 dark:border-gray-700">
4
- <h3 class="text-lg font-bold text-gray-900 dark:text-white mb-4">Notification Statistics</h3>
5
- <div id="notification-stats-content">
6
- <p class="text-gray-600 dark:text-gray-400">Loading...</p>
7
- </div>
8
- </div>
9
- </div>
@@ -1,9 +0,0 @@
1
- <!-- Overview Tab (Active by default) -->
2
- <div id="overview-tab" class="tab-panel">
3
- <div class="bg-white dark:bg-gray-800 rounded-lg p-6 border border-gray-200 dark:border-gray-700">
4
- <h3 class="text-lg font-bold text-gray-900 dark:text-white mb-4">Top Method</h3>
5
- <p class="text-gray-700 dark:text-gray-300" id="top-method">
6
- <span class="text-gray-500">Loading...</span>
7
- </p>
8
- </div>
9
- </div>
@@ -1,23 +0,0 @@
1
- <!-- Recent Requests Tab -->
2
- <div id="requests-tab" class="tab-panel hidden">
3
- <div class="bg-white dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700 overflow-hidden">
4
- <table class="w-full">
5
- <thead class="bg-gray-50 dark:bg-gray-900">
6
- <tr>
7
- <th class="px-4 py-3 text-left text-xs font-medium text-gray-700 dark:text-gray-400 uppercase">Time</th>
8
- <th class="px-4 py-3 text-left text-xs font-medium text-gray-700 dark:text-gray-400 uppercase">Method</th>
9
- <th class="px-4 py-3 text-left text-xs font-medium text-gray-700 dark:text-gray-400 uppercase">Status</th>
10
- <th class="px-4 py-3 text-left text-xs font-medium text-gray-700 dark:text-gray-400 uppercase">Duration</th>
11
- <th class="px-4 py-3 text-left text-xs font-medium text-gray-700 dark:text-gray-400 uppercase">Correlation ID</th>
12
- </tr>
13
- </thead>
14
- <tbody id="requests-table-body" class="divide-y divide-gray-200 dark:divide-gray-700">
15
- <tr>
16
- <td colspan="5" class="px-4 py-8 text-center text-gray-600 dark:text-gray-400">
17
- Loading...
18
- </td>
19
- </tr>
20
- </tbody>
21
- </table>
22
- </div>
23
- </div>
@@ -1,47 +0,0 @@
1
- <!-- System Status -->
2
- <div class="bg-white dark:bg-gray-800 rounded-lg p-6 border border-gray-200 dark:border-gray-700 mb-8">
3
- <h2 class="text-xl font-bold text-gray-900 dark:text-white mb-4 flex items-center">
4
- <span class="material-icons mr-2">health_and_safety</span>
5
- System Status
6
- </h2>
7
- <div id="system-status" class="grid grid-cols-1 md:grid-cols-3 gap-4">
8
- <!-- Redis Status -->
9
- <div class="flex items-start gap-3">
10
- <span class="material-icons flex-shrink-0 text-2xl text-gray-500" id="redis-status-icon">
11
- help_outline
12
- </span>
13
- <div class="min-w-0">
14
- <p class="text-sm font-medium text-gray-900 dark:text-white">Redis</p>
15
- <p class="text-xs text-gray-600 dark:text-gray-400" id="redis-status-text">
16
- Checking...
17
- </p>
18
- </div>
19
- </div>
20
-
21
- <!-- Stream Status -->
22
- <div class="flex items-start gap-3">
23
- <span class="material-icons flex-shrink-0 text-2xl text-gray-500" id="stream-status-icon">
24
- help_outline
25
- </span>
26
- <div class="min-w-0">
27
- <p class="text-sm font-medium text-gray-900 dark:text-white">Request Stream</p>
28
- <p class="text-xs text-gray-600 dark:text-gray-400" id="stream-status-text">
29
- Checking...
30
- </p>
31
- </div>
32
- </div>
33
-
34
- <!-- Activity Status -->
35
- <div class="flex items-start gap-3">
36
- <span class="material-icons flex-shrink-0 text-2xl text-gray-500" id="activity-status-icon">
37
- help_outline
38
- </span>
39
- <div class="min-w-0">
40
- <p class="text-sm font-medium text-gray-900 dark:text-white">Recent Activity</p>
41
- <p class="text-xs text-gray-600 dark:text-gray-400" id="activity-status-text">
42
- Checking...
43
- </p>
44
- </div>
45
- </div>
46
- </div>
47
- </div>