Skip to content

Commit 54d888e

Browse files
authored
Merge pull request #288 from cmu-delphi/staging
Staging
2 parents e6603ee + 8a82b04 commit 54d888e

File tree

13 files changed

+704
-491
lines changed

13 files changed

+704
-491
lines changed

src/assets/css/custom_styles.css

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,6 @@ tr:not(.odd-row) > .dtfc-fixed-end {
261261

262262
.table-stats-info {
263263
font-size: 20px;
264-
margin-bottom: 10px;
265264
}
266265

267266
/* Mobile Filter Sidebar */

src/assets/js/indicatorSetsTable.js

Lines changed: 124 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -10,61 +10,153 @@ function calculate_table_height() {
1010
return (percent * h) / 100;
1111
}
1212

13-
var table = new DataTable("#indicatorSetsTable", {
13+
var table = new DataTable("#indicatorSetsTable", {
14+
ajax: {
15+
url: `${window.location.pathname}${window.location.search.replace(/[?&]format=[^&]*/, "")}${window.location.search ? "&" : "?"}format=json`,
16+
dataSrc: "data"
17+
},
18+
columns: [
19+
{
20+
className: 'dt-control',
21+
orderable: false,
22+
data: null,
23+
defaultContent: ''
24+
}, // dt-control column
25+
{ data: "name" }, // Name
26+
{
27+
data: "pathogens",
28+
render: function (data, type, row) {
29+
if (data) {
30+
return data.map(pathogen => `<span class="badge badge-pill-outline">${pathogen.display_name}</span>`).join('');
31+
} else {
32+
return '';
33+
}
34+
}
35+
}, // Pathogens
36+
{ data: "geographic_scope" }, // Geographic Coverage
37+
{
38+
data: "geographic_levels",
39+
render: function (data, type, row) {
40+
if (data) {
41+
return data.map(geography => `<span class="badge badge-pill-outline">${geography.display_name}</span>`).join('');
42+
} else {
43+
return '';
44+
}
45+
}
46+
}, // Geographic Levels
47+
{ data: "temporal_scope_start" }, // Temporal Scope Start
48+
{ data: "temporal_scope_end" }, // Temporal Scope End
49+
{
50+
data: "temporal_granularity",
51+
render: function (data, type, row) {
52+
if (data) {
53+
return `<span class="badge badge-pill-outline">${data}</span>`;
54+
} else {
55+
return '';
56+
}
57+
}
58+
}, // Temporal Granularity
59+
{ data: "reporting_cadence" }, // Reporting Cadence
60+
{ data: "reporting_lag" }, // Reporting Lag
61+
{ data: "revision_cadence" }, // Revision Cadence
62+
{ data: "demographic_scope" }, // Population
63+
{ data: "demographic_granularity" }, // Population Stratifiers
64+
{
65+
data: "severity_pyramid_rungs",
66+
render: function (data, type, row) {
67+
if (data) {
68+
return data.map(severity_pyramid_rung => `<span class="badge badge-pill-outline">${severity_pyramid_rung.display_name}</span>`).join('');
69+
} else {
70+
return '';
71+
}
72+
}
73+
}, // Surveillance Categories
74+
{ data: "original_data_provider" }, // Original Data Provider
75+
{ data: "preprocessing_description" }, // Pre-processing
76+
{ data: "censoring" }, // Censoring
77+
{ data: "missingness" }, // Missingness
78+
{ data: "delphi_hosted" }, // Hosted by Delphi?
79+
{ data: "dua_required" }, // DUA required?
80+
{ data: "license" }, // Data Use Terms
81+
{
82+
data: "documentation_link",
83+
render: function (data, type, row) {
84+
if (data) {
85+
return `<a href="${data}" target="_blank">${data}</a>`;
86+
} else {
87+
return '';
88+
}
89+
}
90+
}, // Documentation
91+
],
1492
fixedHeader: true,
1593
paging: false,
1694
scrollCollapse: true,
1795
scrollX: true,
1896
scrollY: calculate_table_height() + 75,
19-
info: false,
2097
fixedColumns: {
2198
left: 2,
2299
},
23100
ordering: false,
24101
mark: true,
25-
26102
language: {
27103
emptyTable: "No indicators match your specified filters. Try relaxing some filters, or clear all filters and try again.",
28-
// buttons: {
29-
// colvis: "Toggle Columns",
30-
// },
31104
},
32-
search: {
33-
smart: true,
34-
highlight: true,
105+
layout: {
106+
topStart: function () {
107+
let indicatorSetsInfo = document.createElement('span');
108+
indicatorSetsInfo.className = 'table-stats-info';
109+
indicatorSetsInfo.id = 'indicatorSetsInfo';
110+
$.ajax({
111+
112+
url: "get_table_stats_info/" + window.location.search,
113+
method: "GET",
114+
success: function (response) {
115+
if (response.num_of_locations > 0) {
116+
indicatorSetsInfo.innerHTML =
117+
`Showing <b>${response.num_of_indicators}</b> distinct ${pluralize(response.num_of_indicators, "indicator")} (arranged in <b>${response.num_of_indicator_sets}</b> ${pluralize(response.num_of_indicator_sets, "set")}), including <b>${numberWithCommas(response.num_of_locations)}</b> Delphi-hosted time series across numerous locations.`;
118+
} else {
119+
indicatorSetsInfo.innerHTML =
120+
`Showing <b>${response.num_of_indicators}</b> indicator sets (arranged in <b>${response.num_of_indicator_sets}</b> ${pluralize(response.num_of_indicator_sets, "set")}).`;
121+
}
122+
}
123+
});
124+
return indicatorSetsInfo;
125+
},
126+
topEnd: null,
127+
bottomStart: null,
128+
bottomEnd: null
35129
},
36-
sDom: 'ltipr',
37-
rowCallback: function(row, data, index) {
38-
if (index % 2 === 0) {
130+
createdRow: function (row, data, dataIndex) {
131+
if (data.description) {
132+
$(row).attr('data-description', data.description);
133+
} else {
134+
$(row).attr('data-description', '');
135+
}
136+
// Set row ID if present
137+
if (data.DT_RowId) {
138+
$(row).attr('data-id', data.DT_RowId);
139+
}
140+
// Add odd-row class for styling
141+
if (dataIndex % 2 === 0) {
39142
$(row).addClass('odd-row');
40143
}
41-
}
144+
},
42145
});
43146

44-
// new DataTable.Buttons(table, {
45-
// buttons: [
46-
// {
47-
// extend: "colvis",
48-
// columns: "th:nth-child(n+3)",
49-
// prefixButtons: ["colvisRestore"],
50-
// },
51-
// ],
52-
// });
53-
54-
// table.buttons(0, null).container().appendTo("#colvis");
55-
56-
// $("#tableSearch").keyup(function () {
57-
// table.search(this.value).draw();
58-
// });
59-
60147
function format(indicatorSetId, relatedIndicators, indicatorSetDescription) {
61148
if (!relatedIndicators) {
62149
return '<div class="d-flex justify-content-start my-3" style="padding-left: 20px;"><div class="spinner-border text-primary" role="status"><span class="visually-hidden">Loading...</span></div></div>';
63150
}
64151

65-
var indicators = relatedIndicators.filter(
66-
(indicator) => indicator.indicator_set === indicatorSetId
67-
);
152+
var indicators;
153+
if (Array.isArray(relatedIndicators)) {
154+
indicators = relatedIndicators.filter(
155+
(indicator) => indicator.indicator_set === indicatorSetId
156+
);
157+
} else {
158+
indicators = relatedIndicators[indicatorSetId] || [];
159+
}
68160
var disabled, restricted, sourceType;
69161

70162
if (indicators.length > 0) {

src/assets/js/selectedIndicatorsModal.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,6 @@ async function checkFluviewGeoCoverage(geoValue) {
210210
checkedIndicator["notCoveredGeos"] = [geoValue];
211211
}
212212
}
213-
console.log(checkedIndicatorMembers);
214213
return result["not_covered_indicators"];
215214
} catch (error) {
216215
console.error("Error fetching fluview geo coverage:", error);

src/epiportal/settings.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
from sentry_sdk.integrations.django import DjangoIntegration
2525
from sentry_sdk.integrations.redis import RedisIntegration
2626

27-
APP_VERSION = "1.0.23"
27+
APP_VERSION = "1.1.0"
2828
ALTERNATIVE_INTERFACE_VERSION = "1.0.10"
2929

3030

src/epiportal/urls.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,9 @@
5050
f"{settings.MAIN_PAGE}/" if settings.MAIN_PAGE else "",
5151
include("alternative_interface.urls"),
5252
),
53-
path("__debug__/", include("debug_toolbar.urls")),
53+
path("__debug__/", include("debug_toolbar.urls")),
5454
]
5555

5656

5757
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) # type: ignore
58-
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) # type: ignore
58+
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) # type: ignore

src/indicatorsets/filters.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222

2323
class IndicatorSetFilter(django_filters.FilterSet):
2424

25-
indicators_qs = Indicator.objects.filter(indicator_set__isnull=False)
25+
indicators_qs = Indicator.objects.filter(indicator_set__isnull=False).select_related("indicator_set", "source")
2626

2727
pathogens = django_filters.ModelMultipleChoiceFilter(
2828
field_name="pathogens",

src/indicatorsets/urls.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
check_fluview_geo_coverage, create_query_code,
66
epivis, generate_export_data_url,
77
get_available_geos,
8-
get_related_indicators_json, preview_data)
8+
get_related_indicators_json, preview_data, get_table_stats_info)
99

