Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Added help button that pulls in markdown documentation

  • Loading branch information...
commit 59afd48d5ac93a58d5530d9d8405993df585c52d 1 parent b072536
@mikeymckay authored
View
7 _attachments/app/app.coffee
@@ -30,6 +30,7 @@ class Router extends Backbone.Router
"users": "users"
"messaging": "messaging"
"help": "help"
+ "help/:helpDocument": "help"
"clean": "clean"
# "clean/:applyTarget": "clean"
"clean/:startDate/:endDate": "clean"
@@ -100,10 +101,14 @@ class Router extends Backbone.Router
Coconut.cleanView.render()
- help: ->
+ help: (helpDocument) ->
@userLoggedIn
success: ->
Coconut.helpView ?= new HelpView()
+ if helpDocument?
+ Coconut.helpView.helpDocument = helpDocument
+ else
+ Coconut.helpView.helpDocument = null
Coconut.helpView.render()
users: ->
View
8 _attachments/app/app.js
@@ -42,6 +42,7 @@ Router = (function(_super) {
"users": "users",
"messaging": "messaging",
"help": "help",
+ "help/:helpDocument": "help",
"clean": "clean",
"clean/:startDate/:endDate": "clean",
"csv/:question/startDate/:startDate/endDate/:endDate": "csv",
@@ -140,7 +141,7 @@ Router = (function(_super) {
});
};
- Router.prototype.help = function() {
+ Router.prototype.help = function(helpDocument) {
return this.userLoggedIn({
success: function() {
var _ref1;
@@ -148,6 +149,11 @@ Router = (function(_super) {
if ((_ref1 = Coconut.helpView) == null) {
Coconut.helpView = new HelpView();
}
+ if (helpDocument != null) {
+ Coconut.helpView.helpDocument = helpDocument;
+ } else {
+ Coconut.helpView.helpDocument = null;
+ }
return Coconut.helpView.render();
}
});
View
13 _attachments/app/models/Case.coffee
@@ -81,6 +81,10 @@ class Case
MalariaCaseID: ->
@caseID
+ facility: ->
+ console.log @["USSD Notification"]
+ @["USSD Notification"]?.hf
+
shehia: ->
@.Household?.Shehia || @.Facility?.Shehia || @["USSD Notification"]?.shehia
@@ -90,10 +94,11 @@ class Case
# Don't use facility to identify district because they may be traveling
district: ->
district = WardHierarchy.district(@shehia()) if @shehia()?
- user = @user()
- if user? and not district?
- district = Users.district(user)
- district
+# Below is invalid, because it could use a facility's district, which would be wrong, so commenting out
+ #user = @user()
+ #if user? and not district?
+ # district = Users.district(user)
+ #district
possibleQuestions: ->
["Case Notification", "Facility","Household","Household Members"]
View
16 _attachments/app/models/Case.js
@@ -135,6 +135,13 @@ Case = (function() {
return this.caseID;
};
+ Case.prototype.facility = function() {
+ var _ref;
+
+ console.log(this["USSD Notification"]);
+ return (_ref = this["USSD Notification"]) != null ? _ref.hf : void 0;
+ };
+
Case.prototype.shehia = function() {
var _ref, _ref1, _ref2;
@@ -148,16 +155,11 @@ Case = (function() {
};
Case.prototype.district = function() {
- var district, user;
+ var district;
if (this.shehia() != null) {
- district = WardHierarchy.district(this.shehia());
- }
- user = this.user();
- if ((user != null) && (district == null)) {
- district = Users.district(user);
+ return district = WardHierarchy.district(this.shehia());
}
- return district;
};
Case.prototype.possibleQuestions = function() {
View
48 _attachments/app/models/Reports.coffee
@@ -200,3 +200,51 @@ class Reports
data.travelByDistrict["ALL"].travelReported.push positiveCase
options.finished(data)
+
+
+
+
+ @systemErrors: (options) ->
+
+ $.couch.db(Coconut.config.database_name()).view "#{Coconut.config.design_doc_name()}/errorsByDate",
+ # Note that these seem reversed due to descending order
+ startkey: options?.endDate || moment().format("YYYY-MM-DD")
+ endkey: options?.startDate || moment().subtract('days',1).format("YYYY-MM-DD")
+ descending: true
+ include_docs: true
+ success: (result) ->
+ errorsByType = {}
+ _.chain(result.rows)
+ .pluck("doc")
+ .each (error) ->
+ if errorsByType[error.message]?
+ errorsByType[error.message].count++
+ else
+ errorsByType[error.message]= {}
+ errorsByType[error.message].count = 0
+ errorsByType[error.message]["Most Recent"] = error.datetime
+ errorsByType[error.message]["Source"] = error.source
+
+ errorsByType[error.message]["Most Recent"] = error.datetime if errorsByType[error.message]["Most Recent"] < error.datetime
+ options.success(errorsByType)
+
+ @notFollowedUp: (options) ->
+ reports = new Reports()
+ # TODO casesAggregatedForAnalysis should be static
+ reports.casesAggregatedForAnalysis
+ startDate: options?.startDate || moment().subtract('days',9).format("YYYY-MM-DD")
+ endDate: options?.endDate || moment().subtract('days',2).format("YYYY-MM-DD")
+ mostSpecificLocation: options.mostSpecificLocation
+ success: (cases) ->
+ console.log cases
+ options.success(cases.followupsByDistrict["ALL"]?.casesNotFollowedUp)
+
+ @unknownDistricts: (options) ->
+ reports = new Reports()
+ # TODO casesAggregatedForAnalysis should be static
+ reports.casesAggregatedForAnalysis
+ startDate: options?.startDate || moment().subtract('days',14).format("YYYY-MM-DD")
+ endDate: options?.endDate || moment().subtract('days',7).format("YYYY-MM-DD")
+ mostSpecificLocation: options.mostSpecificLocation
+ success: (cases) ->
+ options.success(cases.followupsByDistrict["UNKNOWN"]?.casesNotFollowedUp)
View
61 _attachments/app/models/Reports.js
@@ -256,6 +256,67 @@ Reports = (function() {
}));
};
+ Reports.systemErrors = function(options) {
+ return $.couch.db(Coconut.config.database_name()).view("" + (Coconut.config.design_doc_name()) + "/errorsByDate", {
+ startkey: (options != null ? options.endDate : void 0) || moment().format("YYYY-MM-DD"),
+ endkey: (options != null ? options.startDate : void 0) || moment().subtract('days', 1).format("YYYY-MM-DD"),
+ descending: true,
+ include_docs: true,
+ success: function(result) {
+ var errorsByType;
+
+ errorsByType = {};
+ _.chain(result.rows).pluck("doc").each(function(error) {
+ if (errorsByType[error.message] != null) {
+ errorsByType[error.message].count++;
+ } else {
+ errorsByType[error.message] = {};
+ errorsByType[error.message].count = 0;
+ errorsByType[error.message]["Most Recent"] = error.datetime;
+ errorsByType[error.message]["Source"] = error.source;
+ }
+ if (errorsByType[error.message]["Most Recent"] < error.datetime) {
+ return errorsByType[error.message]["Most Recent"] = error.datetime;
+ }
+ });
+ return options.success(errorsByType);
+ }
+ });
+ };
+
+ Reports.notFollowedUp = function(options) {
+ var reports;
+
+ reports = new Reports();
+ return reports.casesAggregatedForAnalysis({
+ startDate: (options != null ? options.startDate : void 0) || moment().subtract('days', 9).format("YYYY-MM-DD"),
+ endDate: (options != null ? options.endDate : void 0) || moment().subtract('days', 2).format("YYYY-MM-DD"),
+ mostSpecificLocation: options.mostSpecificLocation,
+ success: function(cases) {
+ var _ref;
+
+ console.log(cases);
+ return options.success((_ref = cases.followupsByDistrict["ALL"]) != null ? _ref.casesNotFollowedUp : void 0);
+ }
+ });
+ };
+
+ Reports.unknownDistricts = function(options) {
+ var reports;
+
+ reports = new Reports();
+ return reports.casesAggregatedForAnalysis({
+ startDate: (options != null ? options.startDate : void 0) || moment().subtract('days', 14).format("YYYY-MM-DD"),
+ endDate: (options != null ? options.endDate : void 0) || moment().subtract('days', 7).format("YYYY-MM-DD"),
+ mostSpecificLocation: options.mostSpecificLocation,
+ success: function(cases) {
+ var _ref;
+
+ return options.success((_ref = cases.followupsByDistrict["UNKNOWN"]) != null ? _ref.casesNotFollowedUp : void 0);
+ }
+ });
+ };
+
return Reports;
})();
View
16 _attachments/app/views/HelpView.coffee
@@ -5,9 +5,21 @@ class HelpView extends Backbone.View
events:
"click input[value=Send]": "send"
- render: ->
+ render: =>
+
+ if @helpDocument?
+ $.ajax
+ url: "documentation/#{@helpDocument}.markdown"
+ success: (result) =>
+ @$el.html markdown.toHTML(result)
+ @appendHelpForm()
+ else
+ @$el.html ""
+ @appendHelpForm()
- @$el.html "
+ appendHelpForm: ->
+ @$el.append "
+ <hr/>
<label style='display:block' for='message'>If you are having trouble please contact your supervisor as soon as possible. You can also describe the problem in the box below and it will send a message to our support team. We'll get back to you as soon as possible.</label>
<textarea style='width:100%' id='message' name='message'></textarea>
<div id='messageBox'></div>
View
22 _attachments/app/views/HelpView.js
@@ -1,5 +1,6 @@
// Generated by CoffeeScript 1.6.2
var HelpView, _ref,
+ __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
@@ -7,7 +8,7 @@ HelpView = (function(_super) {
__extends(HelpView, _super);
function HelpView() {
- _ref = HelpView.__super__.constructor.apply(this, arguments);
+ this.render = __bind(this.render, this); _ref = HelpView.__super__.constructor.apply(this, arguments);
return _ref;
}
@@ -18,7 +19,24 @@ HelpView = (function(_super) {
};
HelpView.prototype.render = function() {
- return this.$el.html(" <label style='display:block' for='message'>If you are having trouble please contact your supervisor as soon as possible. You can also describe the problem in the box below and it will send a message to our support team. We'll get back to you as soon as possible.</label> <textarea style='width:100%' id='message' name='message'></textarea> <div id='messageBox'></div> </div> <input type='submit' value='Send'></input> ");
+ var _this = this;
+
+ if (this.helpDocument != null) {
+ return $.ajax({
+ url: "documentation/" + this.helpDocument + ".markdown",
+ success: function(result) {
+ _this.$el.html(markdown.toHTML(result));
+ return _this.appendHelpForm();
+ }
+ });
+ } else {
+ this.$el.html("");
+ return this.appendHelpForm();
+ }
+ };
+
+ HelpView.prototype.appendHelpForm = function() {
+ return this.$el.append(" <hr/> <label style='display:block' for='message'>If you are having trouble please contact your supervisor as soon as possible. You can also describe the problem in the box below and it will send a message to our support team. We'll get back to you as soon as possible.</label> <textarea style='width:100%' id='message' name='message'></textarea> <div id='messageBox'></div> </div> <input type='submit' value='Send'></input> ");
};
HelpView.prototype.send = function() {
View
4 _attachments/app/views/QuestionView.coffee
@@ -94,6 +94,10 @@ class QuestionView extends Backbone.View
</style>
+ <div style='position:fixed; right:5px; color:white; padding:20px; z-index:5' id='messageText'>
+ <a href='#help/#{@model.id}'>Help</a>
+ </div>
+
<div style='position:fixed; right:5px; color:white; background-color: #333; padding:20px; display:none; z-index:10' id='messageText'>
Saving...
</div>
View
2  _attachments/app/views/QuestionView.js
@@ -76,7 +76,7 @@ QuestionView = (function(_super) {
var autocompleteElements, skipperList,
_this = this;
- this.$el.html(" <style> .message { color: grey; font-weight: bold; padding: 10px; border: 1px yellow dotted; background: yellow; display: none; } label.radio { border-radius:20px; display:block; padding:4px 11px; border: 1px solid black; cursor: pointer; text-decoration: none; } input[type='radio']:checked + label { background-color:#ddd; background: #5393c5; background-image: -webkit-gradient(linear,left top,left bottom,from(#5393c5),to(#6facd5)); background-image: -webkit-linear-gradient(#5393c5,#6facd5); background-image: -moz-linear-gradient(#5393c5,#6facd5); background-image: -ms-linear-gradient(#5393c5,#6facd5); background-image: -o-linear-gradient(#5393c5,#6facd5); background-image: linear-gradient(#5393c5,#6facd5); } input[type='radio']{ height: 0px; } div.question.radio{ padding-top: 8px; padding-bottom: 8px; } .tt-hint{ display:none } .tt-dropdown-menu{ width: 100%; background-color: lightgray; } .tt-suggestion{ background-color: white; border-radius:20px; display:block; padding:4px 11px; border: 1px solid black; cursor: pointer; text-decoration: none; } .tt-suggestion .{ } </style> <div style='position:fixed; right:5px; color:white; background-color: #333; padding:20px; display:none; z-index:10' id='messageText'> Saving... </div> <h1>" + this.model.id + "</h1> <div id='question-view'> <form> " + (this.toHTMLForm(this.model)) + " </form> </div> ");
+ this.$el.html(" <style> .message { color: grey; font-weight: bold; padding: 10px; border: 1px yellow dotted; background: yellow; display: none; } label.radio { border-radius:20px; display:block; padding:4px 11px; border: 1px solid black; cursor: pointer; text-decoration: none; } input[type='radio']:checked + label { background-color:#ddd; background: #5393c5; background-image: -webkit-gradient(linear,left top,left bottom,from(#5393c5),to(#6facd5)); background-image: -webkit-linear-gradient(#5393c5,#6facd5); background-image: -moz-linear-gradient(#5393c5,#6facd5); background-image: -ms-linear-gradient(#5393c5,#6facd5); background-image: -o-linear-gradient(#5393c5,#6facd5); background-image: linear-gradient(#5393c5,#6facd5); } input[type='radio']{ height: 0px; } div.question.radio{ padding-top: 8px; padding-bottom: 8px; } .tt-hint{ display:none } .tt-dropdown-menu{ width: 100%; background-color: lightgray; } .tt-suggestion{ background-color: white; border-radius:20px; display:block; padding:4px 11px; border: 1px solid black; cursor: pointer; text-decoration: none; } .tt-suggestion .{ } </style> <div style='position:fixed; right:5px; color:white; padding:20px; z-index:5' id='messageText'> <a href='#help/" + this.model.id + "'>Help</a> </div> <div style='position:fixed; right:5px; color:white; background-color: #333; padding:20px; display:none; z-index:10' id='messageText'> Saving... </div> <h1>" + this.model.id + "</h1> <div id='question-view'> <form> " + (this.toHTMLForm(this.model)) + " </form> </div> ");
js2form($('form').get(0), this.result.toJSON());
this.updateCache();
this.updateSkipLogic();
View
161 _attachments/app/views/ReportView.coffee
@@ -15,22 +15,38 @@ USSD}
"change #reportOptions": "update"
"change #summaryField1": "summarySelectorChanged"
"change #summaryField2": "summarySelector2Changed"
- "change #cluster": "update"
+ "change #cluster": "updateCluster"
"click .toggleDisaggregation": "toggleDisaggregation"
"click .same-cell-disaggregatable": "toggleDisaggregationSameCell"
"click .toggle-trend-data": "toggleTrendData"
"click #downloadMap": "downloadMap"
+ "click #downloadLargePembaMap": "downloadLargePembaMap"
+ "click #downloadLargeUngujaMap": "downloadLargeUngujaMap"
"click button:contains(Pemba)": "zoomPemba"
"click button:contains(Unguja)": "zoomUnguja"
+ updateCluster: ->
+ @updateUrl("cluster",$("#cluster").val())
+ Coconut.router.navigate(url,true)
+
zoomPemba: ->
@map.fitBounds @bounds["Pemba"]
- @updateUrlShowPlace("Pemba")
-
+ @updateUrl("showIsland","Pemba")
+ Coconut.router.navigate(url,false)
zoomUnguja: ->
@map.fitBounds @bounds["Unguja"]
- @updateUrlShowPlace("Unguja")
+ @updateUrl("showIsland","Unguja")
+ Coconut.router.navigate(url,false)
+
+ updateUrl: (property,value) ->
+ urlHash = document.location.hash
+ url = if urlHash.match(property)
+ regExp = new RegExp("#{property}\\/.*?\\/")
+ urlHash.replace(regExp,"#{property}/#{value}/")
+ else
+ urlHash + "/#{property}/#{value}/"
+ document.location.hash = url
updateUrlShowPlace: (place) ->
urlHash = document.location.hash
@@ -41,6 +57,16 @@ USSD}
document.location.hash = url
Coconut.router.navigate(url,false)
+ downloadLargePembaMap: ->
+ @updateUrl("showIsland","Pemba")
+ @updateUrl("mapWidth","2000px")
+ @updateUrl("mapHeight","4000px")
+
+ downloadLargeUngujaMap: ->
+ @updateUrl("showIsland","Unguja")
+ @updateUrl("mapWidth","2000px")
+ @updateUrl("mapHeight","4000px")
+
downloadMap: ->
$("#downloadMap").html "Generating downloadable map..."
html2canvas $('#map'),
@@ -229,8 +255,7 @@ USSD}
mostSpecificLocation: @mostSpecificLocationSelected()
- alerts: ->
-
+ alerts: =>
alerts_to_check = "system_errors, not_followed_up, unknown_districts".split(/, */)
$("#reportContents").html "
<h2>Alerts</h2>
@@ -246,7 +271,6 @@ USSD}
alerts = false
- console.log alerts_to_check.length
# Don't call this until all alert checks are complete
afterFinished = _.after(alerts_to_check.length, ->
if alerts
@@ -255,30 +279,10 @@ USSD}
$("#alerts_status").html("<div id='hasAlerts'>Report finished, no alerts found.</div>")
)
-
- $.couch.db(Coconut.config.database_name()).view "#{Coconut.config.design_doc_name()}/errorsByDate",
- # Note that these seem reversed due to descending order
- startkey: moment().format("YYYY-MM-DD")
- endkey: moment().subtract('days',1).format("YYYY-MM-DD")
- descending: true
- include_docs: true
- success: (result) ->
- errorsByType = {}
- _.chain(result.rows)
- .pluck("doc")
- .each (error) ->
- if errorsByType[error.message]?
- errorsByType[error.message].count++
- else
- errorsByType[error.message]= {}
- errorsByType[error.message].count = 0
- errorsByType[error.message]["Most Recent"] = error.datetime
- errorsByType[error.message]["Source"] = error.source
-
- errorsByType[error.message]["Most Recent"] = error.datetime if errorsByType[error.message]["Most Recent"] < error.datetime
-
+ Reports.systemErrors
+ success: (errorsByType) ->
if _(errorsByType).isEmpty()
- $("#system_errors").append "No system errors"
+ $("#system_errors").append "No system errors."
else
alerts = true
@@ -310,26 +314,25 @@ USSD}
</table>
"
afterFinished()
- console.log "ASDAS"
-
- reports = new Reports()
- reports.casesAggregatedForAnalysis
+
+ console.log @mostSpecificLocationSelected()
+ Reports.notFollowedUp
startDate: @startDate
endDate: @endDate
mostSpecificLocation: @mostSpecificLocationSelected()
- success: (cases) ->
+ success: (casesNotFollowedUp) =>
- if cases.followupsByDistrict["ALL"].length is 0
- $("#not_followed_up").append "All cases between #{@startDate()} and #{@endDate()} have been followed up within two days."
+ if casesNotFollowedUp.length is 0
+ $("#not_followed_up").append "All cases between #{@startDate} and #{@endDate} have been followed up within two days."
else
alerts = true
$("#not_followed_up").append "
- The following districts have USSD Notifications that have not been followed up after two days. Recommendation call the DMSO:
+ The following districts have USSD Notifications that occurred between #{@startDate} and #{@endDate} that have not been followed up after two days. Recommendation call the DMSO:
<table style='border:1px solid black' class='alerts'>
<thead>
<tr>
- <th>Number of cases</th>
+ <th>Facility</th>
<th>District</th>
<th>Officer</th>
<th>Phone number</th>
@@ -337,12 +340,10 @@ USSD}
</thead>
<tbody>
#{
- _.map(cases.followupsByDistrict, (result,district) ->
+ _.map(casesNotFollowedUp, (malariaCase) ->
+ district = malariaCase.district() || "UNKNOWN"
return "" if district is "ALL" or district is "UNKNOWN"
- casesNotFollowedUp = result.casesNotFollowedUp.length
- return if casesNotFollowedUp is 0
-
user = Users.where(
district: district
)
@@ -350,7 +351,7 @@ USSD}
"
<tr>
- <td>#{casesNotFollowedUp}</td>
+ <td>#{malariaCase.facility()}</td>
<td>#{district.titleize()}</td>
<td>#{user.get? "name"}</td>
<td>#{user.username?()}</td>
@@ -362,40 +363,46 @@ USSD}
</table>
"
afterFinished()
+
+ console.log @mostSpecificLocationSelected()
- if cases.followupsByDistrict["UNKNOWN"].length is 0
- $("#unknown_districts").append "No unknown districts reported"
- else
- alerts = true
+ Reports.unknownDistricts
+ startDate: @startDate
+ endDate: @endDate
+ mostSpecificLocation: @mostSpecificLocationSelected()
+ success: (casesNotFollowedupWithUnknownDistrict) ->
- $("#unknown_districts").append "
- The following USSD notifications have shehias with unknown districts. These may be traveling patients or incorrectly spelled shehias. Please contact an administrator if the problem can be resolved by fixing the spelling.
- <table style='border:1px solid black' class='unknown-districts'>
- <thead>
- <tr>
- <th>Health facility</th>
- <th>Shehia</th>
- <th>Case ID</th>
- </tr>
- </thead>
- <tbody>
- #{
- _.map(cases.followupsByDistrict["UNKNOWN"].casesNotFollowedUp, (caseNotFollowedUp) ->
- return unless caseNotFollowedUp["USSD Notification"]
- console.log caseNotFollowedUp
- "
- <tr>
- <td>#{caseNotFollowedUp["USSD Notification"].hf.titleize()}</td>
- <td>#{caseNotFollowedUp["USSD Notification"].shehia.titleize()}</td>
- <td><a href='#show/case/#{caseNotFollowedUp["USSD Notification"].caseid}'>#{caseNotFollowedUp["USSD Notification"].caseid}</a></td>
- </tr>
- "
- ).join("")
- }
- </tbody>
- </table>
- "
- afterFinished()
+ if casesNotFollowedupWithUnknownDistrict.length is 0
+ $("#unknown_districts").append "All cases between #{@startDate} and #{@endDate} that have not been followed up have shehias with known districts"
+ else
+ alerts = true
+
+ $("#unknown_districts").append "
+ The following cases have not been followed up and have shehias with unknown districts (for period #{@startDate} to #{@endDate}. These may be traveling patients or incorrectly spelled shehias. Please contact an administrator if the problem can be resolved by fixing the spelling.
+ <table style='border:1px solid black' class='unknown-districts'>
+ <thead>
+ <tr>
+ <th>Health facility</th>
+ <th>Shehia</th>
+ <th>Case ID</th>
+ </tr>
+ </thead>
+ <tbody>
+ #{
+ _.map(casesNotFollowedupWithUnknownDistrict, (caseNotFollowedUpWithUnknownDistrict) ->
+ "
+ <tr>
+ <td>#{caseNotFollowedUpWithUnknownDistrict["USSD Notification"].hf.titleize()}</td>
+ <td>#{caseNotFollowedUpWithUnknownDistrict.shehia().titleize()}</td>
+ <td><a href='#show/case/#{caseNotFollowedUpWithUnknownDistrict.caseID}'>#{caseNotFollowedUpWithUnknownDistrict.caseID}</a></td>
+ </tr>
+ "
+ ).join("")
+ }
+ </tbody>
+ </table>
+ "
+ afterFinished()
locations: ->
@@ -421,6 +428,8 @@ USSD}
Use + - buttons to zoom map. Click and drag to reposition the map. Circles with a darker have multiple cases. Red cases show households with additional positive malaria cases.<br/>
<div id='map' style='width:#{@mapWidth}; height:#{@mapHeight};'></div>
<button id='downloadMap' type='button'>Download Map</button>
+ <button id='downloadLargeUngujaMap' type='button'>Download Large Pemba Map</button>
+ <button id='downloadLargePembaMap' type='button'>Download Large Unguja Map</button>
<a id='mapData' download='map.png' style='display:none'>Map</map>
"
View
120 _attachments/app/views/ReportView.js
@@ -8,6 +8,7 @@ ReportView = (function(_super) {
__extends(ReportView, _super);
function ReportView() {
+ this.alerts = __bind(this.alerts, this);
this.getCases = __bind(this.getCases, this);
this.render = __bind(this.render, this);
this.update = __bind(this.update, this); _ref = ReportView.__super__.constructor.apply(this, arguments);
@@ -24,23 +25,40 @@ ReportView = (function(_super) {
"change #reportOptions": "update",
"change #summaryField1": "summarySelectorChanged",
"change #summaryField2": "summarySelector2Changed",
- "change #cluster": "update",
+ "change #cluster": "updateCluster",
"click .toggleDisaggregation": "toggleDisaggregation",
"click .same-cell-disaggregatable": "toggleDisaggregationSameCell",
"click .toggle-trend-data": "toggleTrendData",
"click #downloadMap": "downloadMap",
+ "click #downloadLargePembaMap": "downloadLargePembaMap",
+ "click #downloadLargeUngujaMap": "downloadLargeUngujaMap",
"click button:contains(Pemba)": "zoomPemba",
"click button:contains(Unguja)": "zoomUnguja"
};
+ ReportView.prototype.updateCluster = function() {
+ this.updateUrl("cluster", $("#cluster").val());
+ return Coconut.router.navigate(url, true);
+ };
+
ReportView.prototype.zoomPemba = function() {
this.map.fitBounds(this.bounds["Pemba"]);
- return this.updateUrlShowPlace("Pemba");
+ this.updateUrl("showIsland", "Pemba");
+ return Coconut.router.navigate(url, false);
};
ReportView.prototype.zoomUnguja = function() {
this.map.fitBounds(this.bounds["Unguja"]);
- return this.updateUrlShowPlace("Unguja");
+ this.updateUrl("showIsland", "Unguja");
+ return Coconut.router.navigate(url, false);
+ };
+
+ ReportView.prototype.updateUrl = function(property, value) {
+ var regExp, url, urlHash;
+
+ urlHash = document.location.hash;
+ url = urlHash.match(property) ? (regExp = new RegExp("" + property + "\\/.*?\\/"), urlHash.replace(regExp, "" + property + "/" + value + "/")) : urlHash + ("/" + property + "/" + value + "/");
+ return document.location.hash = url;
};
ReportView.prototype.updateUrlShowPlace = function(place) {
@@ -52,6 +70,18 @@ ReportView = (function(_super) {
return Coconut.router.navigate(url, false);
};
+ ReportView.prototype.downloadLargePembaMap = function() {
+ this.updateUrl("showIsland", "Pemba");
+ this.updateUrl("mapWidth", "2000px");
+ return this.updateUrl("mapHeight", "4000px");
+ };
+
+ ReportView.prototype.downloadLargeUngujaMap = function() {
+ this.updateUrl("showIsland", "Unguja");
+ this.updateUrl("mapWidth", "2000px");
+ return this.updateUrl("mapHeight", "4000px");
+ };
+
ReportView.prototype.downloadMap = function() {
$("#downloadMap").html("Generating downloadable map...");
return html2canvas($('#map'), {
@@ -228,14 +258,14 @@ ReportView = (function(_super) {
};
ReportView.prototype.alerts = function() {
- var afterFinished, alerts, alerts_to_check, reports;
+ var afterFinished, alerts, alerts_to_check,
+ _this = this;
alerts_to_check = "system_errors, not_followed_up, unknown_districts".split(/, */);
$("#reportContents").html(" <h2>Alerts</h2> <div id='alerts_status' style='padding-bottom:20px;font-size:150%'> <h2>Checking for system alerts:" + (alerts_to_check.join(", ")) + "</h2> </div> <div id='alerts'> " + (_.map(alerts_to_check, function(alert) {
return "<div id='" + alert + "'><br/></div>";
}).join("")) + " </div> ");
alerts = false;
- console.log(alerts_to_check.length);
afterFinished = _.after(alerts_to_check.length, function() {
if (alerts) {
return $("#alerts_status").html("<div id='hasAlerts'>Report finished, alerts found.</div>");
@@ -243,83 +273,63 @@ ReportView = (function(_super) {
return $("#alerts_status").html("<div id='hasAlerts'>Report finished, no alerts found.</div>");
}
});
- $.couch.db(Coconut.config.database_name()).view("" + (Coconut.config.design_doc_name()) + "/errorsByDate", {
- startkey: moment().format("YYYY-MM-DD"),
- endkey: moment().subtract('days', 1).format("YYYY-MM-DD"),
- descending: true,
- include_docs: true,
- success: function(result) {
- var errorsByType;
-
- errorsByType = {};
- _.chain(result.rows).pluck("doc").each(function(error) {
- if (errorsByType[error.message] != null) {
- errorsByType[error.message].count++;
- } else {
- errorsByType[error.message] = {};
- errorsByType[error.message].count = 0;
- errorsByType[error.message]["Most Recent"] = error.datetime;
- errorsByType[error.message]["Source"] = error.source;
- }
- if (errorsByType[error.message]["Most Recent"] < error.datetime) {
- return errorsByType[error.message]["Most Recent"] = error.datetime;
- }
- });
+ Reports.systemErrors({
+ success: function(errorsByType) {
if (_(errorsByType).isEmpty()) {
- $("#system_errors").append("No system errors");
+ $("#system_errors").append("No system errors.");
} else {
alerts = true;
$("#system_errors").append(" The following system errors have occurred in the last 2 days: <table style='border:1px solid black' class='system-errors'> <thead> <tr> <th>Time of most recent error</th> <th>Message</th> <th>Number of errors of this type in last 24 hours</th> <th>Source</th> </tr> </thead> <tbody> " + (_.map(errorsByType, function(errorData, errorMessage) {
return " <tr> <td>" + errorData["Most Recent"] + "</td> <td>" + errorMessage + "</td> <td>" + errorData.count + "</td> <td>" + errorData["Source"] + "</td> </tr> ";
}).join("")) + " </tbody> </table> ");
}
- afterFinished();
- return console.log("ASDAS");
+ return afterFinished();
}
});
- reports = new Reports();
- return reports.casesAggregatedForAnalysis({
+ console.log(this.mostSpecificLocationSelected());
+ return Reports.notFollowedUp({
startDate: this.startDate,
endDate: this.endDate,
mostSpecificLocation: this.mostSpecificLocationSelected(),
- success: function(cases) {
- if (cases.followupsByDistrict["ALL"].length === 0) {
- $("#not_followed_up").append("All cases between " + (this.startDate()) + " and " + (this.endDate()) + " have been followed up within two days.");
+ success: function(casesNotFollowedUp) {
+ if (casesNotFollowedUp.length === 0) {
+ $("#not_followed_up").append("All cases between " + _this.startDate + " and " + _this.endDate + " have been followed up within two days.");
} else {
alerts = true;
- $("#not_followed_up").append(" The following districts have USSD Notifications that have not been followed up after two days. Recommendation call the DMSO: <table style='border:1px solid black' class='alerts'> <thead> <tr> <th>Number of cases</th> <th>District</th> <th>Officer</th> <th>Phone number</th> </tr> </thead> <tbody> " + (_.map(cases.followupsByDistrict, function(result, district) {
- var casesNotFollowedUp, user;
+ $("#not_followed_up").append(" The following districts have USSD Notifications that occurred between " + _this.startDate + " and " + _this.endDate + " that have not been followed up after two days. Recommendation call the DMSO: <table style='border:1px solid black' class='alerts'> <thead> <tr> <th>Facility</th> <th>District</th> <th>Officer</th> <th>Phone number</th> </tr> </thead> <tbody> " + (_.map(casesNotFollowedUp, function(malariaCase) {
+ var district, user;
+ district = malariaCase.district() || "UNKNOWN";
if (district === "ALL" || district === "UNKNOWN") {
return "";
}
- casesNotFollowedUp = result.casesNotFollowedUp.length;
- if (casesNotFollowedUp === 0) {
- return;
- }
user = Users.where({
district: district
});
if (user.length) {
user = user[0];
}
- return " <tr> <td>" + casesNotFollowedUp + "</td> <td>" + (district.titleize()) + "</td> <td>" + (typeof user.get === "function" ? user.get("name") : void 0) + "</td> <td>" + (typeof user.username === "function" ? user.username() : void 0) + "</td> </tr> ";
+ return " <tr> <td>" + (malariaCase.facility()) + "</td> <td>" + (district.titleize()) + "</td> <td>" + (typeof user.get === "function" ? user.get("name") : void 0) + "</td> <td>" + (typeof user.username === "function" ? user.username() : void 0) + "</td> </tr> ";
}).join("")) + " </tbody> </table> ");
}
afterFinished();
- if (cases.followupsByDistrict["UNKNOWN"].length === 0) {
- $("#unknown_districts").append("No unknown districts reported");
- } else {
- alerts = true;
- $("#unknown_districts").append(" The following USSD notifications have shehias with unknown districts. These may be traveling patients or incorrectly spelled shehias. Please contact an administrator if the problem can be resolved by fixing the spelling. <table style='border:1px solid black' class='unknown-districts'> <thead> <tr> <th>Health facility</th> <th>Shehia</th> <th>Case ID</th> </tr> </thead> <tbody> " + (_.map(cases.followupsByDistrict["UNKNOWN"].casesNotFollowedUp, function(caseNotFollowedUp) {
- if (!caseNotFollowedUp["USSD Notification"]) {
- return;
+ console.log(_this.mostSpecificLocationSelected());
+ return Reports.unknownDistricts({
+ startDate: _this.startDate,
+ endDate: _this.endDate,
+ mostSpecificLocation: _this.mostSpecificLocationSelected(),
+ success: function(casesNotFollowedupWithUnknownDistrict) {
+ if (casesNotFollowedupWithUnknownDistrict.length === 0) {
+ $("#unknown_districts").append("All cases between " + this.startDate + " and " + this.endDate + " that have not been followed up have shehias with known districts");
+ } else {
+ alerts = true;
+ $("#unknown_districts").append(" The following cases have not been followed up and have shehias with unknown districts (for period " + this.startDate + " to " + this.endDate + ". These may be traveling patients or incorrectly spelled shehias. Please contact an administrator if the problem can be resolved by fixing the spelling. <table style='border:1px solid black' class='unknown-districts'> <thead> <tr> <th>Health facility</th> <th>Shehia</th> <th>Case ID</th> </tr> </thead> <tbody> " + (_.map(casesNotFollowedupWithUnknownDistrict, function(caseNotFollowedUpWithUnknownDistrict) {
+ return " <tr> <td>" + (caseNotFollowedUpWithUnknownDistrict["USSD Notification"].hf.titleize()) + "</td> <td>" + (caseNotFollowedUpWithUnknownDistrict.shehia().titleize()) + "</td> <td><a href='#show/case/" + caseNotFollowedUpWithUnknownDistrict.caseID + "'>" + caseNotFollowedUpWithUnknownDistrict.caseID + "</a></td> </tr> ";
+ }).join("")) + " </tbody> </table> ");
}
- console.log(caseNotFollowedUp);
- return " <tr> <td>" + (caseNotFollowedUp["USSD Notification"].hf.titleize()) + "</td> <td>" + (caseNotFollowedUp["USSD Notification"].shehia.titleize()) + "</td> <td><a href='#show/case/" + caseNotFollowedUp["USSD Notification"].caseid + "'>" + caseNotFollowedUp["USSD Notification"].caseid + "</a></td> </tr> ";
- }).join("")) + " </tbody> </table> ");
- }
- return afterFinished();
+ return afterFinished();
+ }
+ });
}
});
};
@@ -334,7 +344,7 @@ ReportView = (function(_super) {
}));
$("#reportOptions").append(" <button>Pemba</button> <button>Unguja</button> ");
$("#reportOptions button").button();
- $("#reportContents").html(" Use + - buttons to zoom map. Click and drag to reposition the map. Circles with a darker have multiple cases. Red cases show households with additional positive malaria cases.<br/> <div id='map' style='width:" + this.mapWidth + "; height:" + this.mapHeight + ";'></div> <button id='downloadMap' type='button'>Download Map</button> <a id='mapData' download='map.png' style='display:none'>Map</map> ");
+ $("#reportContents").html(" Use + - buttons to zoom map. Click and drag to reposition the map. Circles with a darker have multiple cases. Red cases show households with additional positive malaria cases.<br/> <div id='map' style='width:" + this.mapWidth + "; height:" + this.mapHeight + ";'></div> <button id='downloadMap' type='button'>Download Map</button> <button id='downloadLargeUngujaMap' type='button'>Download Large Pemba Map</button> <button id='downloadLargePembaMap' type='button'>Download Large Unguja Map</button> <a id='mapData' download='map.png' style='display:none'>Map</map> ");
$("#cluster").slider();
return this.getCases({
success: function(results) {
View
7 _attachments/app/views/ResultsView.coffee
@@ -14,6 +14,13 @@ class ResultsView extends Backbone.View
.dataTables_wrapper .dataTables_length{
display: none;
}
+
+ .dataTables_filter input{
+ display:inline;
+ width:300px;
+ }
+
+
a[role=button]{
background-color: white;
margin-right:5px;
View
2  _attachments/app/views/ResultsView.js
@@ -21,7 +21,7 @@ ResultsView = (function(_super) {
ResultsView.prototype.render = function() {
var _this = this;
- this.$el.html((" <style> table.results th.header, table.results td{ font-size:150%; } .dataTables_wrapper .dataTables_length{ display: none; } a[role=button]{ background-color: white; margin-right:5px; -moz-border-radius: 1em; -webkit-border-radius: 1em; border: solid gray 1px; font-family: Helvetica,Arial,sans-serif; font-weight: bold; color: #222; text-shadow: 0 1px 0 #fff; -webkit-background-clip: padding-box; -moz-background-clip: padding; background-clip: padding-box; padding: .6em 20px; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; position: relative; zoom: 1; } a[role=button].paginate_disabled_previous, a[role=button].paginate_disabled_next{ color:gray; } .dataTables_info{ float:right; } .dataTables_paginate{ margin-bottom:20px; } </style> <a href='#new/result/" + (escape(this.question.id)) + "'>Add new '" + this.question.id + "'</a> <div class='not-complete' data-collapsed='false' data-role='collapsible'> <h2>'" + this.question.id + "' Items Not Completed (<span class='count-complete-false'></span>)</h2> <table class='results complete-false tablesorter'> <thead><tr> ") + _.map(this.question.summaryFieldNames(), function(summaryField) {
+ this.$el.html((" <style> table.results th.header, table.results td{ font-size:150%; } .dataTables_wrapper .dataTables_length{ display: none; } .dataTables_filter input{ display:inline; width:300px; } a[role=button]{ background-color: white; margin-right:5px; -moz-border-radius: 1em; -webkit-border-radius: 1em; border: solid gray 1px; font-family: Helvetica,Arial,sans-serif; font-weight: bold; color: #222; text-shadow: 0 1px 0 #fff; -webkit-background-clip: padding-box; -moz-background-clip: padding; background-clip: padding-box; padding: .6em 20px; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; position: relative; zoom: 1; } a[role=button].paginate_disabled_previous, a[role=button].paginate_disabled_next{ color:gray; } .dataTables_info{ float:right; } .dataTables_paginate{ margin-bottom:20px; } </style> <a href='#new/result/" + (escape(this.question.id)) + "'>Add new '" + this.question.id + "'</a> <div class='not-complete' data-collapsed='false' data-role='collapsible'> <h2>'" + this.question.id + "' Items Not Completed (<span class='count-complete-false'></span>)</h2> <table class='results complete-false tablesorter'> <thead><tr> ") + _.map(this.question.summaryFieldNames(), function(summaryField) {
return "<th class='header'>" + summaryField + "</th>";
}).join("") + " <th></th> </tr></thead> <tbody> </tbody> <tfoot><tr> " + _.map(this.question.summaryFieldNames(), function(summaryField) {
return "<th class='header'>" + summaryField + "</th>";
View
2  _attachments/documentation/Intro.markdown
@@ -1,6 +1,6 @@
Coconut Surveillance is a system that combines phone based notifications from health facilities, a team of surveillance officers using tablets for household followups, and a management team that responds to the data.
-[](flowchart.png)
+![](flowchart.png)
In Coconut Surveillance, there are four kinds of interactions that lead to data being captured. The following sections describe the process in detail.
View
BIN  _attachments/documentation/coconut-surveillance-flowchart_0.png
Deleted file not rendered
View
2  _attachments/documentation/combine.sh
@@ -1 +1 @@
-pandoc -o CoconutDocumentation.docx Intro.markdown Case Notification.markdown Facility.markdown Houshold.markdown Household\ Member.markdown
+pandoc -o CoconutDocumentation.docx Intro.markdown "Case Notification.markdown" Facility.markdown Household.markdown "Household Member.markdown"
View
2  _attachments/index.html
@@ -71,11 +71,13 @@
<script type="text/javascript" src="js-libraries/rickshaw.min.js"></script>
<script type="text/javascript" src="js-libraries/latlong.js"></script>
<script type="text/javascript" src="js-libraries/html2canvas.js"></script>
+ <script type="text/javascript" src="js-libraries/markdown.min.js"></script>
<script src='http://maps.google.com/maps/api/js?v=3.2&sensor=false'></script>
<!-- START -->
<script type='text/javascript' src='app/config.js'></script>
+<script type='text/javascript' src='app/models/Alerts.js'></script>
<script type='text/javascript' src='app/models/Case.js'></script>
<script type='text/javascript' src='app/models/Config.js'></script>
<script type='text/javascript' src='app/models/FacilityHierarchy.js'></script>
View
2  _docs/version.json
@@ -1 +1 @@
-{"version":"1df750f","isApplicationDoc":true}
+{"version":"b072536","isApplicationDoc":true}
View
BIN  build_android_app/bin/classes.dex
Binary file not shown
View
326 documentation/FormDefinitions.markdown
@@ -1,326 +0,0 @@
-{
- "isApplicationDoc": true,
- "collection": "question",
- "questions": [
- {
- "label": "Facility Name",
- "type": "autocomplete from code",
- "autocomplete-options": "window.FacilityOptions = FacilityHierarchy.allFacilities()",
-
- },
- {
- "type": "text",
- "label": "Malaria Case ID",
- },
- {
- "label": "Shehia",
- "type": "autocomplete from code",
- "autocomplete-options": "window.ShehiaOptions = WardHierarchy.allWards()",
- },
- {
- "type": "text",
- "label": "Name",
- },
- {
- "label": "complete",
- "type": "checkbox",
- }
- ],
- "resultSummaryFields": {
- "Malaria Case ID": "on",
- "Facility Name": "on"
- },
-}
-{
- "isApplicationDoc": true,
- "resultSummaryFields": {
- "Facility Name": "on",
- "Shehia": "on",
- "Malaria Case ID": "on",
- "Head of Household Name": "on"
- },
- "collection": "question",
- "questions": [
- {
- "label": "Facility Name",
- "type": "autocomplete from code",
- "autocomplete-options": "window.FacilityOptions = FacilityHierarchy.allFacilities()",
- },
- {
- "label": "Malaria Case ID",
- "type": "text",
- },
- {
- "label": "Date of Positive Results",
- "type": "date",
- },
- {
- "label": "Parasite Species",
- "type": "radio",
- "radio-options": "PF,NF,Unknown,Not Applicable"
- },
- {
- "label": "Reference # in OPD Register",
- "type": "number",
- },
- {
- "label": "First Name",
- "type": "autocomplete from previous entries",
- },
- {
- "type": "autocomplete from previous entries",
- "required": "false",
- },
- {
- "label": "Last Name",
- "type": "autocomplete from previous entries",
- },
- {
- "label": "Age",
- "type": "number",
- },
- {
- "label": "Age in Months or Years",
- "type": "radio",
- "radio-options": "Years, Months,Unknown,Not Applicable"
- },
- {
- "label": "Sex",
- "type": "radio",
- "radio-options": "Male,Female,Unknown,Not Applicable"
- },
- {
- "label": "Shehia",
- "type": "autocomplete from code",
- "autocomplete-options": "window.ShehiaOptions = WardHierarchy.allWards()",
- },
- {
- "label": "Village",
- "type": "autocomplete from previous entries",
- },
- {
- "label": "Sheha/Mjumbe",
- "type": "autocomplete from previous entries",
- },
- {
- "label": "Head of Household Name",
- "type": "autocomplete from previous entries",
- },
- {
- "label": "Contact Mobile # (patient/relative)",
- "type": "text",
- },
- {
- "label": "Treatment Given",
- "type": "autocomplete from previous entries",
- },
- {
- "label": "Travelled Overnight in past month",
- "type": "radio",
- },
- {
- "label": "If YES, list ALL places travelled",
- "type": "text",
- "required": "false",
- "skip_logic": "ResultOfQuestion('TravelledOvernightinpastmonth').indexOf('No') >= 0 if ResultOfQuestion('TravelledOvernightinpastmonth')?",
- },
- {
- "label": "Comment/Remarks",
- "type": "autocomplete from previous entries",
- "required": "false",
- },
- {
- "label": "complete",
- "type": "checkbox",
- }
- ]
-}
-{
- "isApplicationDoc": true,
- "collection": "question",
- "questions": [
-
- {
- "label": "Reason for visiting household",
- "radio-options": "Index Case Household, Index Case Neighbors, Mass Screen",
- "type": "radio",
- "action_on_change": "if (ResultOfQuestion('MalariaCaseID') is null and value is 'Mass Screen') then $('[name=MalariaCaseID]').val(moment().format('YYMD') + Math.floor(Math.random()*100000))",
-
- },
-
- {
- "label": "Malaria Case ID",
- "type": "text",
- },
- {
- "label": "Head of Household Name",
- "type": "autocomplete from previous entries",
- },
- {
- "label": "Shehia",
- "type": "autocomplete from code",
- "autocomplete-options": "window.ShehiaOptions = WardHierarchy.allWards()",
- },
- {
- "label": "Village",
- "type": "autocomplete from previous entries",
- },
- {
- "label": "Sheha/Mjumbe",
- "type": "autocomplete from previous entries",
- },
- {
- "label": "Contact Mobile # (patient/relative)",
- "type": "text",
- },
- {
- "label": "Household Location",
- "required": "false",
- "type": "location",
- },
- {
- "type": "number",
- },
- {
- "label": "Number of LLIN",
- "type": "number",
- },
- {
- "label": "Number of Sleeping Places (beds/mattresses)",
- "type": "number",
- },
- {
- "label": "Number of Household Members with Fever or History of Fever Within Past Week",
- "type": "number",
- },
- {
- "label": "Number of Household Members Treated for Malaria Within Past Week",
- "type": "number",
- },
- {
- "radio-options": "Yes,No,Unknown,Not Applicable",
- "label": "Index case: If patient is female 15-45 years of age, is she is pregant?",
- "type": "radio",
- },
- {
- "label": "Index case: Patient's current status",
- "radio-options": "Feeling Better, Feeling Unchanged, Feeling Worse, Admitted, Died ",
- "type": "radio",
- },
- {
- "label": "Index case: Patient's treatment status",
- "radio-options": "Completed, In Progress, Stopped",
- "type": "radio",
- },
- {
- "label": "Index case: Slept under LLIN last night?",
- "radio-options": "Yes,No,Unknown,Not Applicable",
- "type": "radio",
- },
- {
- "label": "Last date of IRS",
- "type": "date",
- },
- {
- "label": "complete",
- "type": "checkbox",
- }
- ],
- "resultSummaryFields": {
- "Head of Household Name": "on",
- "Malaria Case ID": "on"
- },
-}
-{
- "isApplicationDoc": true,
- "questions": [
- {
- "label": "Malaria Case ID",
- "type": "text",
- },
- {
- "label": "Head of Household Name",
- "type": "autocomplete from previous entries",
- },
- {
- "label": "First Name",
- "type": "autocomplete from previous entries",
- },
- {
- "label": "Last Name",
- "type": "autocomplete from previous entries",
- },
- {
- "radio-options": "Yes,No,Unknown,Not Applicable",
- "type": "radio",
- },
- {
- "label": "Age",
- "type": "number",
- },
- {
- "label": "Age in Years or Months",
- "radio-options": "Years,Months,Unknown,Not Applicable",
- "type": "radio",
- },
- {
- "label": "Sex",
- "radio-options": "Male,Female,Unknown,Not Applicable",
- "type": "radio",
- },
- {
- "label": "Fever currently or in the last two weeks?",
- "radio-options": "Yes,No,Unknown,Not Applicable",
- "type": "radio",
- },
- {
- "label": "Current Body Temperature (°C)",
- "type": "number",
- },
- {
- "label": "Malaria Test Result",
- "radio-options": "PF,NPF,Mixed,Unknown,Not Applicable",
- "type": "radio",
- },
- {
- "radio-options": "Yes,No,Unknown,Not Applicable",
- "type": "radio",
- },
- {
- "label": "Referred to Health Facility?",
- "radio-options": "Yes,No,Unknown,Not Applicable",
- "type": "radio",
- },
- {
- "label": "Slept under LLIN last night?",
- "radio-options": "Yes,No,Unknown,Not Applicable",
- "type": "radio",
- },
- {
- "label": "Overnight Travel in past month?",
- "type": "radio",
- },
- {
- "label": "If yes list all places travelled",
- "type": "text",
- "required": "false",
- "skip_logic": "ResultOfQuestion('OvernightTravelinpastmonth').indexOf('No') >= 0 if ResultOfQuestion('OvernightTravelinpastmonth')?",
- },
- {
- "label": "Comments",
- "type": "autocomplete from previous entries",
- "required": "false",
- },
- {
- "label": "complete",
- "type": "checkbox",
- }
- ],
- "resultSummaryFields": {
- "Malaria Test Result": "on",
- "First Name": "on",
- "Malaria Case ID": "on",
- "Head of Household Name": "on"
- },
- "collection": "question",
-}
View
70 documentation/Forms.markdown
@@ -1,70 +0,0 @@
-In Coconut Surveillance, there are four kinds of interactions that lead to data being captured:
-
- 1) Data that is sent directly from the health facility. The health facility sends a notification via their mobile phone. When this notification is received, a SMS is sent to the DMSO for that health facility. This SMS tells the DMSO that they have a new case to followup. They must then get their tablet online (via mobile network or wifi) and press the "Get Data" button. This will download all new case data within that DMSO's distrct of responsibility.
-
-#Case Notification
-* Facility Name
-* Malaria Case ID
-* Shehia
-* Name
-* complete
-
-#Facility
-* Facility Name
-* Malaria Case ID
-* Date of Positive Results
-* Parasite Species
-* Reference # in OPD Register
-* First Name
-* Last Name
-* Age
-* Age in Months or Years
-* Sex
-* Shehia
-* Village
-* Sheha/Mjumbe
-* Head of Household Name
-* Contact Mobile # (patient/relative)
-* Treatment Given
-* Travelled Overnight in past month
-* If YES, list ALL places travelled
-* Comment/Remarks
-* complete
-
-#Household
-* Reason for visiting household
-* Malaria Case ID
-* Head of Household Name
-* Shehia
-* Village
-* Sheha/Mjumbe
-* Contact Mobile # (patient/relative)
-* Household Location
-* Number of LLIN
-* Number of Sleeping Places (beds/mattresses)
-* Number of Household Members with Fever or History of Fever Within Past Week
-* Number of Household Members Treated for Malaria Within Past Week
-* Index case: If patient is female 15-45 years of age, is she is pregant?
-* Index case: Patient's current status
-* Index case: Patient's treatment status
-* Index case: Slept under LLIN last night?
-* Last date of IRS
-* complete
-
-#Household Member
-* Malaria Case ID
-* Head of Household Name
-* First Name
-* Last Name
-* Age
-* Age in Years or Months
-* Sex
-* Fever currently or in the last two weeks?
-* Current Body Temperature (°C)
-* Malaria Test Result
-* Referred to Health Facility?
-* Slept under LLIN last night?
-* Overnight Travel in past month?
-* If yes list all places travelled
-* Comments
-* complete
Please sign in to comment.
Something went wrong with that request. Please try again.