diff --git a/django_project/event_mapper/static/event_mapper/css/event_mapper.css b/django_project/event_mapper/static/event_mapper/css/event_mapper.css index 9005128..992f3a5 100755 --- a/django_project/event_mapper/static/event_mapper/css/event_mapper.css +++ b/django_project/event_mapper/static/event_mapper/css/event_mapper.css @@ -10,11 +10,11 @@ .btn.btn-fab, .btn.btn-fab:hover { box-shadow: none !important; } + .pad0 { padding: 0; } - /* -------------------------- */ /* NAVBAR */ /* -------------------------- */ @@ -49,10 +49,12 @@ font-weight: bold; color: #292929; } + .graph-boxes:after { - content:''; + content: ''; clear: both; } + .graph-box { background: #fff; width: 50%; @@ -61,6 +63,7 @@ border: 1px solid #ececeb; color: #575757; } + .graph-box h3 { font-size: 14px; background: #fbfbfb; @@ -68,17 +71,21 @@ margin-top: 0; border-bottom: 1px solid #ececeb; } + .graph-box > div { padding: 10px 20px; } + .graph-box .half { display: inline-block; } + .graph-box .half .number { font-size: 60px; font-weight: bold; padding-top: 20px; } + .graph-box .half .label { font-size: 16px; font-weight: 500; @@ -86,15 +93,18 @@ color: #575757; padding: 0; } + .search-box { background: #fff; border: 1px solid #ececeb; color: #575757; padding: 10px 20px; } + .search-box input { min-width: 300px; } + #visualization { font-family: Arial, Helvetica, sans-serif; font-size: 12px; @@ -151,6 +161,7 @@ background-color: dimgray; cursor: default; } + .switch-layers { position: absolute; top: 20px; @@ -160,3 +171,8 @@ border-radius: 5px; z-index: 50; } + +.chart-section { + width: 320px; + height: 150px; +} \ No newline at end of file diff --git a/django_project/event_mapper/static/event_mapper/css/images/green-marker-icon-2x.png b/django_project/event_mapper/static/event_mapper/css/images/green-marker-icon-2x.png new file mode 100644 index 0000000..ba42baa Binary files /dev/null and b/django_project/event_mapper/static/event_mapper/css/images/green-marker-icon-2x.png differ diff --git a/django_project/event_mapper/static/event_mapper/css/images/lightgreen-marker-icon-2x.png b/django_project/event_mapper/static/event_mapper/css/images/lightgreen-marker-icon-2x.png new file mode 100644 index 0000000..ad433b1 Binary files /dev/null and b/django_project/event_mapper/static/event_mapper/css/images/lightgreen-marker-icon-2x.png differ diff --git a/django_project/event_mapper/static/event_mapper/css/images/orange-marker-icon-2x.png b/django_project/event_mapper/static/event_mapper/css/images/orange-marker-icon-2x.png new file mode 100644 index 0000000..7c07b51 Binary files /dev/null and b/django_project/event_mapper/static/event_mapper/css/images/orange-marker-icon-2x.png differ diff --git a/django_project/event_mapper/static/event_mapper/css/images/red-marker-icon-2x.png b/django_project/event_mapper/static/event_mapper/css/images/red-marker-icon-2x.png new file mode 100644 index 0000000..b625ee2 Binary files /dev/null and b/django_project/event_mapper/static/event_mapper/css/images/red-marker-icon-2x.png differ diff --git a/django_project/event_mapper/static/event_mapper/css/images/yellow-marker-icon-2x.png b/django_project/event_mapper/static/event_mapper/css/images/yellow-marker-icon-2x.png new file mode 100644 index 0000000..45aff62 Binary files /dev/null and b/django_project/event_mapper/static/event_mapper/css/images/yellow-marker-icon-2x.png differ diff --git a/django_project/event_mapper/static/event_mapper/js/event_dashboard.js b/django_project/event_mapper/static/event_mapper/js/event_dashboard.js index 852a46e..5908204 100644 --- a/django_project/event_mapper/static/event_mapper/js/event_dashboard.js +++ b/django_project/event_mapper/static/event_mapper/js/event_dashboard.js @@ -1,6 +1,16 @@ /** * Created by ismailsunni on 5/9/15. */ +Array.prototype.remove = function () { + var what, a = arguments, L = a.length, ax; + while (L && this.length) { + what = a[--L]; + while ((ax = this.indexOf(what)) !== -1) { + this.splice(ax, 1); + } + } + return this; +}; // Variables var markers = []; @@ -9,6 +19,12 @@ var ADVISORY_CODE = 2; var pie_chart; var selected_marker = null; +// filtering variable +var by_types = {}; +var by_datacaptor = {}; +var by_overall_assessment = {}; +var unchecked_statistic = []; + function normalize_json_string(string) { return string.replace(/\n/g, '
').slice(6, -6) @@ -213,6 +229,9 @@ function add_event_marker(event_context) { var raw_incident_icon = event_context['properties']['incident_icon']; var raw_advisory_icon = event_context['properties']['advisory_icon']; var raw_active_icon; // The icon that will be used in the dashboard + // additional info + var overal_assessment = event_context['properties']['overal_assessment']; + var healthsite_type = event_context['properties']['healthsite_type']; // Draw event marker if (event_category == 1) { @@ -220,6 +239,17 @@ function add_event_marker(event_context) { } else if (event_category == 2) { raw_active_icon = raw_advisory_icon; } + if (overal_assessment == 1) { + raw_active_icon = "/static/event_mapper/css/images/red-marker-icon-2x.png"; + } else if (overal_assessment == 2) { + raw_active_icon = "/static/event_mapper/css/images/orange-marker-icon-2x.png"; + } else if (overal_assessment == 3) { + raw_active_icon = "/static/event_mapper/css/images/yellow-marker-icon-2x.png"; + } else if (overal_assessment == 4) { + raw_active_icon = "/static/event_mapper/css/images/lightgreen-marker-icon-2x.png"; + } else if (overal_assessment == 5) { + raw_active_icon = "/static/event_mapper/css/images/green-marker-icon-2x.png"; + } var latlng = L.latLng(lat, lng); var is_selected = is_selected_marker(latlng, event_place_name); @@ -230,6 +260,7 @@ function add_event_marker(event_context) { } if (event_icon) { + // render marker event_marker = L.marker( latlng, { @@ -251,14 +282,36 @@ function add_event_marker(event_context) { event_detained: event_detained, event_source: event_source, event_notes: event_notes, - event_reported_by: event_reported_by + event_reported_by: event_reported_by, + event_overal_assessment: overal_assessment, + event_healthsite_type: healthsite_type }; if (is_selected) { event_marker.options.event_selected = true; } - if (checkbox_event_is_checked()) { + if (is_event_in_hide(event_marker)) { event_marker.addTo(map); } + + // get the list number + var assess_identifier = "assess_" + overal_assessment; + var type_identifier = "type_" + healthsite_type; + var datacaptor_identifier = "datacaptor_" + event_reported_by; + if (assess_identifier in by_overall_assessment) { + by_overall_assessment[assess_identifier].push(event_marker); + } else { + by_overall_assessment[assess_identifier] = [event_marker]; + } + if (type_identifier in by_types) { + by_types[type_identifier].push(event_marker); + } else { + by_types[type_identifier] = [event_marker]; + } + if (datacaptor_identifier in by_datacaptor) { + by_datacaptor[datacaptor_identifier].push(event_marker); + } else { + by_datacaptor[datacaptor_identifier] = [event_marker]; + } } else { event_marker = L.marker( [lat, lng], {id: event_id}).addTo(map); @@ -307,6 +360,9 @@ function get_event_markers(items) { dataType: 'json', success: function (json) { clear_event_markers(); + by_datacaptor = {}; + by_overall_assessment = {}; + by_types = {}; var num_incident = 0; var num_advisory = 0; var events = json['events']['features']; @@ -319,23 +375,16 @@ function get_event_markers(items) { } } $('#num_events').text(events.length); - var num_events_events = $('#num_events_events'); - if (events.length == 1) { - num_events_events.text(' Alert'); - } else { - num_events_events.text(' Alerts'); - } var side_panel = $('#side_panel'); - if (!selected_marker) { - if (side_panel.is(":visible")) { - // Only create chart when the side panel is visible - create_chart( - { - advisory: num_advisory, - incident: num_incident - }); - } + if (!selected_marker && side_panel.is(":visible")) { + // Only create chart when the side panel is visible + //create_chart( + // { + // advisory: num_advisory, + // incident: num_incident + // }); } + render_statistic(); }, errors: function () { console.log('Ajax failed'); @@ -343,6 +392,21 @@ function get_event_markers(items) { }) } +function is_event_in_hide(marker) { + if (!$("#event-filter").is(':checked')) { + return false; + } + var assess_identifier = "assess_" + marker.data.event_overal_assessment; + var type_identifier = "type_" + marker.data.event_healthsite_type; + var datacaptor_identifier = "datacaptor_" + marker.data.event_reported_by; + + var is_checked = true; + if ($.inArray(assess_identifier, unchecked_statistic) > -1 || $.inArray(type_identifier, unchecked_statistic) > -1 || $.inArray(datacaptor_identifier, unchecked_statistic) > -1) { + is_checked = false; + } + return is_checked; +} + function clear_event_markers() { hide_event_markers(); markers = []; @@ -359,8 +423,10 @@ function hide_event_markers() { function show_event_markers() { for (var i = 0; i < markers.length; i++) { if (markers[i]) { - map.removeLayer(markers[i]); - map.addLayer(markers[i]); + if (is_event_in_hide(markers[i])) { + map.removeLayer(markers[i]); + map.addLayer(markers[i]); + } } } } @@ -373,6 +439,96 @@ function checkbox_event_is_checked() { } } +function render_statistic() { + // render statistic + // overal assessment + $("#overall_assessment_chart").html(""); + $("#data_captor_chart").html(""); + $("#type_chart").html(""); + for (var i = 5; i >= 1; i--) { + var name = 'assess_' + i; + var html = ' -1; + if (!found) { + html += ' checked'; + } + html += '>' + name + ' : ' + by_overall_assessment[name].length + '
'; + $("#overall_assessment_chart").append(html); + } + // type_chart + var keys = Object.keys(by_types).sort(); + for (var i = 0; i < keys.length && i < 5; i++) { + var name = keys[i]; + var html = ' -1; + if (!found) { + html += ' checked'; + } + html += '>' + name + ' : ' + by_types[keys[i]].length + '
'; + $("#type_chart").append(html); + } + + // datacaptor + var keys = Object.keys(by_datacaptor).sort(); + for (var i = 0; i < keys.length && i < 5; i++) { + var name = keys[i]; + var html = ' -1; + if (!found) { + html += ' checked'; + } + html += '>' + name + ' : ' + by_datacaptor[keys[i]].length + '
'; + $("#data_captor_chart").append(html); + } + + // checkbox onchange + $(':checkbox').change(function () { + if ($(this).attr('id') == "healthsites-filter") { + if (checkbox_healthsites_is_checked()) { + show_healthsites_markers(); + } else { + hide_healthsites_markers(); + } + } else if ($(this).attr('id') == "event-filter") { + if (checkbox_event_is_checked()) { + show_event_markers(); + } else { + hide_event_markers(); + } + } else { + statistic_clicked(this); + } + }); +} + +function statistic_clicked(element) { + var name = $(element).attr('name'); + var is_checked = $(element).is(':checked'); + unchecked_statistic.remove(name); + if (!is_checked) { + unchecked_statistic.push(name); + } + // rerender the markers + var identifier = name.split("_")[0]; + var temp_markers = {}; + if (identifier == "assess") { + temp_markers = by_overall_assessment[name]; + } else if (identifier == "datacaptor") { + temp_markers = by_datacaptor[name]; + } else if (identifier == "type") { + temp_markers = by_types[name]; + } + if (!is_checked) { + for (var i = 0; i < temp_markers.length; i++) { + if (temp_markers[i]) { + map.removeLayer(temp_markers[i]); + } + } + } else { + show_event_markers(); + } +} + // -------------------------------------------------------------------- // HEALTHSITES // -------------------------------------------------------------------- @@ -451,7 +607,8 @@ function render_healthsite_marker(latlng, myIcon, data) { 'bbox': data['minbbox'], 'count': data['count'], 'name': data['name'], - 'event_place_name': data['name'] + 'event_place_name': data['name'], + 'event_killed': latlng, }; if (is_selected_marker(latlng, data['name'])) { mrk.options.event_selected = true; diff --git a/django_project/event_mapper/templates/event_mapper/event/event_dashboard.html b/django_project/event_mapper/templates/event_mapper/event/event_dashboard.html index d200fd2..921d3cf 100755 --- a/django_project/event_mapper/templates/event_mapper/event/event_dashboard.html +++ b/django_project/event_mapper/templates/event_mapper/event/event_dashboard.html @@ -1,47 +1,54 @@
-

