Skip to content

Okrs24 100 Convert dropdowns do checkboxes #86

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Mar 19, 2024
5 changes: 5 additions & 0 deletions src/assets/css/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -1240,3 +1240,8 @@ h6 {
.clickable-table-cell:hover {
cursor: pointer;
}

.bulk-select > a:nth-child(1):hover,
.bulk-select > a:nth-child(2):hover {
color: #0d6efd;
}
3 changes: 1 addition & 2 deletions src/signals/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,12 @@ class SignalAdmin(ImportExportModelAdmin):
list_display: tuple[Literal['name']] = ('name',)
search_fields: tuple[Literal['name'], Literal['description'], Literal['short_description']]
search_fields = ('name', 'description', 'short_description')
list_filter: tuple[Literal['pathogen'], Literal['available_geography'], Literal['signal_type'], Literal['format_type'],
Literal['is_smoothed'], Literal['is_weighted'], Literal['is_cumulative'], Literal['has_stderr'], Literal['has_sample_size']]
list_filter = (
'pathogen',
'available_geography',
'signal_type',
'format_type',
'time_label',
'is_smoothed',
'is_weighted',
'is_cumulative',
Expand Down
16 changes: 14 additions & 2 deletions src/signals/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,12 @@
)
from django_filters.widgets import QueryArrayWidget

from signals.models import Signal
from datasources.models import SourceSubdivision
from signals.models import (
FormatChoices,
Signal,
TimeLabelChoices,
)


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

id = NumberInFilter(field_name='id', lookup_expr='in', widget=QueryArrayWidget)
id = NumberInFilter(
field_name='id',
lookup_expr='in',
widget=QueryArrayWidget
)
search = CharFilter(method='filter_search')
order_by = OrderingFilter(
fields=(
Expand All @@ -31,6 +40,9 @@ class SignalFilter(django_filters.FilterSet):
('last_updated', 'last_updated'),
)
)
format_type = django_filters.MultipleChoiceFilter(choices=FormatChoices.choices)
source = django_filters.ModelMultipleChoiceFilter(queryset=SourceSubdivision.objects.all())
time_label = django_filters.MultipleChoiceFilter(choices=TimeLabelChoices.choices)

class Meta:
model = Signal
Expand Down
26 changes: 14 additions & 12 deletions src/signals/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@

from datasources.models import SourceSubdivision
from signals.models import (
ActiveChoices,
FormatChoices,
Pathogen,
Signal,
TimeLabelChoices,
ActiveChoices
)


Expand All @@ -18,18 +18,18 @@ class SignalFilterForm(forms.ModelForm):
id = forms.ModelMultipleChoiceField(queryset=Signal.objects.all(), widget=forms.MultipleHiddenInput)
order_by = forms.ChoiceField(choices=[
('', '---------'),
('name', 'Name'),
('source__name', 'Source'),
('last_updated', 'Last Updated'),
('name', _('Name')),
('source__name', _('Source')),
('last_updated', _('Last Updated')),
],
required=False,
)
search = forms.CharField(min_length=3)
pathogen = forms.ModelChoiceField(queryset=Pathogen.objects.all(), empty_label='---------')
pathogen = forms.ModelChoiceField(queryset=Pathogen.objects.all(), widget=forms.CheckboxSelectMultiple())
active = forms.TypedMultipleChoiceField(choices=ActiveChoices.choices, coerce=bool, widget=forms.CheckboxSelectMultiple())
format_type = forms.ChoiceField(choices=[('', '---------')] + FormatChoices.choices)
source = forms.ModelChoiceField(queryset=SourceSubdivision.objects.all(), empty_label='---------')
time_label = forms.ChoiceField(choices=[('', '---------')] + TimeLabelChoices.choices, label=_('Temporal Resolution'))
format_type = forms.ChoiceField(choices=FormatChoices.choices, widget=forms.CheckboxSelectMultiple())
source = forms.ModelMultipleChoiceField(queryset=SourceSubdivision.objects.all(), widget=forms.CheckboxSelectMultiple())
time_label = forms.ChoiceField(choices=TimeLabelChoices.choices, widget=forms.CheckboxSelectMultiple())

class Meta:
model = Signal
Expand All @@ -53,8 +53,7 @@ class Meta:
'id': 'order_by',
'aria-label': 'Order by',
}),
'search': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Enter search term'}),
'pathogen': forms.Select(attrs={'class': 'form-select'}),
'search': forms.TextInput(attrs={'class': 'form-control', 'placeholder': _('Enter search term')}),
'available_geography': forms.CheckboxSelectMultiple(attrs={
'class': 'form-select',
'data-bs-toggle': 'tooltip',
Expand All @@ -70,13 +69,16 @@ class Meta:
'data-bs-toggle': 'tooltip',
'data-bs-placement': 'bottom',
}),
'format_type': forms.Select(attrs={'class': 'form-control'}),
'format_type': forms.CheckboxSelectMultiple(attrs={
'class': 'form-select',
'data-bs-toggle': 'tooltip',
'data-bs-placement': 'bottom',
}),
'source': forms.CheckboxSelectMultiple(attrs={
'class': 'form-select',
'data-bs-toggle': 'tooltip',
'data-bs-placement': 'bottom',
}),
'time_label': forms.Select(attrs={'class': 'form-select'}),
}

