Skip to content

Commit d97cc39

Browse files
committed
Merge pull request #1180 from medic/rc
v0.4.9
2 parents 31d7b12 + 56e6d39 commit d97cc39

32 files changed

+532
-160
lines changed

Changes.md

+17
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,22 @@
11
# Medic Mobile Release Notes
22

3+
## 0.4.9
4+
5+
### TBD
6+
7+
- Fixed bug on node 0.12 in felix-couchdb. #1145
8+
9+
- Improved error handling when notifications (start/stop) configs are
10+
misconfigured. #1144
11+
12+
- Fixed bug in `exists` validation where it fails on some unicode characters.
13+
#1147
14+
15+
- Fixed Reporting Rates interface that was neglected and broken. #1030
16+
17+
- Fixed bug in exporting data by date, it's now inclusive. #1104
18+
19+
320
## 0.4.8
421

522
### Jul 14, 2015

api

Submodule api updated 1 file

kanso.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "medic",
33
"display_name": "Medic Mobile",
4-
"version": "0.4.8",
4+
"version": "0.4.9",
55
"description": "SMS data collection designed for rural environments.",
66
"long_description" : "Medic Mobile is a web based SMS data collection and analytics tool focused on community health care workers in rural environments. We help large health organizations collect and analyze data sent from health care workers using ordinary mobile phones.",
77
"url": "https://github.com/medic/medic-webapp",

