Skip to content

Commit

Permalink
[fix] Dashboard timeseries chart should respect MONITORING_API_BASEURL
Browse files Browse the repository at this point in the history
Django admin should make API request to MONITORING_API_BASEURL.
  • Loading branch information
pandafy committed Aug 28, 2024
1 parent f9839e5 commit 5410433
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 54 deletions.
10 changes: 9 additions & 1 deletion openwisp_monitoring/device/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,14 @@ def register_dashboard_items(self):
}
}

dashboard_chart_url = reverse_lazy(
'monitoring_general:api_dashboard_timeseries',
urlconf=MONITORING_API_URLCONF,
)
if MONITORING_API_BASEURL:
dashboard_chart_url = urljoin(
MONITORING_API_BASEURL, str(dashboard_chart_url)
)
register_dashboard_template(
position=55,
config={
Expand All @@ -450,7 +458,7 @@ def register_dashboard_items(self):
),
},
extra_config={
'api_url': reverse_lazy('monitoring_general:api_dashboard_timeseries'),
'api_url': dashboard_chart_url,
'default_time': Chart.DEFAULT_TIME,
'chart_quick_links': general_wifi_client_quick_links,
},
Expand Down
115 changes: 62 additions & 53 deletions openwisp_monitoring/device/static/monitoring/js/device-map.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,65 +54,74 @@

loadingOverlay.show();

$.getJSON(url, function (data) {
let html = '',
device;
for (let i = 0; i < data.results.length; i++) {
device = data.results[i];
html += `
<tr>
<td><a href="${device.admin_edit_url}">${device.name}</a></td>
<td>
<span class="health-status health-${device.monitoring.status}">
${device.monitoring.status_label}
</span>
</td>
</tr>`;
}
let pagination = '',
parts = [];
if (data.previous || data.next) {
if (data.previous) {
parts.push(`<a class="prev" href="#prev" data-url="${data.previous}">&#8249; ${gettext('previous')}</a>`);
$.ajax({
dataType: "json",
url: url,
xhrFields: {
withCredentials: true
},
success: function (data) {
let html = '',
device;
for (let i = 0; i < data.results.length; i++) {
device = data.results[i];
html += `
<tr>
<td><a href="${device.admin_edit_url}">${device.name}</a></td>
<td>
<span class="health-status health-${device.monitoring.status}">
${device.monitoring.status_label}
</span>
</td>
</tr>`;
}
if (data.next) {
parts.push(`<a class="next" href="#next" data-url="${data.next}">${gettext('next')} &#8250;</a>`);
let pagination = '',
parts = [];
if (data.previous || data.next) {
if (data.previous) {
parts.push(`<a class="prev" href="#prev" data-url="${data.previous}">&#8249; ${gettext('previous')}</a>`);
}
if (data.next) {
parts.push(`<a class="next" href="#next" data-url="${data.next}">${gettext('next')} &#8250;</a>`);
}
pagination = `<p class="paginator">${parts.join(' ')}</div>`;
}
pagination = `<p class="paginator">${parts.join(' ')}</div>`;
}
layer.bindPopup(`
<div class="map-detail">
<h2>${layer.feature.properties.name} (${data.count})</h2>
<table>
<thead>
<tr>
<th>${gettext('name')}</th>
<th>${gettext('status')}</th>
</tr>
</thead>
<tbody>
${html}
</tbody>
</table>
${pagination}
</div>`);
layer.openPopup();
layer.bindPopup(`
<div class="map-detail">
<h2>${layer.feature.properties.name} (${data.count})</h2>
<table>
<thead>
<tr>
<th>${gettext('name')}</th>
<th>${gettext('status')}</th>
</tr>
</thead>
<tbody>
${html}
</tbody>
</table>
${pagination}
</div>`);
layer.openPopup();

// bind next/prev buttons
let el = $(layer.getPopup().getElement());
el.find('.next').click(function () {
loadPopUpContent(layer, $(this).data('url'));
});
el.find('.prev').click(function () {
loadPopUpContent(layer, $(this).data('url'));
});
// bind next/prev buttons
let el = $(layer.getPopup().getElement());
el.find('.next').click(function () {
loadPopUpContent(layer, $(this).data('url'));
});
el.find('.prev').click(function () {
loadPopUpContent(layer, $(this).data('url'));
});

loadingOverlay.hide();
loadingOverlay.hide();

}).fail(function () {
loadingOverlay.hide();
alert(gettext('Error while retrieving data'));
},
error: function () {
loadingOverlay.hide();
alert(gettext('Error while retrieving data'));
}
});

};
const leafletConfig = JSON.parse($('#leaflet-config').text());
const tiles = leafletConfig.TILES.map((tile) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,9 @@ django.jQuery(function ($) {
loadCharts = function (time, showLoading) {
$.ajax(getChartFetchUrl(time), {
dataType: 'json',
xhrFields: {
withCredentials: true
},
beforeSend: function () {
chartContents.hide();
chartContents.empty();
Expand Down
38 changes: 38 additions & 0 deletions openwisp_monitoring/tests/test_selenium.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
)
from openwisp_monitoring.monitoring.configuration import DEFAULT_DASHBOARD_TRAFFIC_CHART
from openwisp_monitoring.monitoring.migrations import create_general_metrics
from openwisp_utils.admin_theme.dashboard import DASHBOARD_TEMPLATES
from openwisp_utils.test_selenium_mixins import (
SeleniumTestMixin as BaseSeleniumTestMixin,
)
Expand All @@ -30,6 +31,43 @@


class SeleniumTestMixin(BaseSeleniumTestMixin):
@classmethod
def setUpClass(cls):
"""
Sets up the necessary configurations for the test environment, ensuring
that the dashboard templates render correctly during Selenium tests.
During testing, the `OPENWISP_MONITORING_API_BASEURL` is set to
`http://testserver`, a dummy value for the test environment. The dashboard
templates are registered in the `AppConfig.ready` method, and these
templates depend on specific URLs being correctly configured.
Since mocking the `OPENWISP_MONITORING_API_BASEURL` does not update the
URLs in the already registered dashboard templates, this method manually
adjusts the template contexts to ensure they contain the correct URLs.
"""
super().setUpClass()
cls._dashboard_map_context = DASHBOARD_TEMPLATES[0][1].copy()
cls._dashboard_timeseries_context = DASHBOARD_TEMPLATES[55][1].copy()
DASHBOARD_TEMPLATES[0][1] = {
'monitoring_device_list_url': reverse(
'monitoring:api_location_device_list',
args=['000'],
),
'monitoring_location_geojson_url': reverse(
'monitoring:api_location_geojson'
),
}
DASHBOARD_TEMPLATES[55][1]['api_url'] = reverse(
'monitoring_general:api_dashboard_timeseries'
)

@classmethod
def tearDownClass(cls):
super().tearDownClass()
DASHBOARD_TEMPLATES[0][1] = cls._dashboard_map_context
DASHBOARD_TEMPLATES[55][1] = cls._dashboard_timeseries_context

def setUp(self):
self.admin = self._create_admin(
username=self.admin_username, password=self.admin_password
Expand Down

0 comments on commit 5410433

Please sign in to comment.