def __init__(self, *args, **kwargs):
Expand Down
16 changes: 6 additions & 10 deletions src/signals/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

from signals.filters import SignalFilter
from signals.forms import SignalFilterForm
from signals.models import Signal
from signals.models import Pathogen, Signal
from signals.serializers import SignalSerializer


Expand Down Expand Up @@ -38,9 +38,9 @@ def get_url_params(self):
url_params_dict = {
"id": self.request.GET.get("id"),
"search": self.request.GET.get("search"),
"pathogen": int(self.request.GET.get("pathogen"))
"pathogen": [el for el in self.request.GET._getlist("pathogen")]
if self.request.GET.get("pathogen")
else "",
else [el.id for el in Pathogen.objects.all()],
"active": [el for el in self.request.GET._getlist("active")]
if self.request.GET.get("active")
else [True, False],
Expand All @@ -55,13 +55,9 @@ def get_url_params(self):
"category": self.request.GET._getlist("category")
if self.request.GET.get("category")
else None,
"format_type": self.request.GET.get("format_type"),
"source": int(self.request.GET.get("source"))
if self.request.GET.get("source")
else "",
"time_label": self.request.GET.get("time_label")
if self.request.GET.get("time_label")
else "",
"format_type": [el for el in self.request.GET._getlist("format_type")],
"source": [int(el) for el in self.request.GET._getlist("source")],
"time_label": [el for el in self.request.GET._getlist("time_label")]
}
url_params_str = ""
for param_name, param_value in url_params_dict.items():
Expand Down
18 changes: 18 additions & 0 deletions src/templates/signals/signal_detail.html
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,24 @@ <h5>About this signal</h5>
{% endif %}
</td>
</tr>
<tr>
<th scope="row">Available Since</th>
<td>
{{ signal.from_date }}
</td>
</tr>
<tr>
<th scope="row">Available Until</th>
<td>
{{ signal.to_date }}
</td>
</tr>
<tr>
<th scope="row">Last Updated</th>
<td>
{{ signal.last_updated }}
</td>
</tr>
</tbody>
</table>
</div>
Expand Down
43 changes: 42 additions & 1 deletion src/templates/signals/signals.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ <h5 class="card-title">Search</h5>
</div>
<div class="card-body">
<label for="id_pathogen" class="form-label">
Pathogen <a href="#" data-bs-toggle="modal" data-bs-target="#pathogen_modal">
Pathogen
<a href="#" data-bs-toggle="modal" data-bs-target="#pathogen_modal">
<i class="bi bi-info-circle"></i>
</a>
</label>
Expand All @@ -42,6 +43,7 @@ <h5 class="modal-title">Pathogen</h5>
</div>
</div>
{{ form.pathogen|as_crispy_field }}

</div>
<div class="card-body">
<label for="id_active" class="form-label">
Expand Down Expand Up @@ -97,6 +99,10 @@ <h5 class="modal-title">Available Geography</h5>
</div>
</div>
</div>
<div class="d-flex justify-content-evenly bulk-select">
<a role="button">All</a>
<a role="button">Clear</a>
</div>
{{ form.available_geography|as_crispy_field }}
</div>
<div class="card-body">
Expand Down Expand Up @@ -125,6 +131,10 @@ <h5 class="modal-title">Signal Type</h5>
</div>
</div>
</div>
<div class="d-flex justify-content-evenly bulk-select">
<a role="button">All</a>
<a role="button">Clear</a>
</div>
{{ form.signal_type|as_crispy_field }}
</div>
<div class="card-body">
Expand Down Expand Up @@ -153,6 +163,10 @@ <h5 class="modal-title">Category</h5>
</div>
</div>
</div>
<div class="d-flex justify-content-evenly bulk-select">
<a role="button">All</a>
<a role="button">Clear</a>
</div>
{{ form.category|as_crispy_field }}
</div>
<div class="card-body">
Expand Down Expand Up @@ -181,6 +195,10 @@ <h5 class="modal-title">Format Type</h5>
</div>
</div>
</div>
<div class="d-flex justify-content-evenly bulk-select">
<a role="button">All</a>
<a role="button">Clear</a>
</div>
{{ form.format_type|as_crispy_field }}
</div>
<div class="card-body">
Expand Down Expand Up @@ -209,6 +227,10 @@ <h5 class="modal-title">Source</h5>
</div>
</div>
</div>
<div class="d-flex justify-content-evenly bulk-select">
<a role="button">All</a>
<a role="button">Clear</a>
</div>
{{ form.source|as_crispy_field }}
</div>
<div class="card-body">
Expand Down Expand Up @@ -285,9 +307,28 @@ <h5 class="modal-title">Time Label</h5>
</form>

<script>

// Add an event listener to the 'order_by' select element
document.getElementById('id_order_by').addEventListener('change', function() {
document.getElementById('filters-form').submit();
});


// Add an event listener to each 'bulk-select' element
let bulkSelectDivs = document.querySelectorAll('.bulk-select');
bulkSelectDivs.forEach(div => {
div.addEventListener('click', function(event) {
let form = this.nextElementSibling;
let checkboxes = form.querySelectorAll('input[type="checkbox"]');

if (event.target.innerText === 'All') {
checkboxes.forEach(checkbox => checkbox.checked = true);
} else if (event.target.innerText === 'Clear') {
checkboxes.forEach(checkbox => checkbox.checked = false);
}
});
});

</script>

{% endblock %}