lib/shows.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,13 @@ function onExportFormsSubmit(ev) {
5353
startkey = JSON.parse(params.startkey),
5454
endkey = JSON.parse(params.endkey),
5555
// moment doesn't like dates of '' or null
56-
startDate = moment(startVal || undefined),
57-
endDate = moment(endVal || undefined);
56+
startDate = moment.utc(startVal || undefined),
57+
endDate = moment.utc(endVal || undefined);
5858

5959
// flip dates if both have values and startDate's after endDate
6060
if (startVal !== '' && startDate > endDate) {
6161
endDate = startDate;
62-
startDate = moment(endVal || undefined);
62+
startDate = moment.utc(endVal || undefined);
6363
}
6464

6565
// optionally filter by date
@@ -69,7 +69,7 @@ function onExportFormsSubmit(ev) {
6969
}
7070
if (endVal !== '') {
7171
// update startkey for enddate as view is descending
72-
startkey.push(endDate.valueOf());
72+
startkey.push(endDate.add(1, 'days').valueOf());
7373
} else {
7474
startkey.push({});
7575
}

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "medic",
3-
"version": "0.4.8",
3+
"version": "0.4.9",
44
"repository": {
55
"type": "git",
66
"url": "git://github.com/medic/medic-webapp.git"

packages/kujua-reporting/css/base.less

+13-3
Original file line numberDiff line numberDiff line change
@@ -81,13 +81,17 @@
8181
font-size: 1.12em;
8282
font-weight: normal;
8383
margin: 0.7em 1em 0 0;
84+
i {
85+
margin: 0 0.7em 0 0;
86+
}
8487
}
8588
.row {
8689
margin: 0 10px;
8790
text-align: center;
8891
}
8992
.nav {
9093
display: inline-block;
94+
width: 75%;
9195
}
9296
.btn-group {
9397
margin: 3px;
@@ -130,7 +134,8 @@
130134
.mini-pie {
131135
font-size: 2em;
132136
margin-top: 5px;
133-
&.fa-times {
137+
&.fa-times,
138+
&.fa-warning {
134139
color: @red;
135140
}
136141
&.fa-check {
@@ -341,9 +346,9 @@
341346
#reporting-district-choice {
342347
padding-bottom: 40px;
343348
padding-top: 20px;
349+
text-align: center;
344350
.form-name {
345351
padding: 20px;
346-
text-align: center;
347352
}
348353
.district-name {
349354
padding: 10px 0 10px 20px;
@@ -393,4 +398,9 @@
393398
padding-top: 1.5em;
394399
}
395400
}
396-
}
401+
#date-nav {
402+
.nav {
403+
width: 100%;
404+
}
405+
}
406+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,271 @@
1+
var dust = require('dust-core'),
2+
appinfo = require('views/lib/appinfo'),
3+
_ = require('underscore');
4+
5+
var info;
6+
var initInfo = function() {
7+
if (!info || !info.translate) {
8+
info = appinfo.getAppInfo();
9+
}
10+
};
11+
12+
// add helpers
13+
_.extend(dust.helpers, {
14+
// Stolen from: https://github.com/linkedin/dustjs-helpers/blob/master/dist/dust-helpers.js
15+
tap: function(input, chunk, context) {
16+
// return given input if there is no dust reference to resolve
17+
// dust compiles a string/reference such as {foo} to a function
18+
if (typeof input !== "function") {
19+
return input;
20+
}
21+
22+
var dustBodyOutput = '',
23+
returnValue;
24+
25+
//use chunk render to evaluate output. For simple functions result will be returned from render call,
26+
//for dust body functions result will be output via callback function
27+
returnValue = chunk.tap(function(data) {
28+
dustBodyOutput += data;
29+
return '';
30+
}).render(input, context);
31+
32+
chunk.untap();
33+
34+
//assume it's a simple function call if return result is not a chunk
35+
if (returnValue.constructor !== chunk.constructor) {
36+
//use returnValue as a result of tap
37+
return returnValue;
38+
} else if (dustBodyOutput === '') {
39+
return false;
40+
} else {
41+
return dustBodyOutput;
42+
}
43+
},
44+
translate: function(chunk, context, bodies, params) {
45+
initInfo();
46+
var value = dust.helpers.tap(params.value, chunk, context);
47+
return chunk.write(info.translate(value));
48+
},
49+
formatDate: function(chunk, context, bodies, params) {
50+
var timestamp = Number(dust.helpers.tap(params.timestamp, chunk, context)),
51+
format = dust.helpers.tap(params.format, chunk, context);
52+
53+
if (_.isNaN(timestamp)) {
54+
timestamp = dust.helpers.tap(params.timestamp, chunk, context);
55+
}
56+
57+
// todo use data_format setting if format is not passed in
58+
format = format || 'DD, MMM YYYY, HH:mm:ss ZZ';
59+
60+
return chunk.write(moment(timestamp).format(format));
61+
},
62+
formName: function(chunk, context, bodies, params) {
63+
var form = dust.helpers.tap(params.form, chunk, context);
64+
65+
return chunk.write(sms_utils.getFormTitle(form));
66+
},
67+
contact: function(chunk, context, bodies, params) {
68+
initInfo();
69+
var entities = dust.helpers.tapObject(params.entities, chunk, context),
70+
to = dust.helpers.tap(params.to, chunk, context),
71+
verbose = dust.helpers.tap(params.verbose, chunk, context),
72+
from = dust.helpers.tap(params.from, chunk, context),
73+
contact,
74+
clinic;
75+
76+
if (!contact && entities) {
77+
contact = objectpath.get(
78+
entities,
79+
info.contact_display_short
80+
);
81+
if (!contact) {
82+
contact = entities.clinic && entities.clinic.name;
83+
}
84+
if (!contact && entities.contact && entities.contact.name) {
85+
contact = entities.contact.name;
86+
}
87+
}
88+
89+
if (!contact) {
90+
contact = from;
91+
}
92+
if (!contact) {
93+
contact = to;
94+
}
95+
if (!contact) {
96+
contact = '<i class="fa fa-question-circle" title="Unknown"></i>';
97+
}
98+
99+
if (verbose && entities) {
100+
var names = [],
101+
sep = '&raquo;',
102+
str = '';
103+
/*
104+
* Supports the following structures:
105+
*
106+
* <entities>
107+
* {clinic: <entities>}
108+
* {health_center: <entities>}
109+
*
110+
*/
111+
if (entities.clinic) {
112+
entities = entities.clinic;
113+
} else if (entities.health_center) {
114+
entities = entities.health_center;
115+
}
116+
str = objectpath.get(entities, 'parent.parent.name');
117+
if (str) {
118+
names = names.concat(str, sep);
119+
}
120+
str = objectpath.get(entities, 'parent.name');
121+
if (str) {
122+
names = names.concat(str, sep);
123+
}
124+
if (entities.name) {
125+
names = names.concat(entities.name, sep);
126+
}
127+
str = objectpath.get(entities, 'contact.rc_code');
128+
names = str ? names.concat('['+str+']') : names;
129+
str = objectpath.get(entities, 'contact.name');
130+
names = str ? names.concat(str) : names;
131+
if (to) {
132+
names.push(to);
133+
} else {
134+
str = objectpath.get(entities, 'contact.phone');
135+
names = str ? names.concat(str) : names;
136+
}
137+
contact = names.length ? names.join(' ') : contact;
138+
}
139+
140+
return chunk.write(contact);
141+
},
142+
tasksByState: function(chunk, context, bodies, params) {
143+
var array = dust.helpers.tapArray(params.array, chunk, context),
144+
state = dust.helpers.tap(params.state, chunk, context),
145+
matches;
146+
147+
matches = _.filter(array, function(item) {
148+
return item.state === state;
149+
});
150+
151+
return bodies.block(chunk, context.push(matches));
152+
},
153+
ifHasState: function(chunk, context, bodies, params) {
154+
var array = dust.helpers.tapArray(params.array, chunk, context),
155+
state = dust.helpers.tap(params.state, chunk, context),
156+
body = bodies.block,
157+
skip = bodies['else'],
158+
cond;
159+
160+
cond = _.find(array, function(item) {
161+
return item && item.state === state;
162+
});
163+
164+
165+
if (cond) {
166+
return chunk.render( bodies.block, context );
167+
} else if (skip) {
168+
return chunk.render( bodies['else'], context );
169+
} else {
170+
return chunk;
171+
}
172+
},
173+
countByState: function(chunk, context, bodies, params) {
174+
var array1 = dust.helpers.tapArray(params.array1, chunk, context),
175+
state = dust.helpers.tap(params.state, chunk, context),
176+
matches,
177+
array = [];
178+
179+
if (params.array2) {
180+
array1 = array1.concat(
181+
dust.helpers.tapArray(params.array2, chunk, context)
182+
);
183+
}
184+
185+
matches = _.filter(array1, function(item) {
186+
return item && item.state === state;
187+
});
188+
189+
return chunk.write(matches.length);
190+
},
191+
isAdmin: function(chunk, context, bodies, params) {
192+
var body = bodies.block,
193+
skip = bodies['else'];
194+
195+
if (data_records.isAdmin) {
196+
return chunk.render(bodies.block, context);
197+
} else if (skip) {
198+
return chunk.render(skip, context);
199+
} else {
200+
return chunk;
201+
}
202+
},
203+
hasPermission: function(chunk, context, bodies, params) {
204+
var body = bodies.block,
205+
skip = bodies['else'],
206+
permission = dust.helpers.tap(params.permission, chunk, context);
207+
208+
if (utils.hasPerm(data_records.userCtx, permission)) {
209+
return chunk.render(bodies.block, context);
210+
} else if (skip) {
211+
return chunk.render(skip, context);
212+
} else {
213+
return chunk;
214+
}
215+
},
216+
idx: function(chunk, context, bodies) {
217+
if (bodies.block) {
218+
return bodies.block(chunk, context.push(context.stack.index));
219+
}
220+
else {
221+
return chunk;
222+
}
223+
},
224+
if: function(chunk, context, bodies, params) {
225+
var body = bodies.block,
226+
skip = bodies['else'];
227+
228+
if( params && params.cond){
229+
var cond = params.cond;
230+
231+
cond = dust.helpers.tap(cond, chunk, context);
232+
233+
// strip all new line characters as they break eval
234+
if (cond) {
235+
cond = cond.replace(/\r?\n/g, '');
236+
}
237+
238+
// eval expressions with given dust references
239+
if(eval(cond)){
240+
if(body) {
241+
return chunk.render( bodies.block, context );
242+
}
243+
else {
244+
_console.log( "Missing body block in the if helper!" );
245+
return chunk;
246+
}
247+
}
248+
if(skip){
249+
return chunk.render( bodies['else'], context );
250+
}
251+
}
252+
// no condition
253+
else {
254+
_console.log( "No condition given in the if helper!" );
255+
}
256+
return chunk;
257+
},
258+
eq: function(chunk, context, bodies, params) {
259+
var actual = context.get(params.key) + '';
260+
var expected = params.value;
261+
if (actual === expected) {
262+
return chunk.render(bodies.block, context);
263+
} else if (bodies['else']) {
264+
return chunk.render(bodies['else'], context);
265+
} else {
266+
return chunk;
267+
}
268+
}
269+
});
270+
271+
module.exports = dust;

0 commit comments

Comments
 (0)