Skip to content

Commit

Permalink
Merge pull request #376 from onaio/add_stations_centers_filters
Browse files Browse the repository at this point in the history
Add race, station and centers filter in and out options
  • Loading branch information
lincmba authored May 8, 2023
2 parents 6197372 + 2bdb84f commit 7a3c66e
Show file tree
Hide file tree
Showing 4 changed files with 251 additions and 22 deletions.
136 changes: 136 additions & 0 deletions tally_ho/apps/tally/static/js/data_table.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,13 @@ $(document).ready(function () {
let data = [];
let selectOneIds = $('select#centers').val();
let selectTwoIds = $('select#stations').val();
let raceTypeNames = $('select#filter-out-race-types').val();

if (selectOneIds || selectTwoIds) {
const items = {
select_1_ids: selectOneIds !== null ? selectOneIds : [],
select_2_ids: selectTwoIds !== null ? selectTwoIds : [],
race_type_names: raceTypeNames !== null ? raceTypeNames : [],
};

data = items;
Expand Down Expand Up @@ -148,6 +150,140 @@ $(document).ready(function () {
});
});

$('#in-report').on('click', '#filter-in-report', function () {
const table = $('.datatable').DataTable();

table.destroy();
let data = [];
let selectOneIds = $('select#filter-in-centers').val();
let selectTwoIds = $('select#filter-in-stations').val();
let raceTypeNames = $('select#filter-in-race-types').val();

if (selectOneIds || selectTwoIds) {
const items = {
select_1_ids: selectOneIds !== null ? selectOneIds : [],
select_2_ids: selectTwoIds !== null ? selectTwoIds : [],
race_type_names: raceTypeNames !== null ? raceTypeNames : [],
filter_in: "True"
};

data = items;
}

data = data.length
? data.filter((item) =>
Object.values(item).every((value) => typeof value !== 'undefined')
)
: data;

$('.datatable').dataTable({
language: dt_language,
order: [[0, 'desc']],
lengthMenu: [
[10, 25, 50, 100, 500],
[10, 25, 50, 100, 500],
],
columnDefs: [
{
orderable: true,
searchable: true,
className: 'center',
targets: [0, 1],
},
],
searching: true,
processing: true,
serverSide: true,
stateSave: true,
ajax: {
url: LIST_JSON_URL,
type: 'POST',
data: { data: JSON.stringify(data) },
traditional: true,
dataType: 'json',
},
dom:
"<'row'<'col-sm-1'B><'col-sm-6'l><'col-sm-5'f>>" +
"<'row'<'col-sm-12'tr>>" +
"<'row'<'col-sm-5'i><'col-sm-7'p>>",
buttons: [
{
extend: 'csv',
filename: exportFileName,
action: exportAction,
exportOptions: {
columns: ':visible :not(.actions)',
},
},
],
responsive: true,
});
});
$('#race-report').on('click', '#filter-race-report', function () {
const table = $('.datatable').DataTable();

table.destroy();
let data = [];
let raceTypeNames = $('select#filter-in-race-types').val();

if (raceTypeNames ) {
const items = {
race_type_names: raceTypeNames !== null ? raceTypeNames : [],
};

data = items;
}

data = data.length
? data.filter((item) =>
Object.values(item).every((value) => typeof value !== 'undefined')
)
: data;

$('.datatable').dataTable({
language: dt_language,
order: [[0, 'desc']],
lengthMenu: [
[10, 25, 50, 100, 500],
[10, 25, 50, 100, 500],
],
columnDefs: [
{
orderable: true,
searchable: true,
className: 'center',
targets: [0, 1],
},
],
searching: true,
processing: true,
serverSide: true,
stateSave: true,
ajax: {
url: LIST_JSON_URL,
type: 'POST',
data: { data: JSON.stringify(data) },
traditional: true,
dataType: 'json',
},
dom:
"<'row'<'col-sm-1'B><'col-sm-6'l><'col-sm-5'f>>" +
"<'row'<'col-sm-12'tr>>" +
"<'row'<'col-sm-5'i><'col-sm-7'p>>",
buttons: [
{
extend: 'csv',
filename: exportFileName,
action: exportAction,
exportOptions: {
columns: ':visible :not(.actions)',
},
},
],
responsive: true,
});
});

$('#report').on('click', '#reset', function () {
const table = $('.datatable').DataTable();

Expand Down
25 changes: 24 additions & 1 deletion tally_ho/apps/tally/static/js/get_centers_stations.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
$(document).ready(function () {
$('#centers').change(function () {
const center_ids = $('.selectpicker').val();
const center_ids = $('#centers').val();

if (center_ids) {
$.ajax({
Expand All @@ -23,4 +23,27 @@ $(document).ready(function () {
$('.center-stations').selectpicker('refresh');
}
});
$('#filter-in-centers').change(function () {
const center_ids = $('#filter-in-centers').val();
if (center_ids) {
$.ajax({
url: getCentersStationsUrl,
data: {
data: JSON.stringify({
center_ids: center_ids,
tally_id: tallyId,
}),
},
traditional: true,
dataType: 'json',
success: (data) => {
const { station_ids } = data;
$('.filter-in-center-stations').selectpicker('val', station_ids);
},
});
} else {
$('.filter-in-center-stations').selectpicker('deselectAll');
$('.filter-in-center-stations').selectpicker('refresh');
}
});
});
55 changes: 50 additions & 5 deletions tally_ho/apps/tally/templates/reports/form_results.html
Original file line number Diff line number Diff line change
Expand Up @@ -26,32 +26,77 @@ <h1>{% trans 'Form Results' %}</h1>
<button style="float: left; margin-bottom: 2em;" id="export-form-results-presidential" class="btn btn-default btn-small">{% trans 'Export Presidential Results in JSON' %}</button>
<button style="float: left; margin-left: 1em; margin-bottom: 2em;" id="export-form-results-parliamentary" class="btn btn-default btn-small">{% trans 'Export Parliamentary Results in JSON' %}</button>
</div>
<div class="col-sm-4">
<p style="text-align: left; margin-left: .5em;">Centers</p>
<div class="col-sm-3">
<p style="text-align: left; margin-left: .5em;">{% trans 'Races' %}</p>
<select class="selectpicker" id="filter-out-race-types" name="report_length" aria-controls="report" multiple data-actions-box="true" title="Select Race Type">
{% for race_type in race_types %}
<option value={{race_type.name}}>{{race_type.name}}</option>
{% endfor %}
</select>
</div>
<div class="col-sm-3">
<p style="text-align: left; margin-left: .5em;">{% trans 'Centers' %}</p>
<select class="selectpicker" id="centers" name="report_length" aria-controls="report" multiple data-actions-box="true" title="Select Centers">
{% for center in centers %}
<option value={{center.id}}>{{center.name}}</option>
{% endfor %}
</select>
</div>
<div class="col-sm-4">
<div class="col-sm-3">
<p style="text-align: left; margin-left: .5em;">{% trans 'Stations' %}</p>
<select class="selectpicker center-stations" id="stations" name="report_length" aria-controls="report" multiple data-actions-box="true" title="Select Stations">
{% for station in stations %}
<option value={{station.id}}>{{station.id}}</option>
{% endfor %}
</select>
</div>
<div class="col-sm-4">
<div class="col-sm-3">
<div class="card">
<div class="card-body">
<p class="card-text" style="text-align: left;">{% trans 'Filter out Centers and Stations from results.' %}</p>
<p class="card-text" style="text-align: left;">{% trans 'Filter Out.' %}</p>
<button style="float: left;" id="filter-report" class="btn btn-default btn-small">{% trans 'Apply' %}</button>
<a href='.' style="float: left; margin-left: 1em;" class="btn btn-default btn-small">{% trans 'Reset' %}</a>
</div>
</div>
</div>
</div>
</caption>
<caption style="margin-top: 2em; margin-left: -0.5em; margin-bottom: 2em;">
<div id="in-report" class="row">
<div class="col-sm-3">
<p style="text-align: left; margin-left: .5em;">{% trans 'Races' %}</p>
<select class="selectpicker" id="filter-in-race-types" name="report_length" aria-controls="report" multiple data-actions-box="true" title="Select Race Type">
{% for race_type in race_types %}
<option value={{race_type.name}}>{{race_type.name}}</option>
{% endfor %}
</select>
</div>
<div class="col-sm-3">
<p style="text-align: left; margin-left: .5em;">{% trans 'Centers' %}</p>
<select class="selectpicker" id="filter-in-centers" name="report_length" aria-controls="report" multiple data-actions-box="true" title="Select Centers">
{% for center in centers %}
<option value={{center.id}}>{{center.name}}</option>
{% endfor %}
</select>
</div>
<div class="col-sm-3">
<p style="text-align: left; margin-left: .5em;">{% trans 'Stations' %}</p>
<select class="selectpicker filter-in-center-stations" id="filter-in-stations" name="report_length" aria-controls="report" multiple data-actions-box="true" title="Select Stations">
{% for station in stations %}
<option value={{station.id}}>{{station.id}}</option>
{% endfor %}
</select>
</div>
<div class="col-sm-3">
<div class="card">
<div class="card-body">
<p class="card-text" style="text-align: left;">{% trans 'Filter In.' %}</p>
<button style="float: left;" id="filter-in-report" class="btn btn-default btn-small">{% trans 'Apply' %}</button>
<a href='.' style="float: left; margin-left: 1em;" class="btn btn-default btn-small">{% trans 'Reset' %}</a>
</div>
</div>
</div>
</div>
</caption>
<br>
<thead>
Expand Down
57 changes: 41 additions & 16 deletions tally_ho/apps/tally/views/reports/administrative_areas_reports.py
Original file line number Diff line number Diff line change
Expand Up @@ -555,26 +555,48 @@ def results_queryset(

if data:
selected_center_ids =\
data['select_1_ids'] if len(data['select_1_ids']) else [0]
data['select_1_ids'] if data.get('select_1_ids') else [0]
selected_station_ids =\
data['select_2_ids'] if len(data['select_2_ids']) else [0]

qs = qs\
data['select_2_ids'] if data.get('select_2_ids') else [0]
race_type_names = data['race_type_names'] if data.get('race_type_names') else []
race_types = [race_type for race_type in RaceType if race_type.name in race_type_names]
filter_in = data.get('filter_in')
qs = qs \
.annotate(station_ids=station_id_query)

qs_1 = qs\
.filter(
~Q(result_form__center__id__in=selected_center_ids) &
~Q(station_ids__in=selected_station_ids))\
.annotate(candidate_name=F('candidate__full_name'))\
.filter(candidate_name__isnull=False)
if filter_in:
if race_types:
qs = qs.filter(Q(result_form__ballot__race_type__in=race_types))
qs_1 = qs \
.filter(
Q(result_form__center__id__in=selected_center_ids) &
Q(station_ids__in=selected_station_ids)) \
.annotate(candidate_name=F('candidate__full_name')) \
.filter(candidate_name__isnull=False)

qs_2 = qs\
.filter(
~Q(result_form__center__id__in=selected_center_ids) &
~Q(station_ids__in=selected_station_ids))\
.annotate(candidate_name=F(ballot_comp_candidate_name))\
.filter(candidate_name__isnull=False)
qs_2 = qs \
.filter(
Q(result_form__center__id__in=selected_center_ids) &
Q(station_ids__in=selected_station_ids)) \
.annotate(candidate_name=F(ballot_comp_candidate_name)) \
.filter(candidate_name__isnull=False)

else:
if race_types:
qs = qs.filter(~Q(result_form__ballot__race_type__in=race_types))
qs_1 = qs\
.filter(
~Q(result_form__center__id__in=selected_center_ids) &
~Q(station_ids__in=selected_station_ids))\
.annotate(candidate_name=F('candidate__full_name'))\
.filter(candidate_name__isnull=False)

qs_2 = qs\
.filter(
~Q(result_form__center__id__in=selected_center_ids) &
~Q(station_ids__in=selected_station_ids))\
.annotate(candidate_name=F(ballot_comp_candidate_name))\
.filter(candidate_name__isnull=False)

qs = qs_1.union(qs_2) if len(qs_2) else qs_1

Expand Down Expand Up @@ -652,6 +674,7 @@ def results_queryset(
result_form__reconciliationform__isnull=False,
then=F(reconform_num_valid_votes)
), default=V(0))).distinct()

else:
qs_1 = qs\
.annotate(candidate_name=F('candidate__full_name'))\
Expand Down Expand Up @@ -3217,13 +3240,15 @@ class ResultFormResultsListView(LoginRequiredMixin,
def get(self, request, *args, **kwargs):
tally_id = kwargs.get('tally_id')
stations, centers = build_station_and_centers_list(tally_id)
race_types = list(RaceType)
language_de = get_datatables_language_de_from_locale(self.request)

return self.render_to_response(self.get_context_data(
remote_url=reverse('form-results-data', kwargs=kwargs),
tally_id=tally_id,
stations=stations,
centers=centers,
race_types=race_types,
get_centers_stations_url='/ajax/get-centers-stations/',
results_download_url='/ajax/download-results/',
languageDE=language_de
Expand Down

0 comments on commit 7a3c66e

Please sign in to comment.