Skip to content

Commit 8a7254e

Browse files
committed
Merge branch 'release/1.9.8'
2 parents cf48415 + 7be57a1 commit 8a7254e

24 files changed

+329
-286
lines changed

Dashboard/app/js/lib/router/router.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,6 @@ FLOW.Router = Ember.Router.extend({
7070
connectOutlets: function (router, event) {
7171
router.get('applicationController').connectOutlet('navSurveys');
7272
router.set('navigationController.selected', 'navSurveys');
73-
FLOW.cascadeResourceControl.populate();
7473
},
7574

7675
doNewSurvey: function (router, event) {
@@ -105,8 +104,8 @@ FLOW.Router = Ember.Router.extend({
105104
FLOW.selectedControl.set('selectedSurvey', null);
106105
FLOW.selectedControl.set('selectedQuestion', null);
107106
FLOW.questionControl.set('OPTIONcontent', null);
107+
FLOW.cascadeResourceControl.populate();
108108
FLOW.attributeControl.populate();
109-
110109
}
111110
}),
112111

@@ -137,7 +136,6 @@ FLOW.Router = Ember.Router.extend({
137136
});
138137
// all questions should be closed when we enter
139138
FLOW.selectedControl.set('selectedQuestion', null);
140-
FLOW.attributeControl.populate();
141139
},
142140

143141
doEditQuestions: function (router, event) {

Dashboard/app/js/lib/views/maps/map-views-common.js

Lines changed: 36 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -217,28 +217,30 @@ FLOW.NavMapsView = FLOW.View.extend({
217217
var keyId = $(this).val();
218218
//if a survey is selected, load forms to form selector element.
219219
if($(this).find("option:selected").data('type') === 'PROJECT'){
220-
$.get('/rest/cartodb/forms?surveyId='+keyId, function(data, status) {
221-
var rows = [];
222-
if(data['forms'] && data['forms'].length > 0) {
223-
rows = data['forms'];
224-
rows.sort(function(el1, el2) {
225-
return self.compare(el1, el2, 'name')
226-
});
227-
228-
var hierarchyObject = self.hierarchyObject;
229-
230-
//create folder and/or survey select element
231-
var form_selector = $("<select></select>").attr("data-survey-id", keyId).attr("class", "form_selector");
232-
form_selector.append('<option value="">--' + Ember.String.loc('_choose_a_form') + '--</option>');
233-
234-
for(var i=0; i<rows.length; i++) {
235-
//append returned forms list to the firm selector element
236-
form_selector.append(
237-
$('<option></option>').val(rows[i]["id"]).html(rows[i]["name"]));
220+
$.get(
221+
'/rest/surveys?surveyGroupId='+keyId,
222+
function(data, status) {
223+
var rows = [];
224+
if(data['surveys'] && data['surveys'].length > 0) {
225+
rows = data['surveys'];
226+
rows.sort(function(el1, el2) {
227+
return self.compare(el1, el2, 'name')
228+
});
229+
230+
var hierarchyObject = self.hierarchyObject;
231+
232+
//create folder and/or survey select element
233+
var form_selector = $("<select></select>").attr("data-survey-id", keyId).attr("class", "form_selector");
234+
form_selector.append('<option value="">--' + Ember.String.loc('_choose_a_form') + '--</option>');
235+
236+
for(var i=0; i<rows.length; i++) {
237+
//append returned forms list to the firm selector element
238+
form_selector.append(
239+
$('<option></option>').val(rows[i]["keyId"]).html(rows[i]["name"]));
240+
}
241+
$("#survey_hierarchy").append(form_selector);
238242
}
239-
$("#survey_hierarchy").append(form_selector);
240-
}
241-
});
243+
});
242244

243245
var namedMapObject = {};
244246
namedMapObject['mapObject'] = map;
@@ -679,7 +681,11 @@ FLOW.NavMapsView = FLOW.View.extend({
679681
} else {
680682
videoString = questionAnswer;
681683
}
682-
clickedPointContent += videoString;
684+
685+
var videoFileUrl = FLOW.Env.photo_url_root+videoString.substring(videoString.lastIndexOf("/")+1);
686+
var videoContent = videoFileUrl+' <a href="'+videoFileUrl+'" target="_blank">'+Ember.String.loc('_open_video')+'</a>';
687+
688+
clickedPointContent += videoContent;
683689
break;
684690
case "CASCADE":
685691
case "OPTION":
@@ -760,13 +766,14 @@ FLOW.NavMapsView = FLOW.View.extend({
760766
if(self.hierarchyObject.length > 0){
761767
self.manageHierarchy(parentFolderId);
762768
}else{
763-
$.get('/rest/survey_groups'/*place survey_groups endpoint here*/
764-
, function(data, status){
765-
if(data['survey_groups'].length > 0){
766-
self.hierarchyObject = data['survey_groups'];
767-
self.manageHierarchy(parentFolderId);
768-
}
769-
});
769+
$.get(
770+
'/rest/survey_groups', /*place survey_groups endpoint here*/
771+
function(data, status){
772+
if(data['survey_groups'].length > 0){
773+
self.hierarchyObject = data['survey_groups'];
774+
self.manageHierarchy(parentFolderId);
775+
}
776+
});
770777
}
771778
},
772779

GAE/src/com/gallatinsystems/device/dao/DeviceDAO.java

Lines changed: 34 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -39,34 +39,39 @@ public class DeviceDAO extends BaseDAO<Device> {
3939
public DeviceDAO() {
4040
super(Device.class);
4141
}
42-
42+
4343
/**
44-
* gets a single device by phoneNumber. If phone number is not unique (this shouldn't happen),
45-
* it returns the first instance found.
44+
* Get a single device based on available attributes. The priority
45+
* given to these fields is: androidId, imei, phoneNumber.
46+
* If the device is not found using the most reliable fields, we'll
47+
* fall back to the next attr.
4648
*
47-
* @param phoneNumber
48-
* @return
49+
* @param androidId unique identifier. Reported from app v2.1.2 onwards
50+
* @param imei ESN number. Devices without a SIM card may not have this attr.
51+
* @param phoneNumber phone number or device MAC address
52+
* @return device matching this criteria, if found
4953
*/
50-
public Device get(String phoneNumber) {
51-
return super.findByProperty("phoneNumber", phoneNumber, STRING_TYPE);
52-
}
53-
54-
/**
55-
* gets a single device by imei/esn. If phone number is not unique (this shouldn't happen), it
56-
* returns the first instance found.
57-
*
58-
* @param imei
59-
* @return
60-
*/
61-
public Device getByImei(String imei) {
62-
if (Device.NO_IMEI.equals(imei)) {
54+
public Device getDevice(String androidId, String imei, String phoneNumber) {
55+
Device device = null;
56+
57+
if (StringUtils.isNotEmpty(androidId)) {
58+
// Devices registered with Flow app version > 2.1.2 will have reported
59+
// this attribute, which is the most reliable for identifying a device
60+
device = super.findByProperty("androidId", androidId, STRING_TYPE);
61+
}
62+
if (device == null && StringUtils.isNotEmpty(imei) && !"NO_IMEI".equals(imei)) {
6363
// WiFi only devices could have "NO_IMEI" as value
6464
// We want to fall back to search by `phoneNumber` (MAC address)
65-
return null;
65+
device = super.findByProperty("esn", imei, STRING_TYPE);
6666
}
67-
return super.findByProperty("esn", imei, STRING_TYPE);
67+
68+
if (device == null && StringUtils.isNotEmpty(phoneNumber)) {
69+
device = super.findByProperty("phoneNumber", phoneNumber, STRING_TYPE);
70+
}
71+
return device;
6872
}
6973

74+
7075
/**
7176
* Create or update device
7277
*
@@ -78,28 +83,25 @@ public Device getByImei(String imei) {
7883
* @param deviceIdentifier
7984
* @param imei
8085
*/
81-
public void updateDevice(String phoneNumber, Double lat,
82-
Double lon, Double accuracy, String version,
83-
String deviceIdentifier, String imei, String osVersion) {
86+
public void updateDevice(String phoneNumber, Double lat, Double lon,
87+
Double accuracy, String version, String deviceIdentifier,
88+
String imei, String osVersion, String androidId) {
8489
if (StringUtils.isEmpty(imei) && StringUtils.isEmpty(phoneNumber)) {
8590
return;
8691
}
8792

88-
Device d = null;
89-
if (imei != null) { // New Apps from 1.10.0 and on provide IMEI/ESN
90-
d = getByImei(imei);
91-
}
92-
93-
if (d == null) {
94-
d = get(phoneNumber); // Fall back to less-stable ID
95-
}
93+
Device d = getDevice(androidId, imei, phoneNumber);
9694
if (d == null) {
9795
// if device is null, we have to create it
9896
d = new Device();
9997
d.setCreatedDateTime(new Date());
10098
d.setDeviceType(DeviceType.CELL_PHONE_ANDROID);
101-
d.setPhoneNumber(phoneNumber);
10299
}
100+
// Update device properties
101+
d.setPhoneNumber(phoneNumber);
102+
d.setAndroidId(androidId);
103+
d.setLastLocationBeaconTime(new Date());
104+
d.setGallatinSoftwareManifest(version);
103105
if (lat != null && lon != null) {
104106
d.setLastKnownLat(lat);
105107
d.setLastKnownLon(lon);
@@ -114,8 +116,6 @@ public void updateDevice(String phoneNumber, Double lat,
114116
if (osVersion != null) {
115117
d.setOsVersion(osVersion);
116118
}
117-
d.setLastLocationBeaconTime(new Date());
118-
d.setGallatinSoftwareManifest(version);
119119
save(d);
120120
}
121121
}

GAE/src/com/gallatinsystems/device/domain/Device.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ public class Device extends BaseDomain {
3333
public static final String NO_IMEI = "NO_IMEI";
3434

3535
private DeviceType deviceType;
36+
private String androidId;
3637
private String phoneNumber;
3738
private String esn;
3839
private String deviceIdentifier;
@@ -46,6 +47,14 @@ public class Device extends BaseDomain {
4647
private Double lastKnownAccuracy;
4748
private Date lastLocationBeaconTime;
4849
private String deviceGroup;
50+
51+
public String getAndroidId() {
52+
return androidId;
53+
}
54+
55+
public void setAndroidId(String androidId) {
56+
this.androidId = androidId;
57+
}
4958

5059
public String getDeviceIdentifier() {
5160
return deviceIdentifier;

GAE/src/com/gallatinsystems/device/domain/DeviceFiles.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ public class DeviceFiles extends BaseDomain {
5050
private Text processingMessageText = null;
5151
private Long surveyInstanceId = null;
5252

53+
private String androidId;
5354
private String phoneNumber;
5455
private String checksum;
5556
private String imei;
@@ -117,6 +118,14 @@ public Status getStatus() {
117118
public void setStatus(Status status) {
118119
this.status = status;
119120
}
121+
122+
public String getAndroidId() {
123+
return androidId;
124+
}
125+
126+
public void setAndroidId(String androidId) {
127+
this.androidId = androidId;
128+
}
120129

121130
public String toString() {
122131
StringBuilder sb = new StringBuilder();

GAE/src/com/gallatinsystems/device/domain/DeviceSurveyJobQueue.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ public class DeviceSurveyJobQueue {
3333

3434
private String devicePhoneNumber;
3535
private String imei;
36+
private String androidId;
3637
private Long surveyID;
3738
private Date effectiveStartDate;
3839
private Date effectiveEndDate;
@@ -71,6 +72,14 @@ public void setAssignmentId(Long assignmentId) {
7172
this.assignmentId = assignmentId;
7273
}
7374

75+
public String getAndroidId() {
76+
return androidId;
77+
}
78+
79+
public void setAndroidId(String androidId) {
80+
this.androidId = androidId;
81+
}
82+
7483
public String getDevicePhoneNumber() {
7584
return devicePhoneNumber;
7685
}

GAE/src/com/gallatinsystems/survey/dao/DeviceSurveyJobQueueDAO.java

Lines changed: 32 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,11 @@
1616

1717
package com.gallatinsystems.survey.dao;
1818

19+
import java.util.ArrayList;
1920
import java.util.Date;
21+
import java.util.HashSet;
2022
import java.util.List;
23+
import java.util.Set;
2124

2225
import javax.jdo.PersistenceManager;
2326

@@ -31,31 +34,45 @@
3134
public class DeviceSurveyJobQueueDAO {
3235

3336
/**
34-
* lists all objects for a given imei or phoneNumber
35-
*
36-
* @param devicePhoneNumber
37-
* @param imei
38-
* @return
37+
* lists all objects for a given device
3938
*/
4039
@SuppressWarnings("unchecked")
41-
public List<DeviceSurveyJobQueue> get(String devicePhoneNumber, String imei) {
40+
public List<DeviceSurveyJobQueue> get(String devicePhoneNumber, String imei, String androidId) {
4241
PersistenceManager pm = PersistenceFilter.getManager();
43-
javax.jdo.Query query = pm.newQuery(DeviceSurveyJobQueue.class);
44-
45-
List<DeviceSurveyJobQueue> results = null;
46-
// lookup by imei first and filter out NO_IMEI ones
42+
43+
Set<DeviceSurveyJobQueue> set = new HashSet<>();
44+
javax.jdo.Query query;
45+
46+
// Query entities based on Android ID. This is the most reliable ID
47+
// and should be used whenever possible
48+
if (androidId != null) {
49+
query = pm.newQuery(DeviceSurveyJobQueue.class);
50+
query.setFilter("androidId == androidIdParam");
51+
query.declareParameters("String androidIdParam");
52+
set.addAll((List<DeviceSurveyJobQueue>) query.execute(androidId));
53+
}
54+
55+
// For legacy reasons, some assignments may only be identified by
56+
// IMEI or phone number
57+
List<DeviceSurveyJobQueue> legacy = null;
4758
if (imei != null && !Device.NO_IMEI.equals(imei)) {
59+
query = pm.newQuery(DeviceSurveyJobQueue.class);
4860
query.setFilter("imei == imeiParam");
4961
query.declareParameters("String imeiParam");
50-
results = (List<DeviceSurveyJobQueue>) query.execute(imei);
62+
legacy = (List<DeviceSurveyJobQueue>) query.execute(imei);
5163
}
52-
if (results == null || results.size() == 0) {
53-
// fall back to phonenumber
64+
if ((legacy == null || legacy.isEmpty()) && devicePhoneNumber != null) {
65+
// Fall back to phone number
66+
query = pm.newQuery(DeviceSurveyJobQueue.class);
5467
query.setFilter("devicePhoneNumber == devicePhoneNumberParam");
5568
query.declareParameters("String devicePhoneNumberParam");
56-
results = (List<DeviceSurveyJobQueue>) query.execute(devicePhoneNumber);
69+
legacy = (List<DeviceSurveyJobQueue>) query.execute(devicePhoneNumber);
5770
}
58-
return results;
71+
if (legacy != null) {
72+
set.addAll(legacy);
73+
}
74+
75+
return new ArrayList<>(set);
5976
}
6077

6178
/**
@@ -94,32 +111,6 @@ public List<DeviceSurveyJobQueue> listAllJobsInQueue() {
94111
return results;
95112
}
96113

97-
/**
98-
* delete a job with the phone number and survey id passed in
99-
*
100-
* @param phoneNumbers
101-
* @param surveyId
102-
*/
103-
@SuppressWarnings("unchecked")
104-
public void deleteJob(String phone, Long surveyId) {
105-
PersistenceManager pm = PersistenceFilter.getManager();
106-
if (phone != null && surveyId != null) {
107-
108-
javax.jdo.Query query = pm.newQuery(DeviceSurveyJobQueue.class);
109-
String filterString = "devicePhoneNumber == devicePhoneParam && surveyID == surveyIdParam";
110-
String paramString = "String devicePhoneParam, Long surveyIdParam";
111-
112-
query.setFilter(filterString);
113-
query.declareParameters(paramString);
114-
List<DeviceSurveyJobQueue> results = (List<DeviceSurveyJobQueue>) query
115-
.execute(phone, surveyId);
116-
if (results != null) {
117-
pm.deletePersistentAll(results);
118-
}
119-
120-
}
121-
}
122-
123114
/**
124115
* deletes all jobs for a given assignment
125116
*

0 commit comments

Comments
 (0)