Assessment Dashboard

+

Assessment Dashboard

-
-
-
- 0
- total
healthsites
-
-
- 0
- assessed
healthsites
-
-
-
-

By overall assessment

-
- +
+
+
+ 0
+ total
healthsites
+
+
+ 0
+ assessed
healthsites
+
-
-
-

By type

-
- +
+

By overall assessment

+
+
+
-
-
-

By datacaptor

-
- +
+

By type

+
+ {# #} +
+
+
+

By datacaptor

+
+
+ +
+
+ +
+ + -
- - -

Select reporting period (UTC):

diff --git a/django_project/event_mapper/templates/event_mapper/event/event_dashboard_page.html b/django_project/event_mapper/templates/event_mapper/event/event_dashboard_page.html index 45da62f..e8a6068 100755 --- a/django_project/event_mapper/templates/event_mapper/event/event_dashboard_page.html +++ b/django_project/event_mapper/templates/event_mapper/event/event_dashboard_page.html @@ -28,8 +28,8 @@ { id: 1, content: 'reporting period', - start: '2016-04-02', - end: '2016-04-20' + start: start_date, + end: end_date } ]); @@ -92,30 +92,16 @@ get_healthsites_markers(); get_event_markers(items); - - // checkbox onchange - $(':checkbox').change(function () { - if ($(this).attr('id') == "healthsites-filter") { - if (checkbox_healthsites_is_checked()) { - show_healthsites_markers(); - } else { - hide_healthsites_markers(); - } - } else if ($(this).attr('id') == "event-filter") { - if (checkbox_event_is_checked()) { - show_event_markers(); - } else { - hide_event_markers(); - } - } - }); //same height for the graphs - var maxHeight=0; - $('.graph-box').each(function() { + var maxHeight = 0; + $('.graph-box').each(function () { maxHeight = Math.max(maxHeight, $(this).height()); - + }); - $('.graph-box').css({height:maxHeight + 'px'}); + $('.graph-box').css({height: maxHeight + 'px'}); + + // fill the number of healthsites + $("#num_hs").html("{{ healthsites_num }}") }); function updatePeriodReport(start, end) { @@ -154,9 +140,10 @@ {# map #}
- healthsites - assessment + healthsites + assessment
{% include "event_mapper/map.html" %}
diff --git a/django_project/event_mapper/templates/event_mapper/map.html b/django_project/event_mapper/templates/event_mapper/map.html index adf9f4d..226f9e0 100644 --- a/django_project/event_mapper/templates/event_mapper/map.html +++ b/django_project/event_mapper/templates/event_mapper/map.html @@ -1,2 +1,2 @@ -
+
diff --git a/django_project/event_mapper/views/dummy.py b/django_project/event_mapper/views/dummy.py new file mode 100644 index 0000000..7a98beb --- /dev/null +++ b/django_project/event_mapper/views/dummy.py @@ -0,0 +1,273 @@ +# coding=utf-8 +__author__ = 'Irwan Fathurrahman ' +__date__ = '28/04/16' +__license__ = "GPL" +__copyright__ = 'kartoza.com' + +dummy_data = { + "events": { + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": { + "id": "3", + "place_name": "Salah Al Deen Al Ayyoubi, Jordanie", + "category": "1", + "date_time": "April 12, 2016, 9:45 p.m.", + "type": "Annual assessment", + "perpetrator": "MSF staff", + "victim": "", + "killed": 3, + "injured": 9, + "detained": 5, + "source": ""http://edition.cnn.com/2016/02/02/politics/who-is-ted-cruz/index.html"", + "notes": """", + "reported_by": "Irwan Fathurrahman", + "incident_icon": "/media/event_type_icon/healthsite.png", + "advisory_icon": "/media/event_type_icon/healthsite_DjOTF5t.png", + "overal_assessment": 2, + "healthsite_type": "Hospital", + }, + "geometry": { + "type": "Point", + "coordinates": [35.9304428101, 31.9548931912] + } + }, + { + "type": "Feature", + "properties": { + "id": "4", + "place_name": "MEasharim Hopital", + "category": "1", + "date_time": "April 12, 2016, 2:56 p.m.", + "type": "1st assessment", + "perpetrator": "MSF staff", + "victim": "", + "killed": 5, + "injured": 5, + "detained": 0, + "source": ""https://drive.google.com/folderview?id=0B18NcnUTjJFAaFJ6dVBPRXliRnc&usp=sharing&tid=0B18NcnUTjJFAck93RnUzSV9kZm8"", + "notes": """", + "reported_by": "Irwan Fathurrahman", + "incident_icon": "/media/static/event_mapper/css/images/leaflet/marker-icon.png", + "advisory_icon": "/media/static/event_mapper/css/images/leaflet/marker-icon.png", + "overal_assessment": 3, + "healthsite_type": "Hospital", + }, + "geometry": { + "type": "Point", + "coordinates": [35.2458143234, 31.7807877323] + } + }, + { + "type": "Feature", + "properties": { + "id": "5", + "place_name": "King Abdallah I, Jordanie", + "category": "1", + "date_time": "April 12, 2016, 2:28 p.m.", + "type": "Annual assessment", + "perpetrator": "", + "victim": "", + "killed": 0, + "injured": 0, + "detained": 0, + "source": """", + "notes": """", + "reported_by": "Irwan Fathurrahman", + "incident_icon": "/media/event_type_icon/healthsite.png", + "advisory_icon": "/media/event_type_icon/healthsite_DjOTF5t.png", + "overal_assessment": 1, + "healthsite_type": "Hospital", + }, + "geometry": { + "type": "Point", + "coordinates": [35.9740877151, 31.9737891624] + } + }, + { + "type": "Feature", + "properties": { + "id": "6", + "place_name": "طريق طوارئ المستشفى، Ar Ramadi, Irak", + "category": "1", + "date_time": "April 12, 2016, 2:17 p.m.", + "type": "Repeat assesment", + "perpetrator": "", + "victim": "", + "killed": 34, + "injured": 44, + "detained": 55, + "source": """", + "notes": """", + "reported_by": "Irwan Fathurrahman", + "incident_icon": "/media/static/event_mapper/css/images/leaflet/marker-icon.png", + "advisory_icon": "/media/static/event_mapper/css/images/leaflet/marker-icon.png", + "overal_assessment": 3, + "healthsite_type": "Hospital", + }, + "geometry": { + "type": "Point", + "coordinates": [43.3088779449, 33.4359538848] + } + }, + { + "type": "Feature", + "properties": { + "id": "7", + "place_name": "Hospital المستشفى, Hospital", + "category": "1", + "date_time": "April 12, 2016, 2:17 p.m.", + "type": "Repeat assesment", + "perpetrator": "", + "victim": "", + "killed": 34, + "injured": 44, + "detained": 55, + "source": """", + "notes": """", + "reported_by": "Irwan Fathurrahman", + "incident_icon": "/media/static/event_mapper/css/images/leaflet/marker-icon.png", + "advisory_icon": "/media/static/event_mapper/css/images/leaflet/marker-icon.png", + "overal_assessment": 5, + "healthsite_type": "Hospital", + }, + "geometry": { + "type": "Point", + "coordinates": [33.95258, 28.56668] + } + }, + { + "type": "Feature", + "properties": { + "id": "8", + "place_name": "Child Health Clinic", + "category": "1", + "date_time": "April 12, 2016, 2:17 p.m.", + "type": "Repeat assesment", + "perpetrator": "", + "victim": "", + "killed": 11, + "injured": 10, + "detained": 5, + "source": """", + "notes": """", + "reported_by": "Mark Herringer", + "incident_icon": "/media/static/event_mapper/css/images/leaflet/marker-icon.png", + "advisory_icon": "/media/static/event_mapper/css/images/leaflet/marker-icon.png", + "overal_assessment": 2, + "healthsite_type": "First Aid Post", + }, + "geometry": { + "type": "Point", + "coordinates": [34.94885, 31.50353] + } + }, + { + "type": "Feature", + "properties": { + "id": "9", + "place_name": "Battir Health Center", + "category": "1", + "date_time": "April 12, 2016, 2:17 p.m.", + "type": "Repeat assesment", + "perpetrator": "", + "victim": "", + "killed": 11, + "injured": 10, + "detained": 5, + "source": """", + "notes": """", + "reported_by": "Mark Herringer", + "incident_icon": "/media/static/event_mapper/css/images/leaflet/marker-icon.png", + "advisory_icon": "/media/static/event_mapper/css/images/leaflet/marker-icon.png", + "overal_assessment": 3, + "healthsite_type": "Dispensary", + }, + "geometry": { + "type": "Point", + "coordinates": [35.13948, 31.72819] + } + }, + { + "type": "Feature", + "properties": { + "id": "10", + "place_name": "Military Hospital", + "category": "1", + "date_time": "April 12, 2016, 2:17 p.m.", + "type": "Repeat assesment", + "perpetrator": "", + "victim": "", + "killed": 11, + "injured": 10, + "detained": 5, + "source": """", + "notes": """", + "reported_by": "Mark Herringer", + "incident_icon": "/media/static/event_mapper/css/images/leaflet/marker-icon.png", + "advisory_icon": "/media/static/event_mapper/css/images/leaflet/marker-icon.png", + "overal_assessment": 4, + "healthsite_type": "Clinic", + }, + "geometry": { + "type": "Point", + "coordinates": [35.21162, 31.66244] + } + }, + { + "type": "Feature", + "properties": { + "id": "11", + "place_name": "Jabel Clinic", + "category": "1", + "date_time": "April 12, 2016, 2:17 p.m.", + "type": "Repeat assesment", + "perpetrator": "", + "victim": "", + "killed": 11, + "injured": 10, + "detained": 5, + "source": """", + "notes": """", + "reported_by": "Irwan Fathurrahman", + "incident_icon": "/media/static/event_mapper/css/images/leaflet/marker-icon.png", + "advisory_icon": "/media/static/event_mapper/css/images/leaflet/marker-icon.png", + "overal_assessment": 3, + "healthsite_type": "Health Center", + }, + "geometry": { + "type": "Point", + "coordinates": [35.28348, 31.75814] + } + }, + { + "type": "Feature", + "properties": { + "id": "12", + "place_name": "מגן דוד אדום", + "category": "1", + "date_time": "April 12, 2016, 2:17 p.m.", + "type": "Repeat assesment", + "perpetrator": "", + "victim": "", + "killed": 11, + "injured": 10, + "detained": 5, + "source": """", + "notes": """", + "reported_by": "Irwan Fathurrahman", + "incident_icon": "/media/static/event_mapper/css/images/leaflet/marker-icon.png", + "advisory_icon": "/media/static/event_mapper/css/images/leaflet/marker-icon.png", + "overal_assessment": 3, + "healthsite_type": "Orthopedic Center", + }, + "geometry": { + "type": "Point", + "coordinates": [34.99078, 31.74914] + } + }, + ] + } +} diff --git a/django_project/event_mapper/views/event.py b/django_project/event_mapper/views/event.py index 5713f6a..79d45e5 100644 --- a/django_project/event_mapper/views/event.py +++ b/django_project/event_mapper/views/event.py @@ -7,7 +7,6 @@ __copyright__ = 'imajimatika@gmail.com' __doc__ = '' - import json from django.contrib.auth.decorators import login_required from django.contrib import messages @@ -23,6 +22,9 @@ from event_mapper.models.event import Event from event_mapper.forms.event import EventCreationForm +from healthsites.models.healthsite import Healthsite + +from dummy import dummy_data @login_required @@ -54,6 +56,7 @@ def event_dashboard(request): if request.method == 'GET': return render_to_response( 'event_mapper/event/event_dashboard_page.html', + {"healthsites_num": Healthsite.objects.count()}, context_instance=RequestContext(request) ) elif request.method == 'POST': @@ -115,5 +118,6 @@ def get_events(request): context_instance=RequestContext(request, context)) # events_json = json.dumps(events_json) + events_json = json.dumps(dummy_data) return HttpResponse(events_json, content_type='application/json')