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.
- django_cfg/__init__.py +1 -1
- django_cfg/apps/accounts/admin/__init__.py +24 -8
- django_cfg/apps/accounts/admin/activity_admin.py +146 -0
- django_cfg/apps/accounts/admin/filters.py +98 -22
- django_cfg/apps/accounts/admin/group_admin.py +86 -0
- django_cfg/apps/accounts/admin/inlines.py +42 -13
- django_cfg/apps/accounts/admin/otp_admin.py +115 -0
- django_cfg/apps/accounts/admin/registration_admin.py +173 -0
- django_cfg/apps/accounts/admin/resources.py +123 -19
- django_cfg/apps/accounts/admin/twilio_admin.py +327 -0
- django_cfg/apps/accounts/admin/user_admin.py +362 -0
- django_cfg/apps/agents/admin/__init__.py +17 -4
- django_cfg/apps/agents/admin/execution_admin.py +204 -183
- django_cfg/apps/agents/admin/registry_admin.py +230 -255
- django_cfg/apps/agents/admin/toolsets_admin.py +274 -321
- django_cfg/apps/agents/core/__init__.py +1 -1
- django_cfg/apps/agents/core/django_agent.py +221 -0
- django_cfg/apps/agents/core/exceptions.py +14 -0
- django_cfg/apps/agents/core/orchestrator.py +18 -3
- django_cfg/apps/knowbase/admin/__init__.py +1 -1
- django_cfg/apps/knowbase/admin/archive_admin.py +352 -640
- django_cfg/apps/knowbase/admin/chat_admin.py +258 -192
- django_cfg/apps/knowbase/admin/document_admin.py +269 -262
- django_cfg/apps/knowbase/admin/external_data_admin.py +271 -489
- django_cfg/apps/knowbase/config/settings.py +21 -4
- django_cfg/apps/knowbase/views/chat_views.py +3 -0
- django_cfg/apps/leads/admin/__init__.py +3 -1
- django_cfg/apps/leads/admin/leads_admin.py +235 -35
- django_cfg/apps/maintenance/admin/__init__.py +2 -2
- django_cfg/apps/maintenance/admin/api_key_admin.py +125 -63
- django_cfg/apps/maintenance/admin/log_admin.py +143 -61
- django_cfg/apps/maintenance/admin/scheduled_admin.py +212 -301
- django_cfg/apps/maintenance/admin/site_admin.py +213 -352
- django_cfg/apps/newsletter/admin/__init__.py +29 -2
- django_cfg/apps/newsletter/admin/newsletter_admin.py +531 -193
- django_cfg/apps/payments/admin/__init__.py +18 -27
- django_cfg/apps/payments/admin/api_keys_admin.py +179 -546
- django_cfg/apps/payments/admin/balance_admin.py +166 -632
- django_cfg/apps/payments/admin/currencies_admin.py +235 -607
- django_cfg/apps/payments/admin/endpoint_groups_admin.py +127 -0
- django_cfg/apps/payments/admin/filters.py +83 -3
- django_cfg/apps/payments/admin/networks_admin.py +269 -0
- django_cfg/apps/payments/admin/payments_admin.py +183 -460
- django_cfg/apps/payments/admin/subscriptions_admin.py +119 -636
- django_cfg/apps/payments/admin/tariffs_admin.py +248 -0
- django_cfg/apps/payments/admin_interface/serializers/payment_serializers.py +153 -34
- django_cfg/apps/payments/admin_interface/templates/payments/components/payment_card.html +121 -0
- django_cfg/apps/payments/admin_interface/templates/payments/components/payment_qr_code.html +95 -0
- django_cfg/apps/payments/admin_interface/templates/payments/components/progress_bar.html +37 -0
- django_cfg/apps/payments/admin_interface/templates/payments/components/provider_stats.html +60 -0
- django_cfg/apps/payments/admin_interface/templates/payments/components/status_badge.html +41 -0
- django_cfg/apps/payments/admin_interface/templates/payments/components/status_overview.html +83 -0
- django_cfg/apps/payments/admin_interface/templates/payments/payment_detail.html +363 -0
- django_cfg/apps/payments/admin_interface/templates/payments/payment_form.html +43 -17
- django_cfg/apps/payments/admin_interface/views/__init__.py +2 -0
- django_cfg/apps/payments/admin_interface/views/api/payments.py +102 -0
- django_cfg/apps/payments/admin_interface/views/api/webhook_admin.py +109 -63
- django_cfg/apps/payments/admin_interface/views/forms.py +5 -1
- django_cfg/apps/payments/config/__init__.py +14 -15
- django_cfg/apps/payments/config/django_cfg_integration.py +59 -1
- django_cfg/apps/payments/config/helpers.py +8 -13
- django_cfg/apps/payments/management/commands/manage_currencies.py +236 -274
- django_cfg/apps/payments/management/commands/manage_providers.py +4 -1
- django_cfg/apps/payments/middleware/api_access.py +32 -6
- django_cfg/apps/payments/migrations/0001_initial.py +33 -46
- django_cfg/apps/payments/migrations/0002_rename_payments_un_user_id_7f6e79_idx_payments_un_user_id_8ce187_idx_and_more.py +46 -0
- django_cfg/apps/payments/migrations/0003_universalpayment_status_changed_at.py +25 -0
- django_cfg/apps/payments/models/balance.py +12 -0
- django_cfg/apps/payments/models/currencies.py +106 -32
- django_cfg/apps/payments/models/managers/currency_managers.py +65 -0
- django_cfg/apps/payments/models/managers/payment_managers.py +142 -25
- django_cfg/apps/payments/models/payments.py +94 -0
- django_cfg/apps/payments/services/core/base.py +4 -4
- django_cfg/apps/payments/services/core/currency_service.py +35 -28
- django_cfg/apps/payments/services/core/payment_service.py +266 -39
- django_cfg/apps/payments/services/providers/__init__.py +3 -0
- django_cfg/apps/payments/services/providers/base.py +303 -41
- django_cfg/apps/payments/services/providers/models/__init__.py +42 -0
- django_cfg/apps/payments/services/providers/models/base.py +145 -0
- django_cfg/apps/payments/services/providers/models/providers.py +87 -0
- django_cfg/apps/payments/services/providers/models/universal.py +48 -0
- django_cfg/apps/payments/services/providers/nowpayments/__init__.py +31 -0
- django_cfg/apps/payments/services/providers/nowpayments/config.py +70 -0
- django_cfg/apps/payments/services/providers/nowpayments/models.py +150 -0
- django_cfg/apps/payments/services/providers/nowpayments/parsers.py +879 -0
- django_cfg/apps/payments/services/providers/nowpayments/provider.py +557 -0
- django_cfg/apps/payments/services/providers/nowpayments/sync.py +196 -0
- django_cfg/apps/payments/services/providers/registry.py +9 -37
- django_cfg/apps/payments/services/providers/sync_service.py +277 -0
- django_cfg/apps/payments/services/types/requests.py +19 -7
- django_cfg/apps/payments/signals/payment_signals.py +31 -2
- django_cfg/apps/payments/static/payments/js/api-client.js +29 -6
- django_cfg/apps/payments/static/payments/js/payment-detail.js +167 -0
- django_cfg/apps/payments/static/payments/js/payment-form.js +98 -32
- django_cfg/apps/payments/tasks/__init__.py +39 -0
- django_cfg/apps/payments/tasks/types.py +73 -0
- django_cfg/apps/payments/tasks/usage_tracking.py +308 -0
- django_cfg/apps/payments/templates/admin/payments/_components/dashboard_header.html +23 -0
- django_cfg/apps/payments/templates/admin/payments/_components/stats_card.html +25 -0
- django_cfg/apps/payments/templates/admin/payments/_components/stats_grid.html +16 -0
- django_cfg/apps/payments/templates/admin/payments/apikey/change_list.html +39 -0
- django_cfg/apps/payments/templates/admin/payments/balance/change_list.html +50 -0
- django_cfg/apps/payments/templates/admin/payments/currency/change_list.html +40 -0
- django_cfg/apps/payments/templates/admin/payments/payment/change_list.html +48 -0
- django_cfg/apps/payments/templates/admin/payments/subscription/change_list.html +48 -0
- django_cfg/apps/payments/templatetags/payment_tags.py +8 -0
- django_cfg/apps/payments/urls.py +3 -2
- django_cfg/apps/payments/urls_admin.py +1 -1
- django_cfg/apps/payments/views/api/currencies.py +8 -5
- django_cfg/apps/payments/views/overview/services.py +2 -2
- django_cfg/apps/payments/views/serializers/currencies.py +22 -8
- django_cfg/apps/support/admin/__init__.py +10 -1
- django_cfg/apps/support/admin/support_admin.py +338 -141
- django_cfg/apps/tasks/admin/__init__.py +11 -0
- django_cfg/apps/tasks/admin/tasks_admin.py +430 -0
- django_cfg/apps/tasks/static/tasks/css/dashboard.css +68 -217
- django_cfg/apps/tasks/static/tasks/js/api.js +40 -84
- django_cfg/apps/tasks/static/tasks/js/components/DataManager.js +24 -0
- django_cfg/apps/tasks/static/tasks/js/components/TabManager.js +85 -0
- django_cfg/apps/tasks/static/tasks/js/components/TaskRenderer.js +216 -0
- django_cfg/apps/tasks/static/tasks/js/dashboard/main.mjs +245 -0
- django_cfg/apps/tasks/static/tasks/js/dashboard/overview.mjs +123 -0
- django_cfg/apps/tasks/static/tasks/js/dashboard/queues.mjs +120 -0
- django_cfg/apps/tasks/static/tasks/js/dashboard/tasks.mjs +350 -0
- django_cfg/apps/tasks/static/tasks/js/dashboard/workers.mjs +169 -0
- django_cfg/apps/tasks/tasks/__init__.py +10 -0
- django_cfg/apps/tasks/tasks/demo_tasks.py +133 -0
- django_cfg/apps/tasks/templates/tasks/components/management_actions.html +42 -45
- django_cfg/apps/tasks/templates/tasks/components/{status_cards.html → overview_content.html} +30 -11
- django_cfg/apps/tasks/templates/tasks/components/queues_content.html +19 -0
- django_cfg/apps/tasks/templates/tasks/components/tab_navigation.html +16 -10
- django_cfg/apps/tasks/templates/tasks/components/tasks_content.html +51 -0
- django_cfg/apps/tasks/templates/tasks/components/workers_content.html +30 -0
- django_cfg/apps/tasks/templates/tasks/layout/base.html +117 -0
- django_cfg/apps/tasks/templates/tasks/pages/dashboard.html +82 -0
- django_cfg/apps/tasks/templates/tasks/partials/task_row_template.html +40 -0
- django_cfg/apps/tasks/templates/tasks/widgets/task_filters.html +37 -0
- django_cfg/apps/tasks/templates/tasks/widgets/task_footer.html +41 -0
- django_cfg/apps/tasks/templates/tasks/widgets/task_table.html +50 -0
- django_cfg/apps/tasks/urls.py +2 -2
- django_cfg/apps/tasks/urls_admin.py +2 -2
- django_cfg/apps/tasks/utils/__init__.py +1 -0
- django_cfg/apps/tasks/utils/simulator.py +356 -0
- django_cfg/apps/tasks/views/__init__.py +16 -0
- django_cfg/apps/tasks/views/api.py +569 -0
- django_cfg/apps/tasks/views/dashboard.py +58 -0
- django_cfg/config.py +1 -1
- django_cfg/core/config.py +10 -5
- django_cfg/core/generation.py +1 -1
- django_cfg/core/integration/__init__.py +21 -0
- django_cfg/management/commands/__init__.py +13 -1
- django_cfg/management/commands/migrate_all.py +9 -3
- django_cfg/management/commands/migrator.py +11 -6
- django_cfg/management/commands/rundramatiq.py +3 -2
- django_cfg/management/commands/rundramatiq_simulator.py +430 -0
- django_cfg/middleware/__init__.py +0 -2
- django_cfg/models/api_keys.py +115 -0
- django_cfg/models/constance.py +0 -11
- django_cfg/models/payments.py +137 -3
- django_cfg/modules/django_admin/__init__.py +64 -0
- django_cfg/modules/django_admin/decorators/__init__.py +13 -0
- django_cfg/modules/django_admin/decorators/actions.py +106 -0
- django_cfg/modules/django_admin/decorators/display.py +106 -0
- django_cfg/modules/django_admin/mixins/__init__.py +14 -0
- django_cfg/modules/django_admin/mixins/display_mixin.py +81 -0
- django_cfg/modules/django_admin/mixins/optimization_mixin.py +41 -0
- django_cfg/modules/django_admin/mixins/standalone_actions_mixin.py +202 -0
- django_cfg/modules/django_admin/models/__init__.py +20 -0
- django_cfg/modules/django_admin/models/action_models.py +33 -0
- django_cfg/modules/django_admin/models/badge_models.py +20 -0
- django_cfg/modules/django_admin/models/base.py +26 -0
- django_cfg/modules/django_admin/models/display_models.py +31 -0
- django_cfg/modules/django_admin/utils/badges.py +159 -0
- django_cfg/modules/django_admin/utils/displays.py +247 -0
- django_cfg/modules/django_currency/__init__.py +2 -2
- django_cfg/modules/django_currency/clients/__init__.py +2 -2
- django_cfg/modules/django_currency/clients/hybrid_client.py +587 -0
- django_cfg/modules/django_currency/core/converter.py +12 -12
- django_cfg/modules/django_currency/database/__init__.py +2 -2
- django_cfg/modules/django_currency/database/database_loader.py +93 -42
- django_cfg/modules/django_llm/llm/client.py +10 -2
- django_cfg/modules/django_tasks.py +54 -21
- django_cfg/modules/django_unfold/callbacks/actions.py +1 -1
- django_cfg/modules/django_unfold/callbacks/statistics.py +1 -1
- django_cfg/modules/django_unfold/dashboard.py +14 -13
- django_cfg/modules/django_unfold/models/config.py +1 -1
- django_cfg/registry/core.py +7 -9
- django_cfg/registry/third_party.py +2 -2
- django_cfg/template_archive/django_sample.zip +0 -0
- {django_cfg-1.3.7.dist-info → django_cfg-1.3.11.dist-info}/METADATA +2 -1
- {django_cfg-1.3.7.dist-info → django_cfg-1.3.11.dist-info}/RECORD +198 -160
- django_cfg/apps/accounts/admin/activity.py +0 -96
- django_cfg/apps/accounts/admin/group.py +0 -17
- django_cfg/apps/accounts/admin/otp.py +0 -59
- django_cfg/apps/accounts/admin/registration_source.py +0 -97
- django_cfg/apps/accounts/admin/twilio_response.py +0 -227
- django_cfg/apps/accounts/admin/user.py +0 -300
- django_cfg/apps/agents/core/agent.py +0 -281
- django_cfg/apps/payments/admin_interface/old/payments/base.html +0 -175
- django_cfg/apps/payments/admin_interface/old/payments/components/dev_tool_card.html +0 -125
- django_cfg/apps/payments/admin_interface/old/payments/components/loading_spinner.html +0 -16
- django_cfg/apps/payments/admin_interface/old/payments/components/ngrok_status_card.html +0 -113
- django_cfg/apps/payments/admin_interface/old/payments/components/notification.html +0 -27
- django_cfg/apps/payments/admin_interface/old/payments/components/provider_card.html +0 -86
- django_cfg/apps/payments/admin_interface/old/payments/components/status_card.html +0 -35
- django_cfg/apps/payments/admin_interface/old/payments/currency_converter.html +0 -382
- django_cfg/apps/payments/admin_interface/old/payments/payment_dashboard.html +0 -309
- django_cfg/apps/payments/admin_interface/old/payments/payment_form.html +0 -303
- django_cfg/apps/payments/admin_interface/old/payments/payment_list.html +0 -382
- django_cfg/apps/payments/admin_interface/old/payments/payment_status.html +0 -500
- django_cfg/apps/payments/admin_interface/old/payments/webhook_dashboard.html +0 -518
- django_cfg/apps/payments/admin_interface/old/static/payments/css/components.css +0 -619
- django_cfg/apps/payments/admin_interface/old/static/payments/css/dashboard.css +0 -188
- django_cfg/apps/payments/admin_interface/old/static/payments/js/components.js +0 -545
- django_cfg/apps/payments/admin_interface/old/static/payments/js/ngrok-status.js +0 -163
- django_cfg/apps/payments/admin_interface/old/static/payments/js/utils.js +0 -412
- django_cfg/apps/payments/config/constance/__init__.py +0 -22
- django_cfg/apps/payments/config/constance/config_service.py +0 -123
- django_cfg/apps/payments/config/constance/fields.py +0 -69
- django_cfg/apps/payments/config/constance/settings.py +0 -160
- django_cfg/apps/payments/services/providers/nowpayments.py +0 -478
- django_cfg/apps/tasks/admin.py +0 -320
- django_cfg/apps/tasks/static/tasks/js/dashboard.js +0 -614
- django_cfg/apps/tasks/static/tasks/js/modals.js +0 -452
- django_cfg/apps/tasks/static/tasks/js/notifications.js +0 -144
- django_cfg/apps/tasks/static/tasks/js/task-monitor.js +0 -454
- django_cfg/apps/tasks/static/tasks/js/theme.js +0 -77
- django_cfg/apps/tasks/templates/tasks/base.html +0 -96
- django_cfg/apps/tasks/templates/tasks/components/info_cards.html +0 -85
- django_cfg/apps/tasks/templates/tasks/components/overview_tab.html +0 -22
- django_cfg/apps/tasks/templates/tasks/components/queues_tab.html +0 -19
- django_cfg/apps/tasks/templates/tasks/components/task_details_modal.html +0 -103
- django_cfg/apps/tasks/templates/tasks/components/tasks_tab.html +0 -32
- django_cfg/apps/tasks/templates/tasks/components/workers_tab.html +0 -29
- django_cfg/apps/tasks/templates/tasks/dashboard.html +0 -29
- django_cfg/apps/tasks/views.py +0 -461
- django_cfg/management/commands/auto_generate.py +0 -486
- django_cfg/middleware/static_nocache.py +0 -55
- django_cfg/modules/django_currency/clients/yahoo_client.py +0 -157
- /django_cfg/modules/{django_unfold → django_admin}/icons/README.md +0 -0
- /django_cfg/modules/{django_unfold → django_admin}/icons/__init__.py +0 -0
- /django_cfg/modules/{django_unfold → django_admin}/icons/constants.py +0 -0
- /django_cfg/modules/{django_unfold → django_admin}/icons/generate_icons.py +0 -0
- {django_cfg-1.3.7.dist-info → django_cfg-1.3.11.dist-info}/WHEEL +0 -0
- {django_cfg-1.3.7.dist-info → django_cfg-1.3.11.dist-info}/entry_points.txt +0 -0
- {django_cfg-1.3.7.dist-info → django_cfg-1.3.11.dist-info}/licenses/LICENSE +0 -0
@@ -1,412 +0,0 @@
|
|
1
|
-
/**
|
2
|
-
* Universal Payment System v2.0 - Utility Functions
|
3
|
-
*
|
4
|
-
* Global utilities for the payment system interface.
|
5
|
-
*/
|
6
|
-
|
7
|
-
// Global PaymentSystem namespace
|
8
|
-
window.PaymentSystem = window.PaymentSystem || {};
|
9
|
-
|
10
|
-
/**
|
11
|
-
* Utility functions
|
12
|
-
*/
|
13
|
-
PaymentSystem.Utils = {
|
14
|
-
/**
|
15
|
-
* Copy text to clipboard with Material Icons feedback
|
16
|
-
* @param {string} text - Text to copy
|
17
|
-
* @param {string} successMessage - Success message to show
|
18
|
-
*/
|
19
|
-
copyToClipboard: function(text, successMessage = 'Copied to clipboard!') {
|
20
|
-
if (navigator.clipboard && window.isSecureContext) {
|
21
|
-
navigator.clipboard.writeText(text).then(() => {
|
22
|
-
this.showNotification(successMessage, 'success', 'content_copy');
|
23
|
-
}).catch(() => {
|
24
|
-
this.fallbackCopyToClipboard(text, successMessage);
|
25
|
-
});
|
26
|
-
} else {
|
27
|
-
this.fallbackCopyToClipboard(text, successMessage);
|
28
|
-
}
|
29
|
-
},
|
30
|
-
|
31
|
-
/**
|
32
|
-
* Fallback copy method for older browsers
|
33
|
-
* @param {string} text - Text to copy
|
34
|
-
* @param {string} successMessage - Success message to show
|
35
|
-
*/
|
36
|
-
fallbackCopyToClipboard: function(text, successMessage) {
|
37
|
-
const textArea = document.createElement('textarea');
|
38
|
-
textArea.value = text;
|
39
|
-
textArea.style.position = 'fixed';
|
40
|
-
textArea.style.left = '-999999px';
|
41
|
-
textArea.style.top = '-999999px';
|
42
|
-
document.body.appendChild(textArea);
|
43
|
-
textArea.focus();
|
44
|
-
textArea.select();
|
45
|
-
|
46
|
-
try {
|
47
|
-
document.execCommand('copy');
|
48
|
-
this.showNotification(successMessage, 'success', 'content_copy');
|
49
|
-
} catch (err) {
|
50
|
-
this.showNotification('Failed to copy to clipboard', 'error', 'error');
|
51
|
-
}
|
52
|
-
|
53
|
-
document.body.removeChild(textArea);
|
54
|
-
},
|
55
|
-
|
56
|
-
/**
|
57
|
-
* Show notification with Material Icons
|
58
|
-
* @param {string} message - Notification message
|
59
|
-
* @param {string} type - Notification type (success, error, warning, info)
|
60
|
-
* @param {string} icon - Material icon name
|
61
|
-
* @param {number} duration - Duration in milliseconds
|
62
|
-
*/
|
63
|
-
showNotification: function(message, type = 'info', icon = null, duration = 5000) {
|
64
|
-
// Remove existing notifications of the same type
|
65
|
-
const existingNotifications = document.querySelectorAll(`.notification.${type}`);
|
66
|
-
existingNotifications.forEach(notification => {
|
67
|
-
notification.remove();
|
68
|
-
});
|
69
|
-
|
70
|
-
const notification = document.createElement('div');
|
71
|
-
notification.className = `notification ${type} slide-in`;
|
72
|
-
|
73
|
-
// Default icons for each type
|
74
|
-
const defaultIcons = {
|
75
|
-
success: 'check_circle',
|
76
|
-
error: 'error',
|
77
|
-
warning: 'warning',
|
78
|
-
info: 'info'
|
79
|
-
};
|
80
|
-
|
81
|
-
const iconName = icon || defaultIcons[type] || 'info';
|
82
|
-
|
83
|
-
notification.innerHTML = `
|
84
|
-
<span class="material-icons-outlined">${iconName}</span>
|
85
|
-
<span class="flex-1">${message}</span>
|
86
|
-
<button class="close-btn" onclick="this.parentElement.remove()">
|
87
|
-
<span class="material-icons-outlined">close</span>
|
88
|
-
</button>
|
89
|
-
`;
|
90
|
-
|
91
|
-
document.body.appendChild(notification);
|
92
|
-
|
93
|
-
// Auto-remove after duration
|
94
|
-
setTimeout(() => {
|
95
|
-
if (notification.parentElement) {
|
96
|
-
notification.classList.remove('slide-in');
|
97
|
-
notification.classList.add('slide-out');
|
98
|
-
setTimeout(() => {
|
99
|
-
notification.remove();
|
100
|
-
}, 300);
|
101
|
-
}
|
102
|
-
}, duration);
|
103
|
-
},
|
104
|
-
|
105
|
-
/**
|
106
|
-
* Format currency with proper locale
|
107
|
-
* @param {number} amount - Amount to format
|
108
|
-
* @param {string} currency - Currency code
|
109
|
-
* @param {string} locale - Locale for formatting
|
110
|
-
* @returns {string} Formatted currency string
|
111
|
-
*/
|
112
|
-
formatCurrency: function(amount, currency = 'USD', locale = 'en-US') {
|
113
|
-
try {
|
114
|
-
return new Intl.NumberFormat(locale, {
|
115
|
-
style: 'currency',
|
116
|
-
currency: currency,
|
117
|
-
minimumFractionDigits: currency === 'USD' ? 2 : 8
|
118
|
-
}).format(amount);
|
119
|
-
} catch (error) {
|
120
|
-
return `${amount} ${currency}`;
|
121
|
-
}
|
122
|
-
},
|
123
|
-
|
124
|
-
/**
|
125
|
-
* Format date with relative time
|
126
|
-
* @param {string|Date} dateString - Date to format
|
127
|
-
* @param {boolean} relative - Whether to show relative time
|
128
|
-
* @returns {string} Formatted date string
|
129
|
-
*/
|
130
|
-
formatDate: function(dateString, relative = false) {
|
131
|
-
const date = new Date(dateString);
|
132
|
-
|
133
|
-
if (relative) {
|
134
|
-
const now = new Date();
|
135
|
-
const diffInSeconds = Math.floor((now - date) / 1000);
|
136
|
-
|
137
|
-
if (diffInSeconds < 60) return 'Just now';
|
138
|
-
if (diffInSeconds < 3600) return `${Math.floor(diffInSeconds / 60)} minutes ago`;
|
139
|
-
if (diffInSeconds < 86400) return `${Math.floor(diffInSeconds / 3600)} hours ago`;
|
140
|
-
if (diffInSeconds < 2592000) return `${Math.floor(diffInSeconds / 86400)} days ago`;
|
141
|
-
}
|
142
|
-
|
143
|
-
return date.toLocaleString();
|
144
|
-
},
|
145
|
-
|
146
|
-
/**
|
147
|
-
* Debounce function calls
|
148
|
-
* @param {Function} func - Function to debounce
|
149
|
-
* @param {number} wait - Wait time in milliseconds
|
150
|
-
* @param {boolean} immediate - Whether to execute immediately
|
151
|
-
* @returns {Function} Debounced function
|
152
|
-
*/
|
153
|
-
debounce: function(func, wait, immediate = false) {
|
154
|
-
let timeout;
|
155
|
-
return function executedFunction(...args) {
|
156
|
-
const later = () => {
|
157
|
-
timeout = null;
|
158
|
-
if (!immediate) func.apply(this, args);
|
159
|
-
};
|
160
|
-
const callNow = immediate && !timeout;
|
161
|
-
clearTimeout(timeout);
|
162
|
-
timeout = setTimeout(later, wait);
|
163
|
-
if (callNow) func.apply(this, args);
|
164
|
-
};
|
165
|
-
},
|
166
|
-
|
167
|
-
/**
|
168
|
-
* Throttle function calls
|
169
|
-
* @param {Function} func - Function to throttle
|
170
|
-
* @param {number} limit - Time limit in milliseconds
|
171
|
-
* @returns {Function} Throttled function
|
172
|
-
*/
|
173
|
-
throttle: function(func, limit) {
|
174
|
-
let inThrottle;
|
175
|
-
return function(...args) {
|
176
|
-
if (!inThrottle) {
|
177
|
-
func.apply(this, args);
|
178
|
-
inThrottle = true;
|
179
|
-
setTimeout(() => inThrottle = false, limit);
|
180
|
-
}
|
181
|
-
};
|
182
|
-
},
|
183
|
-
|
184
|
-
/**
|
185
|
-
* Generate random ID
|
186
|
-
* @param {number} length - Length of ID
|
187
|
-
* @returns {string} Random ID
|
188
|
-
*/
|
189
|
-
generateId: function(length = 8) {
|
190
|
-
return Math.random().toString(36).substring(2, length + 2);
|
191
|
-
},
|
192
|
-
|
193
|
-
/**
|
194
|
-
* Validate email address
|
195
|
-
* @param {string} email - Email to validate
|
196
|
-
* @returns {boolean} Whether email is valid
|
197
|
-
*/
|
198
|
-
isValidEmail: function(email) {
|
199
|
-
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
200
|
-
return emailRegex.test(email);
|
201
|
-
},
|
202
|
-
|
203
|
-
/**
|
204
|
-
* Validate URL
|
205
|
-
* @param {string} url - URL to validate
|
206
|
-
* @returns {boolean} Whether URL is valid
|
207
|
-
*/
|
208
|
-
isValidUrl: function(url) {
|
209
|
-
try {
|
210
|
-
new URL(url);
|
211
|
-
return true;
|
212
|
-
} catch {
|
213
|
-
return false;
|
214
|
-
}
|
215
|
-
},
|
216
|
-
|
217
|
-
/**
|
218
|
-
* Get status badge class
|
219
|
-
* @param {string} status - Status value
|
220
|
-
* @returns {string} CSS class for status badge
|
221
|
-
*/
|
222
|
-
getStatusBadgeClass: function(status) {
|
223
|
-
const statusMap = {
|
224
|
-
'completed': 'success',
|
225
|
-
'success': 'success',
|
226
|
-
'active': 'success',
|
227
|
-
'failed': 'error',
|
228
|
-
'error': 'error',
|
229
|
-
'cancelled': 'error',
|
230
|
-
'pending': 'warning',
|
231
|
-
'processing': 'info',
|
232
|
-
'inactive': 'error'
|
233
|
-
};
|
234
|
-
|
235
|
-
return `status-badge ${statusMap[status.toLowerCase()] || 'info'}`;
|
236
|
-
},
|
237
|
-
|
238
|
-
/**
|
239
|
-
* Get Material Icon for status
|
240
|
-
* @param {string} status - Status value
|
241
|
-
* @returns {string} Material icon name
|
242
|
-
*/
|
243
|
-
getStatusIcon: function(status) {
|
244
|
-
const iconMap = {
|
245
|
-
'completed': 'check_circle',
|
246
|
-
'success': 'check_circle',
|
247
|
-
'active': 'check_circle',
|
248
|
-
'failed': 'error',
|
249
|
-
'error': 'error',
|
250
|
-
'cancelled': 'cancel',
|
251
|
-
'pending': 'schedule',
|
252
|
-
'processing': 'sync',
|
253
|
-
'inactive': 'radio_button_unchecked'
|
254
|
-
};
|
255
|
-
|
256
|
-
return iconMap[status.toLowerCase()] || 'help';
|
257
|
-
},
|
258
|
-
|
259
|
-
/**
|
260
|
-
* Format file size
|
261
|
-
* @param {number} bytes - File size in bytes
|
262
|
-
* @returns {string} Formatted file size
|
263
|
-
*/
|
264
|
-
formatFileSize: function(bytes) {
|
265
|
-
if (bytes === 0) return '0 Bytes';
|
266
|
-
|
267
|
-
const k = 1024;
|
268
|
-
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
|
269
|
-
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
270
|
-
|
271
|
-
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
272
|
-
},
|
273
|
-
|
274
|
-
/**
|
275
|
-
* Scroll to element smoothly
|
276
|
-
* @param {string|Element} element - Element or selector
|
277
|
-
* @param {number} offset - Offset from top
|
278
|
-
*/
|
279
|
-
scrollToElement: function(element, offset = 0) {
|
280
|
-
const target = typeof element === 'string' ? document.querySelector(element) : element;
|
281
|
-
if (target) {
|
282
|
-
const targetPosition = target.offsetTop - offset;
|
283
|
-
window.scrollTo({
|
284
|
-
top: targetPosition,
|
285
|
-
behavior: 'smooth'
|
286
|
-
});
|
287
|
-
}
|
288
|
-
},
|
289
|
-
|
290
|
-
/**
|
291
|
-
* Check if element is in viewport
|
292
|
-
* @param {Element} element - Element to check
|
293
|
-
* @returns {boolean} Whether element is in viewport
|
294
|
-
*/
|
295
|
-
isInViewport: function(element) {
|
296
|
-
const rect = element.getBoundingClientRect();
|
297
|
-
return (
|
298
|
-
rect.top >= 0 &&
|
299
|
-
rect.left >= 0 &&
|
300
|
-
rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
|
301
|
-
rect.right <= (window.innerWidth || document.documentElement.clientWidth)
|
302
|
-
);
|
303
|
-
}
|
304
|
-
};
|
305
|
-
|
306
|
-
/**
|
307
|
-
* Auto-refresh functionality
|
308
|
-
*/
|
309
|
-
PaymentSystem.AutoRefresh = {
|
310
|
-
interval: null,
|
311
|
-
|
312
|
-
/**
|
313
|
-
* Setup auto-refresh for elements with data-auto-refresh attribute
|
314
|
-
* @param {number} intervalMs - Refresh interval in milliseconds
|
315
|
-
*/
|
316
|
-
setup: function(intervalMs = 30000) {
|
317
|
-
if (document.querySelector('[data-auto-refresh]')) {
|
318
|
-
this.interval = setInterval(() => {
|
319
|
-
this.refresh();
|
320
|
-
}, intervalMs);
|
321
|
-
}
|
322
|
-
},
|
323
|
-
|
324
|
-
/**
|
325
|
-
* Refresh the page or specific elements
|
326
|
-
*/
|
327
|
-
refresh: function() {
|
328
|
-
const elements = document.querySelectorAll('[data-auto-refresh]');
|
329
|
-
if (elements.length > 0) {
|
330
|
-
elements.forEach(element => {
|
331
|
-
const refreshType = element.getAttribute('data-auto-refresh');
|
332
|
-
if (refreshType === 'page') {
|
333
|
-
location.reload();
|
334
|
-
} else if (refreshType === 'ajax' && element.hasAttribute('data-refresh-url')) {
|
335
|
-
this.refreshElement(element);
|
336
|
-
}
|
337
|
-
});
|
338
|
-
}
|
339
|
-
},
|
340
|
-
|
341
|
-
/**
|
342
|
-
* Refresh specific element via AJAX
|
343
|
-
* @param {Element} element - Element to refresh
|
344
|
-
*/
|
345
|
-
refreshElement: function(element) {
|
346
|
-
const url = element.getAttribute('data-refresh-url');
|
347
|
-
if (url) {
|
348
|
-
fetch(url)
|
349
|
-
.then(response => response.text())
|
350
|
-
.then(html => {
|
351
|
-
element.innerHTML = html;
|
352
|
-
})
|
353
|
-
.catch(error => {
|
354
|
-
console.error('Auto-refresh failed:', error);
|
355
|
-
});
|
356
|
-
}
|
357
|
-
},
|
358
|
-
|
359
|
-
/**
|
360
|
-
* Stop auto-refresh
|
361
|
-
*/
|
362
|
-
stop: function() {
|
363
|
-
if (this.interval) {
|
364
|
-
clearInterval(this.interval);
|
365
|
-
this.interval = null;
|
366
|
-
}
|
367
|
-
}
|
368
|
-
};
|
369
|
-
|
370
|
-
/**
|
371
|
-
* Initialize utilities on page load
|
372
|
-
*/
|
373
|
-
document.addEventListener('DOMContentLoaded', function() {
|
374
|
-
// Setup auto-refresh if enabled
|
375
|
-
PaymentSystem.AutoRefresh.setup();
|
376
|
-
|
377
|
-
// Add global keyboard shortcuts
|
378
|
-
document.addEventListener('keydown', function(e) {
|
379
|
-
// Ctrl/Cmd + K for search (if search exists)
|
380
|
-
if ((e.ctrlKey || e.metaKey) && e.key === 'k') {
|
381
|
-
const searchInput = document.querySelector('[data-search]');
|
382
|
-
if (searchInput) {
|
383
|
-
e.preventDefault();
|
384
|
-
searchInput.focus();
|
385
|
-
}
|
386
|
-
}
|
387
|
-
|
388
|
-
// Escape to close modals
|
389
|
-
if (e.key === 'Escape') {
|
390
|
-
const modals = document.querySelectorAll('.modal-overlay');
|
391
|
-
modals.forEach(modal => {
|
392
|
-
if (modal.style.display !== 'none') {
|
393
|
-
modal.style.display = 'none';
|
394
|
-
}
|
395
|
-
});
|
396
|
-
}
|
397
|
-
});
|
398
|
-
|
399
|
-
// Add click-to-copy functionality for elements with data-copy attribute
|
400
|
-
document.addEventListener('click', function(e) {
|
401
|
-
const copyElement = e.target.closest('[data-copy]');
|
402
|
-
if (copyElement) {
|
403
|
-
const textToCopy = copyElement.getAttribute('data-copy') || copyElement.textContent;
|
404
|
-
PaymentSystem.Utils.copyToClipboard(textToCopy);
|
405
|
-
}
|
406
|
-
});
|
407
|
-
});
|
408
|
-
|
409
|
-
// Export for module systems
|
410
|
-
if (typeof module !== 'undefined' && module.exports) {
|
411
|
-
module.exports = PaymentSystem;
|
412
|
-
}
|
@@ -1,22 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
Constance configuration for Universal Payment System v2.0.
|
3
|
-
|
4
|
-
Centralized configuration for dynamic settings that can be changed at runtime
|
5
|
-
through Django admin interface.
|
6
|
-
|
7
|
-
This module provides:
|
8
|
-
- Field definitions for Constance
|
9
|
-
- Settings validation and defaults
|
10
|
-
- Integration with django-cfg PaymentsConfig
|
11
|
-
"""
|
12
|
-
|
13
|
-
from .fields import get_django_cfg_payments_constance_fields
|
14
|
-
from .settings import PaymentConstanceSettings
|
15
|
-
from .config_service import PaymentConfigService, get_payment_config_service
|
16
|
-
|
17
|
-
__all__ = [
|
18
|
-
'get_django_cfg_payments_constance_fields',
|
19
|
-
'PaymentConstanceSettings',
|
20
|
-
'PaymentConfigService',
|
21
|
-
'get_payment_config_service',
|
22
|
-
]
|
@@ -1,123 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
Configuration service for payments using Constance.
|
3
|
-
|
4
|
-
Provides easy access to Constance settings with type safety and caching.
|
5
|
-
"""
|
6
|
-
|
7
|
-
from typing import Dict, Any, Optional
|
8
|
-
from django_cfg.modules.django_logger import get_logger
|
9
|
-
from .settings import PaymentConstanceSettings, get_payment_settings
|
10
|
-
|
11
|
-
logger = get_logger(__name__)
|
12
|
-
|
13
|
-
|
14
|
-
class PaymentConfigService:
|
15
|
-
"""
|
16
|
-
Service for accessing payment configuration from Constance.
|
17
|
-
|
18
|
-
Provides type-safe access to dynamic settings with caching and validation.
|
19
|
-
"""
|
20
|
-
|
21
|
-
def __init__(self):
|
22
|
-
"""Initialize config service."""
|
23
|
-
self._cached_settings: Optional[PaymentConstanceSettings] = None
|
24
|
-
self._cache_timeout = 60 # Cache for 1 minute
|
25
|
-
self._last_refresh = 0
|
26
|
-
|
27
|
-
def get_settings(self, force_refresh: bool = False) -> PaymentConstanceSettings:
|
28
|
-
"""
|
29
|
-
Get current payment settings from Constance.
|
30
|
-
|
31
|
-
Args:
|
32
|
-
force_refresh: Force refresh from Constance (ignore cache)
|
33
|
-
|
34
|
-
Returns:
|
35
|
-
PaymentConstanceSettings instance
|
36
|
-
"""
|
37
|
-
import time
|
38
|
-
|
39
|
-
current_time = time.time()
|
40
|
-
|
41
|
-
if (force_refresh or
|
42
|
-
self._cached_settings is None or
|
43
|
-
(current_time - self._last_refresh) > self._cache_timeout):
|
44
|
-
|
45
|
-
try:
|
46
|
-
self._cached_settings = get_payment_settings()
|
47
|
-
self._last_refresh = current_time
|
48
|
-
logger.debug("Refreshed payment settings from Constance")
|
49
|
-
except Exception as e:
|
50
|
-
logger.error(f"Failed to refresh payment settings: {e}")
|
51
|
-
if self._cached_settings is None:
|
52
|
-
# Fallback to defaults if no cache
|
53
|
-
self._cached_settings = PaymentConstanceSettings()
|
54
|
-
|
55
|
-
return self._cached_settings
|
56
|
-
|
57
|
-
def is_enabled(self) -> bool:
|
58
|
-
"""Check if payments system is enabled."""
|
59
|
-
return self.get_settings().enabled
|
60
|
-
|
61
|
-
def is_middleware_enabled(self) -> bool:
|
62
|
-
"""Check if payments middleware is enabled."""
|
63
|
-
return self.get_settings().middleware_enabled
|
64
|
-
|
65
|
-
def is_rate_limiting_enabled(self) -> bool:
|
66
|
-
"""Check if rate limiting is enabled."""
|
67
|
-
return self.get_settings().rate_limiting_enabled
|
68
|
-
|
69
|
-
def is_usage_tracking_enabled(self) -> bool:
|
70
|
-
"""Check if usage tracking is enabled."""
|
71
|
-
return self.get_settings().usage_tracking_enabled
|
72
|
-
|
73
|
-
def get_rate_limits(self) -> Dict[str, int]:
|
74
|
-
"""Get rate limits configuration."""
|
75
|
-
return self.get_settings().get_rate_limits()
|
76
|
-
|
77
|
-
def get_cache_timeouts(self) -> Dict[str, int]:
|
78
|
-
"""Get cache timeouts configuration."""
|
79
|
-
return self.get_settings().get_cache_timeouts()
|
80
|
-
|
81
|
-
def get_provider_config(self, provider: str) -> Dict[str, Any]:
|
82
|
-
"""Get provider-specific configuration."""
|
83
|
-
return self.get_settings().get_provider_config(provider)
|
84
|
-
|
85
|
-
def get_nowpayments_config(self) -> Dict[str, Any]:
|
86
|
-
"""Get NowPayments configuration."""
|
87
|
-
return self.get_provider_config('nowpayments')
|
88
|
-
|
89
|
-
def refresh_configuration(self):
|
90
|
-
"""Force refresh configuration from Constance."""
|
91
|
-
self.get_settings(force_refresh=True)
|
92
|
-
|
93
|
-
def get_all_provider_configs(self) -> Dict[str, Dict[str, Any]]:
|
94
|
-
"""Get all provider configurations."""
|
95
|
-
return {
|
96
|
-
'nowpayments': self.get_nowpayments_config(),
|
97
|
-
}
|
98
|
-
|
99
|
-
def get_constance_settings(self) -> PaymentConstanceSettings:
|
100
|
-
"""
|
101
|
-
Alias for get_settings() for backward compatibility.
|
102
|
-
|
103
|
-
Returns:
|
104
|
-
PaymentConstanceSettings instance
|
105
|
-
"""
|
106
|
-
return self.get_settings()
|
107
|
-
|
108
|
-
|
109
|
-
# Global instance
|
110
|
-
_config_service: Optional[PaymentConfigService] = None
|
111
|
-
|
112
|
-
|
113
|
-
def get_payment_config_service() -> PaymentConfigService:
|
114
|
-
"""
|
115
|
-
Get global payment config service instance.
|
116
|
-
|
117
|
-
Returns:
|
118
|
-
PaymentConfigService instance
|
119
|
-
"""
|
120
|
-
global _config_service
|
121
|
-
if _config_service is None:
|
122
|
-
_config_service = PaymentConfigService()
|
123
|
-
return _config_service
|
@@ -1,69 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
Constance fields configuration for Payments app.
|
3
|
-
|
4
|
-
This module defines ONLY dynamic settings that need to be changed at runtime.
|
5
|
-
Static configuration is handled by PaymentsConfig Pydantic model.
|
6
|
-
|
7
|
-
Note: This file MUST NOT import Django models or anything that requires
|
8
|
-
Django apps to be loaded, as it's imported during settings generation.
|
9
|
-
"""
|
10
|
-
|
11
|
-
from typing import List
|
12
|
-
from django_cfg.models.constance import ConstanceField
|
13
|
-
|
14
|
-
|
15
|
-
def get_django_cfg_payments_constance_fields() -> List[ConstanceField]:
|
16
|
-
"""
|
17
|
-
Get Constance field definitions for Payments app.
|
18
|
-
|
19
|
-
Only includes settings that need runtime configuration:
|
20
|
-
- API keys and secrets (change per environment)
|
21
|
-
- Rate limits (admins need to adjust)
|
22
|
-
- Usage tracking preferences
|
23
|
-
- Currency update intervals
|
24
|
-
|
25
|
-
Static settings (enabled flags, middleware, cache timeouts) are handled
|
26
|
-
by PaymentsConfig Pydantic model and auto-detection.
|
27
|
-
|
28
|
-
Returns:
|
29
|
-
List of ConstanceField objects for runtime-configurable settings
|
30
|
-
"""
|
31
|
-
# Import PaymentsConfigManager for consistent config access
|
32
|
-
from ..django_cfg_integration import PaymentsConfigManager
|
33
|
-
|
34
|
-
# Get default values from initialized Pydantic config using PaymentsConfigManager
|
35
|
-
default_config = PaymentsConfigManager.get_payments_config()
|
36
|
-
|
37
|
-
return [
|
38
|
-
# === 📊 Usage Tracking ===
|
39
|
-
ConstanceField(
|
40
|
-
name='PAYMENTS_TRACK_ANONYMOUS_USAGE',
|
41
|
-
default=default_config.track_anonymous_usage,
|
42
|
-
help_text="📊 Usage Tracking: Track usage for anonymous users (privacy setting)",
|
43
|
-
field_type='bool',
|
44
|
-
group='Payments'
|
45
|
-
),
|
46
|
-
|
47
|
-
# === 🔌 NowPayments Provider ===
|
48
|
-
ConstanceField(
|
49
|
-
name='PAYMENTS_NOWPAYMENTS_API_KEY',
|
50
|
-
default='',
|
51
|
-
help_text="🔌 NowPayments: API key for production (sensitive)",
|
52
|
-
field_type='str',
|
53
|
-
group='Payments'
|
54
|
-
),
|
55
|
-
ConstanceField(
|
56
|
-
name='PAYMENTS_NOWPAYMENTS_IPN_SECRET',
|
57
|
-
default='',
|
58
|
-
help_text="🔌 NowPayments: IPN secret for webhook verification (sensitive)",
|
59
|
-
field_type='str',
|
60
|
-
group='Payments'
|
61
|
-
),
|
62
|
-
ConstanceField(
|
63
|
-
name='PAYMENTS_NOWPAYMENTS_SANDBOX_MODE',
|
64
|
-
default=True,
|
65
|
-
help_text="🔌 NowPayments: Use sandbox mode for testing",
|
66
|
-
field_type='bool',
|
67
|
-
group='Payments'
|
68
|
-
),
|
69
|
-
]
|