From 56cda47af8116d6f6f1ca099e4cc908f852949c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Fri, 31 Oct 2025 12:13:49 +0100 Subject: [PATCH] feature/Implemented a GUI for the `/obp/v6.0.0/management/consumers/CONSUMER_ID/consumer/current-usage` endpoint with the --- .../consumers/templates/consumers/detail.html | 83 ++++++++++--------- apimanager/consumers/views.py | 50 +++++++++-- 2 files changed, 85 insertions(+), 48 deletions(-) diff --git a/apimanager/consumers/templates/consumers/detail.html b/apimanager/consumers/templates/consumers/detail.html index 7e65d90..64f6556 100644 --- a/apimanager/consumers/templates/consumers/detail.html +++ b/apimanager/consumers/templates/consumers/detail.html @@ -182,62 +182,55 @@ - {% if consumer.current_state %}

{% trans "Current Usage" %}

- {% if consumer.current_state.per_hour %}
- {% if consumer.current_state.per_second %}
{% trans "Per Second" %}
- {{ consumer.current_state.per_second.calls_made }} calls made
- Resets in {{ consumer.current_state.per_second.reset_in_seconds }} seconds + {% if current_usage.per_second.calls_made|add:"0" == -1 %}Not tracked{% else %}{{ current_usage.per_second.calls_made }} calls made{% endif %}
+ {% if current_usage.per_second.reset_in_seconds|add:"0" == -1 %}Not tracked{% else %}Resets in {{ current_usage.per_second.reset_in_seconds }} seconds{% endif %}
- {% endif %} - {% if consumer.current_state.per_minute %}
{% trans "Per Minute" %}
- {{ consumer.current_state.per_minute.calls_made }} calls made
- Resets in {{ consumer.current_state.per_minute.reset_in_seconds }} seconds + {% if current_usage.per_minute.calls_made|add:"0" == -1 %}Not tracked{% else %}{{ current_usage.per_minute.calls_made }} calls made{% endif %}
+ {% if current_usage.per_minute.reset_in_seconds|add:"0" == -1 %}Not tracked{% else %}Resets in {{ current_usage.per_minute.reset_in_seconds }} seconds{% endif %}
- {% endif %}
{% trans "Per Hour" %}
- {{ consumer.current_state.per_hour.calls_made }} calls made
- Resets in {{ consumer.current_state.per_hour.reset_in_seconds }} seconds + {% if current_usage.per_hour.calls_made|add:"0" == -1 %}Not tracked{% else %}{{ current_usage.per_hour.calls_made }} calls made{% endif %}
+ {% if current_usage.per_hour.reset_in_seconds|add:"0" == -1 %}Not tracked{% else %}Resets in {{ current_usage.per_hour.reset_in_seconds }} seconds{% endif %}
{% trans "Per Day" %}
- {{ consumer.current_state.per_day.calls_made }} calls made
- Resets in {{ consumer.current_state.per_day.reset_in_seconds }} seconds + {% if current_usage.per_day.calls_made|add:"0" == -1 %}Not tracked{% else %}{{ current_usage.per_day.calls_made }} calls made{% endif %}
+ {% if current_usage.per_day.reset_in_seconds|add:"0" == -1 %}Not tracked{% else %}Resets in {{ current_usage.per_day.reset_in_seconds }} seconds{% endif %}
{% trans "Per Week" %}
- {{ consumer.current_state.per_week.calls_made }} calls made
- Resets in {{ consumer.current_state.per_week.reset_in_seconds }} seconds + {% if current_usage.per_week.calls_made|add:"0" == -1 %}Not tracked{% else %}{{ current_usage.per_week.calls_made }} calls made{% endif %}
+ {% if current_usage.per_week.reset_in_seconds|add:"0" == -1 %}Not tracked{% else %}Resets in {{ current_usage.per_week.reset_in_seconds }} seconds{% endif %}
{% trans "Per Month" %}
- {{ consumer.current_state.per_month.calls_made }} calls made
- Resets in {{ consumer.current_state.per_month.reset_in_seconds }} seconds + {% if current_usage.per_month.calls_made|add:"0" == -1 %}Not tracked{% else %}{{ current_usage.per_month.calls_made }} calls made{% endif %}
+ {% if current_usage.per_month.reset_in_seconds|add:"0" == -1 %}Not tracked{% else %}Resets in {{ current_usage.per_month.reset_in_seconds }} seconds{% endif %}
- {% endif %} +
- {% endif %}
@@ -352,6 +345,14 @@ {% if consumer.to_date %} $('body').attr('data-to-date', '{{ consumer.to_date }}'); {% endif %} + + // Debug: Log basic debugging info + console.log('Current usage data available:', {% if current_usage %}true{% else %}false{% endif %}); + + // Initial load of usage data + setTimeout(function() { + fetchUsageData(); + }, 1000); }); // Global functions for CRUD operations - attached to window for global access @@ -469,17 +470,17 @@ // Global variables for refresh functionality let refreshInterval = null; let refreshCount = 0; - const MAX_REFRESH_COUNT = 10; + const MAX_REFRESH_COUNT = 5; // Function to refresh usage statistics - function refreshUsageStats() { + window.refreshUsageStats = function() { const button = document.getElementById('refreshUsageBtn'); const progressDiv = document.getElementById('refreshProgress'); const progressBar = document.getElementById('progressBar'); // Disable button and show progress button.disabled = true; - button.innerHTML = ' Refreshing...'; + button.innerHTML = ' Auto Refreshing...'; progressDiv.style.display = 'block'; // Reset counters @@ -488,13 +489,15 @@ // Start refresh cycle refreshInterval = setInterval(fetchUsageData, 1000); fetchUsageData(); // Initial fetch - } + }; // Function to fetch usage data via AJAX function fetchUsageData() { const consumerId = '{{ consumer.consumer_id }}'; const panel = document.getElementById('usageStatsPanel'); + console.log('Fetching usage data for consumer:', consumerId); + // Add refreshing effect to panel panel.classList.add('panel-refreshing'); @@ -507,6 +510,7 @@ }, timeout: 5000, // 5 second timeout success: function(data) { + console.log('Usage data received:', data); updateUsageDisplay(data); refreshCount++; @@ -516,7 +520,7 @@ progressBar.style.width = progress + '%'; progressBar.textContent = refreshCount + '/' + MAX_REFRESH_COUNT; - // Stop after 10 seconds + // Stop after 5 seconds if (refreshCount >= MAX_REFRESH_COUNT) { clearInterval(refreshInterval); resetRefreshButton(); @@ -524,7 +528,7 @@ } }, error: function(xhr, status, error) { - console.error('Error fetching usage data:', error); + console.error('Error fetching usage data:', error, xhr.responseText); showRefreshError(error); refreshCount++; @@ -562,12 +566,12 @@ // Function to update usage display with new data function updateUsageDisplay(data) { - if (data && data.current_state) { - const currentState = data.current_state; + console.log('Updating display with data:', data); + if (data) { const periods = ['per_second', 'per_minute', 'per_hour', 'per_day', 'per_week', 'per_month']; periods.forEach(function(period) { - const periodData = currentState[period]; + const periodData = data[period]; if (periodData) { const periodDiv = document.querySelector('[data-period="' + period + '"]'); if (periodDiv) { @@ -575,13 +579,14 @@ const resetSpan = periodDiv.querySelector('.usage-reset'); if (callsSpan) { - const oldCalls = callsSpan.textContent.match(/\d+/); + const oldCalls = callsSpan.textContent.match(/-?\d+/); const newCalls = periodData.calls_made; + const displayCalls = newCalls === -1 ? 'Not tracked' : newCalls + ' calls made'; // Check if calls increased - const callsIncreased = oldCalls && parseInt(oldCalls[0]) < newCalls; + const callsIncreased = oldCalls && parseInt(oldCalls[0]) < newCalls && newCalls !== -1; - callsSpan.textContent = newCalls + ' calls made'; + callsSpan.textContent = displayCalls; // Add visual feedback callsSpan.classList.add('updating'); @@ -604,7 +609,8 @@ } if (resetSpan) { - resetSpan.textContent = 'Resets in ' + periodData.reset_in_seconds + ' seconds'; + const resetText = periodData.reset_in_seconds === -1 ? 'Not tracked' : 'Resets in ' + periodData.reset_in_seconds + ' seconds'; + resetSpan.textContent = resetText; // Add subtle animation to reset timer resetSpan.style.opacity = '0.7'; setTimeout(function() { @@ -621,7 +627,7 @@ } // Function to update last refresh time - function updateLastRefreshTime() { + window.updateLastRefreshTime = function() { let timeDiv = document.getElementById('lastRefreshTime'); if (!timeDiv) { timeDiv = document.createElement('small'); @@ -638,13 +644,12 @@ } // Function to reset refresh button - function resetRefreshButton() { + window.resetRefreshButton = function() { const button = document.getElementById('refreshUsageBtn'); const progressDiv = document.getElementById('refreshProgress'); - const panel = document.getElementById('usageStatsPanel'); button.disabled = false; - button.innerHTML = ' {% trans "Refresh (10s)" %}'; + button.innerHTML = ' Auto Refresh (5s)'; progressDiv.style.display = 'none'; document.getElementById('progressBar').style.width = '0%'; document.getElementById('progressBar').textContent = ''; @@ -654,7 +659,7 @@ if (errorDiv && errorDiv.parentNode) { errorDiv.parentNode.removeChild(errorDiv); } - } + }; {% endblock extrajs %} diff --git a/apimanager/consumers/views.py b/apimanager/consumers/views.py index 950be20..89a6f24 100644 --- a/apimanager/consumers/views.py +++ b/apimanager/consumers/views.py @@ -455,6 +455,15 @@ class DetailView(LoginRequiredMixin, FormView): api = API(self.request.session.get("obp")) consumer = {} call_limits = {} + # Initialize current_usage with default values + current_usage = { + "per_second": {"calls_made": -1, "reset_in_seconds": -1}, + "per_minute": {"calls_made": -1, "reset_in_seconds": -1}, + "per_hour": {"calls_made": -1, "reset_in_seconds": -1}, + "per_day": {"calls_made": -1, "reset_in_seconds": -1}, + "per_week": {"calls_made": -1, "reset_in_seconds": -1}, + "per_month": {"calls_made": -1, "reset_in_seconds": -1}, + } try: urlpath = "/management/consumers/{}".format(self.kwargs["consumer_id"]) @@ -477,6 +486,19 @@ class DetailView(LoginRequiredMixin, FormView): call_limits_urlpath, version=settings.API_VERSION["v510"] ) + # Get current usage data using v6.0.0 API + current_usage_urlpath = ( + "/management/consumers/{}/consumer/current-usage".format( + self.kwargs["consumer_id"] + ) + ) + current_usage = api.get( + current_usage_urlpath, version=settings.API_VERSION["v600"] + ) + if "code" in current_usage and current_usage["code"] >= 400: + # If current usage fails, keep the default values already set + pass + if "code" in call_limits and call_limits["code"] >= 400: messages.error(self.request, "{}".format(call_limits["message"])) call_limits = {"limits": []} @@ -541,29 +563,39 @@ class DetailView(LoginRequiredMixin, FormView): except Exception as err: messages.error(self.request, "{}".format(err)) finally: - context.update({"consumer": consumer, "call_limits": call_limits}) + # Ensure current_usage always has the expected structure + if not current_usage or "per_second" not in current_usage: + current_usage = { + "per_second": {"calls_made": -1, "reset_in_seconds": -1}, + "per_minute": {"calls_made": -1, "reset_in_seconds": -1}, + "per_hour": {"calls_made": -1, "reset_in_seconds": -1}, + "per_day": {"calls_made": -1, "reset_in_seconds": -1}, + "per_week": {"calls_made": -1, "reset_in_seconds": -1}, + "per_month": {"calls_made": -1, "reset_in_seconds": -1}, + } + context.update({"consumer": consumer, "call_limits": call_limits, "current_usage": current_usage}) return context class UsageDataAjaxView(LoginRequiredMixin, TemplateView): - """AJAX view to return usage data for real-time updates""" + """AJAX view to return current usage data for real-time updates""" def get(self, request, *args, **kwargs): api = API(self.request.session.get("obp")) try: - call_limits_urlpath = ( - "/management/consumers/{}/consumer/rate-limits".format( + current_usage_urlpath = ( + "/management/consumers/{}/consumer/current-usage".format( self.kwargs["consumer_id"] ) ) - call_limits = api.get( - call_limits_urlpath, version=settings.API_VERSION["v510"] + current_usage = api.get( + current_usage_urlpath, version=settings.API_VERSION["v600"] ) - if "code" in call_limits and call_limits["code"] >= 400: - return JsonResponse({"error": call_limits["message"]}, status=400) + if "code" in current_usage and current_usage["code"] >= 400: + return JsonResponse({"error": current_usage["message"]}, status=400) - return JsonResponse(call_limits) + return JsonResponse(current_usage) except APIError as err: return JsonResponse({"error": str(err)}, status=500) except Exception as err: