Skip to content

Commit f77d0c9

Browse files
authored
Merge pull request #86 from cmu-delphi/OKRS24-100
Okrs24 100 Convert dropdowns do checkboxes
2 parents caf7927 + a3fb17e commit f77d0c9

File tree

7 files changed

+100
-27
lines changed

7 files changed

+100
-27
lines changed

src/assets/css/style.css

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1240,3 +1240,8 @@ h6 {
12401240
.clickable-table-cell:hover {
12411241
cursor: pointer;
12421242
}
1243+
1244+
.bulk-select > a:nth-child(1):hover,
1245+
.bulk-select > a:nth-child(2):hover {
1246+
color: #0d6efd;
1247+
}

src/signals/admin.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,12 @@ class SignalAdmin(ImportExportModelAdmin):
5757
list_display: tuple[Literal['name']] = ('name',)
5858
search_fields: tuple[Literal['name'], Literal['description'], Literal['short_description']]
5959
search_fields = ('name', 'description', 'short_description')
60-
list_filter: tuple[Literal['pathogen'], Literal['available_geography'], Literal['signal_type'], Literal['format_type'],
61-
Literal['is_smoothed'], Literal['is_weighted'], Literal['is_cumulative'], Literal['has_stderr'], Literal['has_sample_size']]
6260
list_filter = (
6361
'pathogen',
6462
'available_geography',
6563
'signal_type',
6664
'format_type',
65+
'time_label',
6766
'is_smoothed',
6867
'is_weighted',
6968
'is_cumulative',

src/signals/filters.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,12 @@
1010
)
1111
from django_filters.widgets import QueryArrayWidget
1212

13-
from signals.models import Signal
13+
from datasources.models import SourceSubdivision
14+
from signals.models import (
15+
FormatChoices,
16+
Signal,
17+
TimeLabelChoices,
18+
)
1419

1520

1621
class NumberInFilter(BaseInFilter, NumberFilter):
@@ -22,7 +27,11 @@ class SignalFilter(django_filters.FilterSet):
2227
FilterSet for the Signal model.
2328
"""
2429

25-
id = NumberInFilter(field_name='id', lookup_expr='in', widget=QueryArrayWidget)
30+
id = NumberInFilter(
31+
field_name='id',
32+
lookup_expr='in',
33+
widget=QueryArrayWidget
34+
)
2635
search = CharFilter(method='filter_search')
2736
order_by = OrderingFilter(
2837
fields=(
@@ -31,6 +40,9 @@ class SignalFilter(django_filters.FilterSet):
3140
('last_updated', 'last_updated'),
3241
)
3342
)
43+
format_type = django_filters.MultipleChoiceFilter(choices=FormatChoices.choices)
44+
source = django_filters.ModelMultipleChoiceFilter(queryset=SourceSubdivision.objects.all())
45+
time_label = django_filters.MultipleChoiceFilter(choices=TimeLabelChoices.choices)
3446

3547
class Meta:
3648
model = Signal

src/signals/forms.py

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33

44
from datasources.models import SourceSubdivision
55
from signals.models import (
6+
ActiveChoices,
67
FormatChoices,
78
Pathogen,
89
Signal,
910
TimeLabelChoices,
10-
ActiveChoices
1111
)
1212

1313

@@ -18,18 +18,18 @@ class SignalFilterForm(forms.ModelForm):
1818
id = forms.ModelMultipleChoiceField(queryset=Signal.objects.all(), widget=forms.MultipleHiddenInput)
1919
order_by = forms.ChoiceField(choices=[
2020
('', '---------'),
21-
('name', 'Name'),
22-
('source__name', 'Source'),
23-
('last_updated', 'Last Updated'),
21+
('name', _('Name')),
22+
('source__name', _('Source')),
23+
('last_updated', _('Last Updated')),
2424
],
2525
required=False,
2626
)
2727
search = forms.CharField(min_length=3)
28-
pathogen = forms.ModelChoiceField(queryset=Pathogen.objects.all(), empty_label='---------')
28+
pathogen = forms.ModelChoiceField(queryset=Pathogen.objects.all(), widget=forms.CheckboxSelectMultiple())
2929
active = forms.TypedMultipleChoiceField(choices=ActiveChoices.choices, coerce=bool, widget=forms.CheckboxSelectMultiple())
30-
format_type = forms.ChoiceField(choices=[('', '---------')] + FormatChoices.choices)
31-
source = forms.ModelChoiceField(queryset=SourceSubdivision.objects.all(), empty_label='---------')
32-
time_label = forms.ChoiceField(choices=[('', '---------')] + TimeLabelChoices.choices, label=_('Temporal Resolution'))
30+
format_type = forms.ChoiceField(choices=FormatChoices.choices, widget=forms.CheckboxSelectMultiple())
31+
source = forms.ModelMultipleChoiceField(queryset=SourceSubdivision.objects.all(), widget=forms.CheckboxSelectMultiple())
32+
time_label = forms.ChoiceField(choices=TimeLabelChoices.choices, widget=forms.CheckboxSelectMultiple())
3333

3434
class Meta:
3535
model = Signal
@@ -53,8 +53,7 @@ class Meta:
5353
'id': 'order_by',
5454
'aria-label': 'Order by',
5555
}),
56-
'search': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Enter search term'}),
57-
'pathogen': forms.Select(attrs={'class': 'form-select'}),
56+
'search': forms.TextInput(attrs={'class': 'form-control', 'placeholder': _('Enter search term')}),
5857
'available_geography': forms.CheckboxSelectMultiple(attrs={
5958
'class': 'form-select',
6059
'data-bs-toggle': 'tooltip',
@@ -70,13 +69,16 @@ class Meta:
7069
'data-bs-toggle': 'tooltip',
7170
'data-bs-placement': 'bottom',
7271
}),
73-
'format_type': forms.Select(attrs={'class': 'form-control'}),
72+
'format_type': forms.CheckboxSelectMultiple(attrs={
73+
'class': 'form-select',
74+
'data-bs-toggle': 'tooltip',
75+
'data-bs-placement': 'bottom',
76+
}),
7477
'source': forms.CheckboxSelectMultiple(attrs={
7578
'class': 'form-select',
7679
'data-bs-toggle': 'tooltip',
7780
'data-bs-placement': 'bottom',
7881
}),
79-
'time_label': forms.Select(attrs={'class': 'form-select'}),
8082
}
8183

8284
def __init__(self, *args, **kwargs):

src/signals/views.py

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
from signals.filters import SignalFilter
1111
from signals.forms import SignalFilterForm
12-
from signals.models import Signal
12+
from signals.models import Pathogen, Signal
1313
from signals.serializers import SignalSerializer
1414

1515

@@ -38,9 +38,9 @@ def get_url_params(self):
3838
url_params_dict = {
3939
"id": self.request.GET.get("id"),
4040
"search": self.request.GET.get("search"),
41-
"pathogen": int(self.request.GET.get("pathogen"))
41+
"pathogen": [el for el in self.request.GET._getlist("pathogen")]
4242
if self.request.GET.get("pathogen")
43-
else "",
43+
else [el.id for el in Pathogen.objects.all()],
4444
"active": [el for el in self.request.GET._getlist("active")]
4545
if self.request.GET.get("active")
4646
else [True, False],
@@ -55,13 +55,9 @@ def get_url_params(self):
5555
"category": self.request.GET._getlist("category")
5656
if self.request.GET.get("category")
5757
else None,
58-
"format_type": self.request.GET.get("format_type"),
59-
"source": int(self.request.GET.get("source"))
60-
if self.request.GET.get("source")
61-
else "",
62-
"time_label": self.request.GET.get("time_label")
63-
if self.request.GET.get("time_label")
64-
else "",
58+
"format_type": [el for el in self.request.GET._getlist("format_type")],
59+
"source": [int(el) for el in self.request.GET._getlist("source")],
60+
"time_label": [el for el in self.request.GET._getlist("time_label")]
6561
}
6662
url_params_str = ""
6763
for param_name, param_value in url_params_dict.items():

src/templates/signals/signal_detail.html

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,24 @@ <h5>About this signal</h5>
179179
{% endif %}
180180
</td>
181181
</tr>
182+
<tr>
183+
<th scope="row">Available Since</th>
184+
<td>
185+
{{ signal.from_date }}
186+
</td>
187+
</tr>
188+
<tr>
189+
<th scope="row">Available Until</th>
190+
<td>
191+
{{ signal.to_date }}
192+
</td>
193+
</tr>
194+
<tr>
195+
<th scope="row">Last Updated</th>
196+
<td>
197+
{{ signal.last_updated }}
198+
</td>
199+
</tr>
182200
</tbody>
183201
</table>
184202
</div>

src/templates/signals/signals.html

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ <h5 class="card-title">Search</h5>
1818
</div>
1919
<div class="card-body">
2020
<label for="id_pathogen" class="form-label">
21-
Pathogen <a href="#" data-bs-toggle="modal" data-bs-target="#pathogen_modal">
21+
Pathogen
22+
<a href="#" data-bs-toggle="modal" data-bs-target="#pathogen_modal">
2223
<i class="bi bi-info-circle"></i>
2324
</a>
2425
</label>
@@ -42,6 +43,7 @@ <h5 class="modal-title">Pathogen</h5>
4243
</div>
4344
</div>
4445
{{ form.pathogen|as_crispy_field }}
46+
4547
</div>
4648
<div class="card-body">
4749
<label for="id_active" class="form-label">
@@ -97,6 +99,10 @@ <h5 class="modal-title">Available Geography</h5>
9799
</div>
98100
</div>
99101
</div>
102+
<div class="d-flex justify-content-evenly bulk-select">
103+
<a role="button">All</a>
104+
<a role="button">Clear</a>
105+
</div>
100106
{{ form.available_geography|as_crispy_field }}
101107
</div>
102108
<div class="card-body">
@@ -125,6 +131,10 @@ <h5 class="modal-title">Signal Type</h5>
125131
</div>
126132
</div>
127133
</div>
134+
<div class="d-flex justify-content-evenly bulk-select">
135+
<a role="button">All</a>
136+
<a role="button">Clear</a>
137+
</div>
128138
{{ form.signal_type|as_crispy_field }}
129139
</div>
130140
<div class="card-body">
@@ -153,6 +163,10 @@ <h5 class="modal-title">Category</h5>
153163
</div>
154164
</div>
155165
</div>
166+
<div class="d-flex justify-content-evenly bulk-select">
167+
<a role="button">All</a>
168+
<a role="button">Clear</a>
169+
</div>
156170
{{ form.category|as_crispy_field }}
157171
</div>
158172
<div class="card-body">
@@ -181,6 +195,10 @@ <h5 class="modal-title">Format Type</h5>
181195
</div>
182196
</div>
183197
</div>
198+
<div class="d-flex justify-content-evenly bulk-select">
199+
<a role="button">All</a>
200+
<a role="button">Clear</a>
201+
</div>
184202
{{ form.format_type|as_crispy_field }}
185203
</div>
186204
<div class="card-body">
@@ -209,6 +227,10 @@ <h5 class="modal-title">Source</h5>
209227
</div>
210228
</div>
211229
</div>
230+
<div class="d-flex justify-content-evenly bulk-select">
231+
<a role="button">All</a>
232+
<a role="button">Clear</a>
233+
</div>
212234
{{ form.source|as_crispy_field }}
213235
</div>
214236
<div class="card-body">
@@ -285,9 +307,28 @@ <h5 class="modal-title">Time Label</h5>
285307
</form>
286308

287309
<script>
310+
311+
// Add an event listener to the 'order_by' select element
288312
document.getElementById('id_order_by').addEventListener('change', function() {
289313
document.getElementById('filters-form').submit();
290314
});
315+
316+
317+
// Add an event listener to each 'bulk-select' element
318+
let bulkSelectDivs = document.querySelectorAll('.bulk-select');
319+
bulkSelectDivs.forEach(div => {
320+
div.addEventListener('click', function(event) {
321+
let form = this.nextElementSibling;
322+
let checkboxes = form.querySelectorAll('input[type="checkbox"]');
323+
324+
if (event.target.innerText === 'All') {
325+
checkboxes.forEach(checkbox => checkbox.checked = true);
326+
} else if (event.target.innerText === 'Clear') {
327+
checkboxes.forEach(checkbox => checkbox.checked = false);
328+
}
329+
});
330+
});
331+
291332
</script>
292333

293334
{% endblock %}

0 commit comments

Comments
 (0)