1010
urlpatterns: list[URLPattern] = [
1111
path("", IndicatorSetListView.as_view(), name="indicatorsets"),
@@ -24,4 +24,9 @@
2424
check_fluview_geo_coverage,
2525
name="check_fluview_geo_coverage",
2626
),
27+
path(
28+
"get_table_stats_info/",
29+
get_table_stats_info,
30+
name="get_table_stats_info",
31+
),
2732
]

src/indicatorsets/utils.py

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import requests
88
from django.conf import settings
99
from django.http import JsonResponse
10+
from django.core.cache import cache
1011
from epiweeks import Week
1112
from delphi_utils import get_structured_logger
1213

@@ -813,16 +814,21 @@ def log_form_data(request, data, form_mode):
813814
def get_num_locations_from_meta(indicators):
814815
timeseries_count = 0
815816
indicators = set(
816-
(indicator["source"], indicator["name"]) for indicator in indicators
817+
(indicator["source__name"], indicator["name"]) for indicator in indicators
817818
)
818-
try:
819-
metadata = requests.get(
820-
f"{settings.EPIDATA_URL}covidcast_meta/", timeout=5
821-
).json()["epidata"]
822-
for r in metadata:
823-
if (r["data_source"], r["signal"]) in indicators:
824-
timeseries_count += r["num_locations"]
825-
except Exception as e:
826-
print(f"Error fetching covidcast metadata: {e}")
827-
return 0
819+
820+
metadata = cache.get("covidcast_meta")
821+
if not metadata:
822+
try:
823+
metadata = requests.get(
824+
f"{settings.EPIDATA_URL}covidcast_meta/", timeout=5
825+
).json()["epidata"]
826+
cache.set("covidcast_meta", metadata, 60 * 60 * 24)
827+
except Exception as e:
828+
print(f"Error fetching covidcast metadata: {e}")
829+
return 0
830+
831+
for r in metadata:
832+
if (r["data_source"], r["signal"]) in indicators:
833+
timeseries_count += r["num_locations"]
828834
return timeseries_count

0 commit comments

Comments
 (0)