django-cfg 1.3.3__py3-none-any.whl → 1.3.7__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 (100) hide show
  1. django_cfg/__init__.py +1 -1
  2. django_cfg/apps/payments/admin_interface/old/payments/base.html +175 -0
  3. django_cfg/apps/payments/admin_interface/old/payments/components/dev_tool_card.html +125 -0
  4. django_cfg/apps/payments/admin_interface/old/payments/components/ngrok_status_card.html +113 -0
  5. django_cfg/apps/payments/admin_interface/old/payments/components/status_card.html +35 -0
  6. django_cfg/apps/payments/admin_interface/old/payments/payment_dashboard.html +309 -0
  7. django_cfg/apps/payments/admin_interface/old/payments/payment_form.html +303 -0
  8. django_cfg/apps/payments/admin_interface/old/payments/payment_list.html +382 -0
  9. django_cfg/apps/payments/admin_interface/old/payments/webhook_dashboard.html +518 -0
  10. django_cfg/apps/payments/{static → admin_interface/old/static}/payments/css/components.css +248 -9
  11. django_cfg/apps/payments/admin_interface/old/static/payments/js/ngrok-status.js +163 -0
  12. django_cfg/apps/payments/admin_interface/serializers/__init__.py +39 -0
  13. django_cfg/apps/payments/admin_interface/serializers/payment_serializers.py +149 -0
  14. django_cfg/apps/payments/admin_interface/serializers/webhook_serializers.py +114 -0
  15. django_cfg/apps/payments/admin_interface/templates/payments/base.html +55 -90
  16. django_cfg/apps/payments/admin_interface/templates/payments/components/dialog.html +81 -0
  17. django_cfg/apps/payments/admin_interface/templates/payments/components/ngrok_help_dialog.html +112 -0
  18. django_cfg/apps/payments/admin_interface/templates/payments/components/ngrok_status.html +175 -0
  19. django_cfg/apps/payments/admin_interface/templates/payments/components/status_card.html +21 -17
  20. django_cfg/apps/payments/admin_interface/templates/payments/payment_dashboard.html +123 -250
  21. django_cfg/apps/payments/admin_interface/templates/payments/payment_form.html +170 -269
  22. django_cfg/apps/payments/admin_interface/templates/payments/payment_list.html +152 -355
  23. django_cfg/apps/payments/admin_interface/templates/payments/webhook_dashboard.html +202 -551
  24. django_cfg/apps/payments/admin_interface/views/__init__.py +25 -14
  25. django_cfg/apps/payments/admin_interface/views/api/__init__.py +20 -0
  26. django_cfg/apps/payments/admin_interface/views/api/payments.py +191 -0
  27. django_cfg/apps/payments/admin_interface/views/api/stats.py +206 -0
  28. django_cfg/apps/payments/admin_interface/views/api/users.py +60 -0
  29. django_cfg/apps/payments/admin_interface/views/api/webhook_admin.py +257 -0
  30. django_cfg/apps/payments/admin_interface/views/api/webhook_public.py +70 -0
  31. django_cfg/apps/payments/admin_interface/views/base.py +114 -0
  32. django_cfg/apps/payments/admin_interface/views/dashboard.py +60 -0
  33. django_cfg/apps/payments/admin_interface/views/forms.py +94 -0
  34. django_cfg/apps/payments/config/helpers.py +2 -2
  35. django_cfg/apps/payments/management/commands/cleanup_expired_data.py +16 -6
  36. django_cfg/apps/payments/management/commands/currency_stats.py +72 -5
  37. django_cfg/apps/payments/management/commands/manage_currencies.py +9 -20
  38. django_cfg/apps/payments/management/commands/manage_providers.py +5 -5
  39. django_cfg/apps/payments/middleware/api_access.py +35 -34
  40. django_cfg/apps/payments/migrations/0001_initial.py +1 -1
  41. django_cfg/apps/payments/models/managers/api_key_managers.py +4 -0
  42. django_cfg/apps/payments/models/managers/payment_managers.py +5 -0
  43. django_cfg/apps/payments/models/subscriptions.py +0 -24
  44. django_cfg/apps/payments/services/cache/__init__.py +1 -1
  45. django_cfg/apps/payments/services/core/balance_service.py +13 -2
  46. django_cfg/apps/payments/services/integrations/ngrok_service.py +3 -3
  47. django_cfg/apps/payments/services/providers/registry.py +20 -0
  48. django_cfg/apps/payments/signals/balance_signals.py +7 -4
  49. django_cfg/apps/payments/static/payments/js/api-client.js +385 -0
  50. django_cfg/apps/payments/static/payments/js/ngrok-status.js +58 -0
  51. django_cfg/apps/payments/static/payments/js/payment-dashboard.js +50 -0
  52. django_cfg/apps/payments/static/payments/js/payment-form.js +175 -0
  53. django_cfg/apps/payments/static/payments/js/payment-list.js +95 -0
  54. django_cfg/apps/payments/static/payments/js/webhook-dashboard.js +154 -0
  55. django_cfg/apps/payments/urls.py +4 -0
  56. django_cfg/apps/payments/urls_admin.py +37 -18
  57. django_cfg/apps/payments/views/api/api_keys.py +14 -0
  58. django_cfg/apps/payments/views/api/base.py +1 -0
  59. django_cfg/apps/payments/views/api/currencies.py +2 -2
  60. django_cfg/apps/payments/views/api/payments.py +11 -5
  61. django_cfg/apps/payments/views/api/subscriptions.py +36 -31
  62. django_cfg/apps/payments/views/overview/__init__.py +40 -0
  63. django_cfg/apps/payments/views/overview/serializers.py +205 -0
  64. django_cfg/apps/payments/views/overview/services.py +439 -0
  65. django_cfg/apps/payments/views/overview/urls.py +27 -0
  66. django_cfg/apps/payments/views/overview/views.py +231 -0
  67. django_cfg/apps/payments/views/serializers/api_keys.py +20 -6
  68. django_cfg/apps/payments/views/serializers/balances.py +5 -8
  69. django_cfg/apps/payments/views/serializers/currencies.py +2 -6
  70. django_cfg/apps/payments/views/serializers/payments.py +37 -32
  71. django_cfg/apps/payments/views/serializers/subscriptions.py +4 -26
  72. django_cfg/core/config.py +25 -15
  73. django_cfg/core/generation.py +12 -12
  74. django_cfg/core/integration/display/startup.py +1 -1
  75. django_cfg/core/validation.py +4 -4
  76. django_cfg/management/commands/show_config.py +2 -2
  77. django_cfg/management/commands/tree.py +1 -3
  78. django_cfg/middleware/__init__.py +2 -0
  79. django_cfg/middleware/static_nocache.py +55 -0
  80. django_cfg/models/payments.py +13 -15
  81. django_cfg/models/security.py +15 -0
  82. django_cfg/modules/django_ngrok.py +6 -0
  83. django_cfg/modules/django_unfold/dashboard.py +1 -3
  84. django_cfg/utils/smart_defaults.py +41 -1
  85. {django_cfg-1.3.3.dist-info → django_cfg-1.3.7.dist-info}/METADATA +1 -1
  86. {django_cfg-1.3.3.dist-info → django_cfg-1.3.7.dist-info}/RECORD +97 -64
  87. django_cfg/apps/payments/admin_interface/templates/payments/components/dev_tool_card.html +0 -38
  88. django_cfg/apps/payments/admin_interface/views/payment_views.py +0 -259
  89. django_cfg/apps/payments/admin_interface/views/webhook_dashboard.py +0 -37
  90. /django_cfg/apps/payments/admin_interface/{templates → old}/payments/components/loading_spinner.html +0 -0
  91. /django_cfg/apps/payments/admin_interface/{templates → old}/payments/components/notification.html +0 -0
  92. /django_cfg/apps/payments/admin_interface/{templates → old}/payments/components/provider_card.html +0 -0
  93. /django_cfg/apps/payments/admin_interface/{templates → old}/payments/currency_converter.html +0 -0
  94. /django_cfg/apps/payments/admin_interface/{templates → old}/payments/payment_status.html +0 -0
  95. /django_cfg/apps/payments/{static → admin_interface/old/static}/payments/css/dashboard.css +0 -0
  96. /django_cfg/apps/payments/{static → admin_interface/old/static}/payments/js/components.js +0 -0
  97. /django_cfg/apps/payments/{static → admin_interface/old/static}/payments/js/utils.js +0 -0
  98. {django_cfg-1.3.3.dist-info → django_cfg-1.3.7.dist-info}/WHEEL +0 -0
  99. {django_cfg-1.3.3.dist-info → django_cfg-1.3.7.dist-info}/entry_points.txt +0 -0
  100. {django_cfg-1.3.3.dist-info → django_cfg-1.3.7.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,114 @@
1
+ """
2
+ Webhook Serializers for Admin Interface.
3
+
4
+ DRF serializers for webhook management in admin dashboard.
5
+ """
6
+
7
+ from rest_framework import serializers
8
+ from datetime import datetime
9
+ from typing import Dict, Any
10
+
11
+
12
+ class WebhookEventSerializer(serializers.Serializer):
13
+ """
14
+ Serializer for individual webhook event.
15
+ """
16
+ id = serializers.IntegerField(read_only=True)
17
+ provider = serializers.CharField(max_length=50)
18
+ event_type = serializers.CharField(max_length=100)
19
+ status = serializers.ChoiceField(choices=[
20
+ ('success', 'Success'),
21
+ ('failed', 'Failed'),
22
+ ('pending', 'Pending'),
23
+ ('retry', 'Retry'),
24
+ ])
25
+ timestamp = serializers.DateTimeField()
26
+ payload_size = serializers.IntegerField(help_text="Size in bytes")
27
+ response_time = serializers.IntegerField(help_text="Response time in ms")
28
+ retry_count = serializers.IntegerField(default=0)
29
+ error_message = serializers.CharField(max_length=500, required=False, allow_blank=True)
30
+ payload_preview = serializers.CharField(max_length=200, required=False, allow_blank=True)
31
+ response_status_code = serializers.IntegerField(required=False)
32
+ webhook_url = serializers.URLField(required=False)
33
+
34
+
35
+ class WebhookEventListSerializer(serializers.Serializer):
36
+ """
37
+ Serializer for paginated webhook events list.
38
+ """
39
+ events = WebhookEventSerializer(many=True)
40
+ total = serializers.IntegerField()
41
+ page = serializers.IntegerField()
42
+ per_page = serializers.IntegerField()
43
+ has_next = serializers.BooleanField()
44
+ has_previous = serializers.BooleanField()
45
+
46
+
47
+ class WebhookProviderStatsSerializer(serializers.Serializer):
48
+ """
49
+ Serializer for provider-specific webhook statistics.
50
+ """
51
+ total = serializers.IntegerField()
52
+ successful = serializers.IntegerField()
53
+ failed = serializers.IntegerField()
54
+ pending = serializers.IntegerField(default=0)
55
+ success_rate = serializers.FloatField()
56
+
57
+
58
+ class WebhookStatsSerializer(serializers.Serializer):
59
+ """
60
+ Serializer for comprehensive webhook statistics.
61
+ """
62
+ total = serializers.IntegerField()
63
+ successful = serializers.IntegerField()
64
+ failed = serializers.IntegerField()
65
+ pending = serializers.IntegerField()
66
+ success_rate = serializers.FloatField()
67
+
68
+ # Provider breakdown
69
+ providers = serializers.DictField(
70
+ child=WebhookProviderStatsSerializer(),
71
+ help_text="Statistics by provider"
72
+ )
73
+
74
+ # Time-based stats
75
+ last_24h = serializers.DictField(
76
+ child=serializers.IntegerField(),
77
+ help_text="Events in last 24 hours"
78
+ )
79
+
80
+ # Performance metrics
81
+ avg_response_time = serializers.FloatField()
82
+ max_response_time = serializers.IntegerField()
83
+
84
+
85
+ class WebhookActionSerializer(serializers.Serializer):
86
+ """
87
+ Serializer for webhook actions (retry, clear, etc.).
88
+ """
89
+ action = serializers.ChoiceField(choices=[
90
+ ('retry', 'Retry'),
91
+ ('clear', 'Clear'),
92
+ ('retry_failed', 'Retry Failed'),
93
+ ])
94
+ event_ids = serializers.ListField(
95
+ child=serializers.IntegerField(),
96
+ required=False,
97
+ help_text="List of event IDs to process"
98
+ )
99
+
100
+
101
+ class WebhookActionResultSerializer(serializers.Serializer):
102
+ """
103
+ Serializer for webhook action results.
104
+ """
105
+ success = serializers.BooleanField()
106
+ message = serializers.CharField(max_length=200)
107
+ event_id = serializers.IntegerField(required=False)
108
+ processed_count = serializers.IntegerField(required=False)
109
+ failed_count = serializers.IntegerField(required=False)
110
+ errors = serializers.ListField(
111
+ child=serializers.CharField(),
112
+ required=False,
113
+ help_text="List of error messages if any"
114
+ )
@@ -4,113 +4,80 @@
4
4
  <head>
5
5
  <meta charset="UTF-8">
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
- <title>{% block title %}Universal Payment System v2.0{% endblock %}</title>
7
+ <title>{% block title %}Payment Admin - Django CFG{% endblock %}</title>
8
8
 
9
9
  <!-- Material Icons -->
10
- <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
11
10
  <link href="https://fonts.googleapis.com/icon?family=Material+Icons+Outlined" rel="stylesheet">
12
- <link href="https://fonts.googleapis.com/icon?family=Material+Icons+Round" rel="stylesheet">
13
11
 
14
12
  <!-- Tailwind CSS -->
15
13
  <script src="https://cdn.tailwindcss.com"></script>
16
14
 
17
- <!-- Alpine.js for interactivity -->
15
+ <!-- Alpine.js -->
18
16
  <script defer src="https://unpkg.com/alpinejs@3.x.x/dist/cdn.min.js"></script>
19
17
 
20
- <!-- Chart.js for statistics -->
21
- <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
22
-
23
- <!-- Custom CSS -->
24
- <link rel="stylesheet" href="{% static 'payments/css/dashboard.css' %}">
25
- <link rel="stylesheet" href="{% static 'payments/css/components.css' %}">
26
-
27
- <!-- Custom styles -->
28
18
  <style>
29
19
  [x-cloak] { display: none !important; }
30
-
31
- /* Custom scrollbar */
32
- .custom-scrollbar::-webkit-scrollbar {
33
- width: 6px;
34
- }
35
- .custom-scrollbar::-webkit-scrollbar-track {
36
- background: #f1f5f9;
37
- }
38
- .custom-scrollbar::-webkit-scrollbar-thumb {
39
- background: #cbd5e1;
40
- border-radius: 3px;
41
- }
42
- .custom-scrollbar::-webkit-scrollbar-thumb:hover {
43
- background: #94a3b8;
44
- }
45
-
46
- /* Dark mode scrollbar */
47
- .dark .custom-scrollbar::-webkit-scrollbar-track {
48
- background: #1e293b;
49
- }
50
- .dark .custom-scrollbar::-webkit-scrollbar-thumb {
51
- background: #475569;
52
- }
53
- .dark .custom-scrollbar::-webkit-scrollbar-thumb:hover {
54
- background: #64748b;
55
- }
56
20
  </style>
57
21
 
22
+ <!-- Dark mode initialization script to prevent flash -->
23
+ <script>
24
+ // Initialize dark mode before Alpine.js loads
25
+ if (localStorage.getItem('darkMode') === 'true' ||
26
+ (!localStorage.getItem('darkMode') && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
27
+ document.documentElement.classList.add('dark');
28
+ }
29
+ </script>
30
+
58
31
  {% block extra_head %}{% endblock %}
59
32
  </head>
60
- <body class="h-full bg-gray-50 dark:bg-gray-900" x-data="{ darkMode: localStorage.getItem('darkMode') === 'true' }"
61
- x-init="$watch('darkMode', val => localStorage.setItem('darkMode', val))"
62
- :class="{ 'dark': darkMode }">
33
+ <body class="h-full bg-gray-50 dark:bg-gray-900" x-data="{
34
+ darkMode: localStorage.getItem('darkMode') === 'true' ||
35
+ (!localStorage.getItem('darkMode') && window.matchMedia('(prefers-color-scheme: dark)').matches),
36
+ showNgrokHelp: false
37
+ }" x-init="$watch('darkMode', val => {
38
+ localStorage.setItem('darkMode', val);
39
+ document.documentElement.classList.toggle('dark', val);
40
+ })">
63
41
 
64
42
  <!-- Navigation -->
65
- <nav class="bg-white dark:bg-gray-800 shadow-sm border-b border-gray-200 dark:border-gray-700">
43
+ <nav class="bg-white dark:bg-gray-800 shadow border-b border-gray-200 dark:border-gray-700">
66
44
  <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
67
- <div class="flex justify-between items-center h-16">
68
- <!-- Logo and title -->
45
+ <div class="flex justify-between h-16">
46
+ <!-- Logo -->
69
47
  <div class="flex items-center">
70
- <div class="flex-shrink-0 flex items-center">
71
- <span class="material-icons-round text-blue-600 mr-2 text-2xl">payment</span>
72
- <h1 class="text-xl font-bold text-gray-900 dark:text-white">
73
- Universal Payment System v2.0
74
- </h1>
75
- </div>
48
+ <span class="material-icons-outlined text-blue-600 mr-2">payment</span>
49
+ <h1 class="text-xl font-semibold text-gray-900 dark:text-white">Payment Admin</h1>
76
50
  </div>
77
51
 
78
- <!-- Navigation links -->
79
- <div class="hidden md:block">
80
- <div class="ml-10 flex items-baseline space-x-4">
81
- <a href="{% url 'cfg_payments_admin:webhook-dashboard' %}"
82
- class="text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white px-3 py-2 rounded-md text-sm font-medium flex items-center">
83
- <span class="material-icons-outlined mr-1 text-sm">webhook</span>
84
- Webhooks
85
- </a>
86
- <a href="{% url 'cfg_payments_admin:payment-list' %}"
87
- class="text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white px-3 py-2 rounded-md text-sm font-medium flex items-center">
88
- <span class="material-icons-outlined mr-1 text-sm">payments</span>
89
- Payments
90
- </a>
91
- <a href="{% url 'admin:payments_universalpayment_changelist' %}"
92
- class="text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white px-3 py-2 rounded-md text-sm font-medium flex items-center">
93
- <span class="material-icons-outlined mr-1 text-sm">admin_panel_settings</span>
94
- Admin
95
- </a>
96
- </div>
97
- </div>
98
-
99
- <!-- Dark mode toggle -->
52
+ <!-- Navigation Links -->
100
53
  <div class="flex items-center space-x-4">
54
+ <a href="{% url 'cfg_payments_admin:dashboard' %}"
55
+ class="text-gray-600 hover:text-gray-900 dark:text-gray-300 dark:hover:text-white px-3 py-2 rounded-md text-sm font-medium">
56
+ Dashboard
57
+ </a>
58
+ <a href="{% url 'cfg_payments_admin:payment-list' %}"
59
+ class="text-gray-600 hover:text-gray-900 dark:text-gray-300 dark:hover:text-white px-3 py-2 rounded-md text-sm font-medium">
60
+ Payments
61
+ </a>
62
+ <a href="{% url 'cfg_payments_admin:webhook-dashboard' %}"
63
+ class="text-gray-600 hover:text-gray-900 dark:text-gray-300 dark:hover:text-white px-3 py-2 rounded-md text-sm font-medium">
64
+ Webhooks
65
+ </a>
66
+
67
+ <!-- Dark Mode Toggle -->
101
68
  <button @click="darkMode = !darkMode"
102
- class="p-2 rounded-md text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white hover:bg-gray-100 dark:hover:bg-gray-700">
103
- <span x-show="!darkMode" class="material-icons-outlined">dark_mode</span>
104
- <span x-show="darkMode" class="material-icons-outlined">light_mode</span>
69
+ class="p-2 text-gray-600 hover:text-gray-900 dark:text-gray-300 dark:hover:text-white transition-colors">
70
+ <span x-show="!darkMode" x-cloak class="material-icons-outlined">dark_mode</span>
71
+ <span x-show="darkMode" x-cloak class="material-icons-outlined">light_mode</span>
105
72
  </button>
106
73
  </div>
107
74
  </div>
108
75
  </div>
109
76
  </nav>
110
77
 
111
- <!-- Main content -->
78
+ <!-- Main Content -->
112
79
  <main class="max-w-7xl mx-auto py-6 px-4 sm:px-6 lg:px-8">
113
- <!-- Page header -->
80
+ <!-- Page Header -->
114
81
  {% block header %}
115
82
  <div class="mb-8">
116
83
  <h2 class="text-2xl font-bold text-gray-900 dark:text-white">
@@ -118,7 +85,7 @@
118
85
  </h2>
119
86
  {% block page_subtitle %}
120
87
  <p class="mt-1 text-sm text-gray-600 dark:text-gray-400">
121
- Monitor and manage your payment system
88
+ Manage payments and webhooks
122
89
  </p>
123
90
  {% endblock %}
124
91
  </div>
@@ -128,34 +95,32 @@
128
95
  {% if messages %}
129
96
  <div class="mb-6 space-y-2">
130
97
  {% for message in messages %}
131
- <div class="rounded-md p-4 {% if message.tags == 'error' %}bg-red-50 text-red-800 border border-red-200{% elif message.tags == 'warning' %}bg-yellow-50 text-yellow-800 border border-yellow-200{% elif message.tags == 'success' %}bg-green-50 text-green-800 border border-green-200{% else %}bg-blue-50 text-blue-800 border border-blue-200{% endif %}">
98
+ <div class="rounded-md p-4 {% if message.tags == 'error' %}bg-red-50 text-red-800 border border-red-200 dark:bg-red-900/20 dark:text-red-400 dark:border-red-800{% elif message.tags == 'warning' %}bg-yellow-50 text-yellow-800 border border-yellow-200 dark:bg-yellow-900/20 dark:text-yellow-400 dark:border-yellow-800{% elif message.tags == 'success' %}bg-green-50 text-green-800 border border-green-200 dark:bg-green-900/20 dark:text-green-400 dark:border-green-800{% else %}bg-blue-50 text-blue-800 border border-blue-200 dark:bg-blue-900/20 dark:text-blue-400 dark:border-blue-800{% endif %}">
132
99
  {{ message }}
133
100
  </div>
134
101
  {% endfor %}
135
102
  </div>
136
103
  {% endif %}
137
104
 
138
- <!-- Page content -->
105
+ <!-- Page Content -->
139
106
  {% block content %}{% endblock %}
140
107
  </main>
141
108
 
142
109
  <!-- Footer -->
143
110
  <footer class="bg-white dark:bg-gray-800 border-t border-gray-200 dark:border-gray-700 mt-12">
144
111
  <div class="max-w-7xl mx-auto py-4 px-4 sm:px-6 lg:px-8">
145
- <div class="flex justify-between items-center text-sm text-gray-600 dark:text-gray-400">
146
- <div>
147
- Universal Payment System v2.0 - Built with Django-CFG
148
- </div>
149
- <div>
150
- {% now "Y-m-d H:i:s" %} UTC
151
- </div>
112
+ <div class="text-center text-sm text-gray-600 dark:text-gray-400">
113
+ Payment Admin - Django CFG
152
114
  </div>
153
115
  </div>
154
116
  </footer>
155
117
 
156
- <!-- Custom JavaScript -->
157
- <script src="{% static 'payments/js/utils.js' %}"></script>
158
- <script src="{% static 'payments/js/components.js' %}"></script>
118
+ <!-- Global Dialogs -->
119
+ {% include 'payments/components/ngrok_help_dialog.html' %}
120
+
121
+ <!-- Payment System JS Components -->
122
+ <script src="{% static 'payments/js/api-client.js' %}"></script>
123
+ <script src="{% static 'payments/js/ngrok-status.js' %}"></script>
159
124
 
160
125
  {% block extra_js %}{% endblock %}
161
126
  </body>
@@ -0,0 +1,81 @@
1
+ {% comment %}
2
+ Dialog Component
3
+
4
+ Usage:
5
+ {% include 'payments/components/dialog.html' with dialog_id="myDialog" title="Dialog Title" %}
6
+
7
+ Then in your Alpine.js component:
8
+ x-data="{ showMyDialog: false }"
9
+ @click="showMyDialog = true"
10
+
11
+ And in the dialog content:
12
+ <div x-show="showMyDialog" x-cloak>
13
+ {% include 'payments/components/dialog.html' with dialog_id="myDialog" title="My Title" %}
14
+ </div>
15
+ {% endcomment %}
16
+
17
+ <!-- Dialog Backdrop -->
18
+ <div x-show="show{{ dialog_id|title }}"
19
+ x-cloak
20
+ x-transition:enter="transition ease-out duration-300"
21
+ x-transition:enter-start="opacity-0"
22
+ x-transition:enter-end="opacity-100"
23
+ x-transition:leave="transition ease-in duration-200"
24
+ x-transition:leave-start="opacity-100"
25
+ x-transition:leave-end="opacity-0"
26
+ class="fixed inset-0 bg-gray-600 bg-opacity-50 flex items-center justify-center z-50"
27
+ @click.away="show{{ dialog_id|title }} = false">
28
+
29
+ <!-- Dialog Panel -->
30
+ <div x-show="show{{ dialog_id|title }}"
31
+ x-transition:enter="transition ease-out duration-300"
32
+ x-transition:enter-start="opacity-0 transform scale-95"
33
+ x-transition:enter-end="opacity-100 transform scale-100"
34
+ x-transition:leave="transition ease-in duration-200"
35
+ x-transition:leave-start="opacity-100 transform scale-100"
36
+ x-transition:leave-end="opacity-0 transform scale-95"
37
+ class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-md w-full mx-4 max-h-96 overflow-y-auto"
38
+ @click.stop>
39
+
40
+ <!-- Dialog Header -->
41
+ <div class="px-6 py-4 border-b border-gray-200 dark:border-gray-700">
42
+ <div class="flex items-center justify-between">
43
+ <h3 class="text-lg font-medium text-gray-900 dark:text-white">
44
+ {% if icon %}
45
+ <span class="material-icons-outlined mr-2 text-{{ icon_color|default:'blue' }}-600 dark:text-{{ icon_color|default:'blue' }}-400">{{ icon }}</span>
46
+ {% endif %}
47
+ {{ title }}
48
+ </h3>
49
+ <button @click="show{{ dialog_id|title }} = false"
50
+ class="text-gray-400 hover:text-gray-600 dark:hover:text-gray-200">
51
+ <span class="material-icons-outlined">close</span>
52
+ </button>
53
+ </div>
54
+ </div>
55
+
56
+ <!-- Dialog Content -->
57
+ <div class="px-6 py-4">
58
+ {% block dialog_content %}
59
+ {{ content|default:"Dialog content goes here" }}
60
+ {% endblock %}
61
+ </div>
62
+
63
+ <!-- Dialog Footer -->
64
+ {% if show_footer|default:True %}
65
+ <div class="px-6 py-4 border-t border-gray-200 dark:border-gray-700 flex justify-end space-x-3">
66
+ {% block dialog_footer %}
67
+ <button @click="show{{ dialog_id|title }} = false"
68
+ class="px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-md hover:bg-gray-50 dark:bg-gray-700 dark:text-gray-300 dark:border-gray-600 dark:hover:bg-gray-600">
69
+ {{ cancel_text|default:"Close" }}
70
+ </button>
71
+ {% if confirm_action %}
72
+ <button @click="{{ confirm_action }}; show{{ dialog_id|title }} = false"
73
+ class="px-4 py-2 text-sm font-medium text-white bg-{{ confirm_color|default:'blue' }}-600 border border-transparent rounded-md hover:bg-{{ confirm_color|default:'blue' }}-700">
74
+ {{ confirm_text|default:"Confirm" }}
75
+ </button>
76
+ {% endif %}
77
+ {% endblock %}
78
+ </div>
79
+ {% endif %}
80
+ </div>
81
+ </div>
@@ -0,0 +1,112 @@
1
+ {% comment %}
2
+ Ngrok Help Dialog Component
3
+ Shows instructions for starting ngrok tunnel
4
+ {% endcomment %}
5
+
6
+ <!-- Ngrok Help Dialog -->
7
+ <div x-show="showNgrokHelp"
8
+ x-cloak
9
+ x-transition:enter="transition ease-out duration-300"
10
+ x-transition:enter-start="opacity-0"
11
+ x-transition:enter-end="opacity-100"
12
+ x-transition:leave="transition ease-in duration-200"
13
+ x-transition:leave-start="opacity-100"
14
+ x-transition:leave-end="opacity-0"
15
+ class="fixed inset-0 bg-gray-600 bg-opacity-50 flex items-center justify-center z-50"
16
+ @click.away="showNgrokHelp = false">
17
+
18
+ <!-- Dialog Panel -->
19
+ <div x-show="showNgrokHelp"
20
+ x-transition:enter="transition ease-out duration-300"
21
+ x-transition:enter-start="opacity-0 transform scale-95"
22
+ x-transition:enter-end="opacity-100 transform scale-100"
23
+ x-transition:leave="transition ease-in duration-200"
24
+ x-transition:leave-start="opacity-100 transform scale-100"
25
+ x-transition:leave-end="opacity-0 transform scale-95"
26
+ class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-lg w-full mx-4"
27
+ @click.stop>
28
+
29
+ <!-- Dialog Header -->
30
+ <div class="px-6 py-4 border-b border-gray-200 dark:border-gray-700">
31
+ <div class="flex items-center justify-between">
32
+ <h3 class="text-lg font-medium text-gray-900 dark:text-white flex items-center">
33
+ <span class="material-icons-outlined mr-2 text-blue-600 dark:text-blue-400">help</span>
34
+ How to Start Ngrok Tunnel
35
+ </h3>
36
+ <button @click="showNgrokHelp = false"
37
+ class="text-gray-400 hover:text-gray-600 dark:hover:text-gray-200">
38
+ <span class="material-icons-outlined">close</span>
39
+ </button>
40
+ </div>
41
+ </div>
42
+
43
+ <!-- Dialog Content -->
44
+ <div class="px-6 py-4 space-y-4">
45
+ <div class="bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-lg p-4">
46
+ <div class="flex items-start">
47
+ <span class="material-icons-outlined text-blue-600 dark:text-blue-400 mr-2 mt-0.5">info</span>
48
+ <div>
49
+ <h4 class="font-medium text-blue-900 dark:text-blue-100 mb-1">Ngrok is not active</h4>
50
+ <p class="text-sm text-blue-800 dark:text-blue-200">
51
+ To enable ngrok tunnel for webhook testing, restart your development server with the ngrok command.
52
+ </p>
53
+ </div>
54
+ </div>
55
+ </div>
56
+
57
+ <div>
58
+ <h4 class="font-medium text-gray-900 dark:text-white mb-2 flex items-center">
59
+ <span class="material-icons-outlined mr-2 text-green-600 dark:text-green-400">terminal</span>
60
+ Start Server with Ngrok
61
+ </h4>
62
+ <div class="bg-gray-900 dark:bg-gray-800 rounded-lg p-4 font-mono text-sm">
63
+ <div class="text-green-400 mb-2"># Stop current server (Ctrl+C) and run:</div>
64
+ <div class="text-white">python manage.py runserver_ngrok</div>
65
+ </div>
66
+ </div>
67
+
68
+ <div>
69
+ <h4 class="font-medium text-gray-900 dark:text-white mb-2 flex items-center">
70
+ <span class="material-icons-outlined mr-2 text-purple-600 dark:text-purple-400">settings</span>
71
+ Advanced Options
72
+ </h4>
73
+ <div class="space-y-2 text-sm">
74
+ <div class="bg-gray-50 dark:bg-gray-700 rounded p-3">
75
+ <div class="font-mono text-gray-800 dark:text-gray-200 mb-1">python manage.py runserver_ngrok --domain myapp</div>
76
+ <div class="text-gray-600 dark:text-gray-400">Use custom subdomain</div>
77
+ </div>
78
+ <div class="bg-gray-50 dark:bg-gray-700 rounded p-3">
79
+ <div class="font-mono text-gray-800 dark:text-gray-200 mb-1">python manage.py runserver_ngrok 0.0.0.0:8080</div>
80
+ <div class="text-gray-600 dark:text-gray-400">Use custom port</div>
81
+ </div>
82
+ </div>
83
+ </div>
84
+
85
+ <div class="bg-yellow-50 dark:bg-yellow-900/20 border border-yellow-200 dark:border-yellow-800 rounded-lg p-4">
86
+ <div class="flex items-start">
87
+ <span class="material-icons-outlined text-yellow-600 dark:text-yellow-400 mr-2 mt-0.5">lightbulb</span>
88
+ <div>
89
+ <h4 class="font-medium text-yellow-900 dark:text-yellow-100 mb-1">Pro Tip</h4>
90
+ <p class="text-sm text-yellow-800 dark:text-yellow-200">
91
+ Once ngrok is active, you'll see the public URL here and can copy it for webhook configuration.
92
+ </p>
93
+ </div>
94
+ </div>
95
+ </div>
96
+ </div>
97
+
98
+ <!-- Dialog Footer -->
99
+ <div class="px-6 py-4 border-t border-gray-200 dark:border-gray-700 flex justify-between">
100
+ <a href="https://ngrok.com/docs"
101
+ target="_blank"
102
+ class="text-sm text-blue-600 hover:text-blue-800 dark:text-blue-400 dark:hover:text-blue-300 flex items-center">
103
+ <span class="material-icons-outlined mr-1 text-sm">open_in_new</span>
104
+ Ngrok Documentation
105
+ </a>
106
+ <button @click="showNgrokHelp = false"
107
+ class="px-4 py-2 text-sm font-medium text-white bg-blue-600 border border-transparent rounded-md hover:bg-blue-700">
108
+ Got it!
109
+ </button>
110
+ </div>
111
+ </div>
112
+ </div>