Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bunch of fixes from the NREL branch #737

Open
wants to merge 11 commits into
base: single_tenant_app_snapshot_unmaintained
Choose a base branch
from
2 changes: 1 addition & 1 deletion www/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
"profile": "Profile",
"tracking": "Tracking",
"medium-accuracy": "Medium accuracy",
"dark-theme": "Dark theme",
"demographic-survey": "Demographic Survey",
"force-sync": "Force sync",
"share": "Share",
"check-ui-updates": "Check for UI updates",
Expand Down
9 changes: 8 additions & 1 deletion www/js/control/general-settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ angular.module('emission.main.control',['emission.services',
ControlCollectionHelper, ControlSyncHelper,
ControlTransitionNotifyHelper,
CarbonDatasetHelper,
UpdateCheck,
SurveyLaunch, UpdateCheck,
CalorieCal, ClientStats, CommHelper, Logger,
$translate) {

Expand Down Expand Up @@ -484,6 +484,13 @@ angular.module('emission.main.control',['emission.services',
}
});
};

$scope.launchDemographicSurvey = function() {
SurveyLaunch.startSurveyPrefilled(
'https://ee.kobotoolbox.org/x/hEkHk50v',
'd[/arcEm5iPB4F9CQZR258k4r/group_hg4zz25/Here_is_your_UUID_wh_ake_any_change_to_it]');
}

$scope.expandDeveloperZone = function() {
if ($scope.collectionExpanded()) {
$scope.expanded = false;
Expand Down
7 changes: 4 additions & 3 deletions www/js/diary/infinite_scroll_list.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,10 @@ angular.module('emission.main.diary.infscrolllist',['ui-leaflet',
Logger.log("Received batch of size "+ctList.length);
ctList.reverse();
ctList.forEach($scope.populateBasicClasses);
ctList.forEach((trip) => {
ctList.forEach((trip, tIndex) => {
trip.userInput = {};
ConfirmHelper.INPUTS.forEach(function(item, index) {
$scope.populateManualInputs(trip, item, $scope.data.manualResultMap[item]);
$scope.populateManualInputs(trip, ctList[tIndex+1], item, $scope.data.manualResultMap[item]);
});
});
ctList.forEach(function(trip, index) {
Expand Down Expand Up @@ -252,11 +252,12 @@ angular.module('emission.main.diary.infscrolllist',['ui-leaflet',
/**
* Embed 'inputType' to the trip
*/
$scope.populateManualInputs = function (tripgj, inputType, inputList) {
$scope.populateManualInputs = function (tripgj, nextTripgj, inputType, inputList) {
// Check unprocessed labels first since they are more recent
// Massage the input to meet getUserInputForTrip expectations
const unprocessedLabelEntry = DiaryHelper.getUserInputForTrip(
{data: {properties: tripgj, features: [{}, {}, {}]}},
{data: {properties: nextTripgj, features: [{}, {}, {}]}},
inputList);
var userInputLabel = unprocessedLabelEntry? unprocessedLabelEntry.data.label : undefined;
if (!angular.isDefined(userInputLabel)) {
Expand Down
16 changes: 10 additions & 6 deletions www/js/diary/list.js
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,8 @@ angular.module('emission.main.diary.list',['ui-leaflet',
/**
* Embed 'inputType' to the trip
*/
$scope.populateInputFromTimeline = function (tripgj, inputType, inputList) {
var userInput = DiaryHelper.getUserInputForTrip(tripgj, inputList);
$scope.populateInputFromTimeline = function (tripgj, nextTripgj, inputType, inputList) {
var userInput = DiaryHelper.getUserInputForTrip(tripgj, nextTripgj, inputList);
if (angular.isDefined(userInput)) {
// userInput is an object with data + metadata
// the label is the "value" from the options
Expand Down Expand Up @@ -237,15 +237,20 @@ angular.module('emission.main.diary.list',['ui-leaflet',
DiaryHelper.directiveForTrip);
Timeline.setTripWrappers(currDayTripWrappers);

$scope.data.currDayTripWrappers.forEach(function(tripgj, index, array) {
$scope.data.currDayTripWrappers.forEach(function(tripgj, tripIndex, array) {
tripgj.userInput = {};
ConfirmHelper.INPUTS.forEach(function(item, index) {
$scope.populateInputFromTimeline(tripgj, item, $scope.data.unifiedConfirmsResults[item]);
$scope.populateInputFromTimeline(tripgj, array[tripIndex+1], item, $scope.data.unifiedConfirmsResults[item]);
});
$scope.populateBasicClasses(tripgj);
$scope.populateCommonInfo(tripgj);
});
$ionicScrollDelegate.scrollTop(true);
if ($rootScope.displayingIncident) {
$ionicScrollDelegate.scrollBottom(true);
$rootScope.displayingIncident = false;
} else {
$ionicScrollDelegate.scrollTop(true);
}
});
});

Expand Down Expand Up @@ -610,7 +615,6 @@ angular.module('emission.main.diary.list',['ui-leaflet',
} else {
Logger.log("currDay is not defined, load not complete");
}
$rootScope.displayingIncident = false;
}
});
});
Expand Down
43 changes: 34 additions & 9 deletions www/js/diary/services.js
Original file line number Diff line number Diff line change
Expand Up @@ -405,7 +405,7 @@ angular.module('emission.main.diary.services', ['emission.plugin.logger',
" " + ui.data.label + " logged at "+ ui.metadata.write_ts;
}

dh.getUserInputForTrip = function(tripgj, userInputList) {
dh.getUserInputForTrip = function(tripgj, nextTripgj, userInputList) {
if (userInputList.length < 20) {
console.log("Input list = "+userInputList.map(printUserInput));
}
Expand All @@ -431,13 +431,15 @@ angular.module('emission.main.diary.services', ['emission.plugin.logger',
+" trip = "+fmtTs(tripProp.start_ts, userInput.metadata.time_zone)
+" -> "+fmtTs(tripProp.end_ts, userInput.metadata.time_zone)
+" checks are ("+(userInput.data.start_ts >= tripProp.start_ts)
+" || "+(-(userInput.data.start_ts - tripProp.start_ts) <= 5 * 60)
+" && "+(userInput.data.start_ts <= tripProp.end_ts)
+" || "+(-(userInput.data.start_ts - tripProp.start_ts) <= 15 * 60)
+") && "+(userInput.data.end_ts <= tripProp.end_ts);
console.log(logStr);
// Logger.log(logStr);
}
return (userInput.data.start_ts >= tripProp.start_ts
|| -(userInput.data.start_ts - tripProp.start_ts) <= 5 * 60)
&& userInput.data.start_ts <= tripProp.end_ts
|| -(userInput.data.start_ts - tripProp.start_ts) <= 15 * 60)
&& userInput.data.end_ts <= tripProp.end_ts;
} else {
// we know that the trip is cleaned so we can use the fmt_time
Expand All @@ -448,14 +450,37 @@ angular.module('emission.main.diary.services', ['emission.plugin.logger',
+" -> "+fmtTs(userInput.data.end_ts, userInput.metadata.time_zone)
+" trip = "+tripProp.start_fmt_time
+" -> "+tripProp.end_fmt_time
+" checks are "+(userInput.data.start_ts >= tripProp.start_ts)
+" && ("+(userInput.data.end_ts <= tripProp.end_ts)
+" || "+((userInput.data.end_ts - tripProp.end_ts) <= 5 * 60)+")";
+" start checks are "+(userInput.data.start_ts >= tripProp.start_ts)
+" && "+(userInput.data.start_ts <= tripProp.end_ts)
+" end checks are "+(userInput.data.end_ts <= tripProp.end_ts)
+" || "+((userInput.data.end_ts - tripProp.end_ts) <= 15 * 60)+")";
Logger.log(logStr);
}
return userInput.data.start_ts >= tripProp.start_ts
&& (userInput.data.end_ts <= tripProp.end_ts ||
(userInput.data.end_ts - tripProp.end_ts) <= 5 * 60);
// https://github.com/e-mission/e-mission-docs/issues/476#issuecomment-747222181
const startChecks = userInput.data.start_ts >= tripProp.start_ts &&
userInput.data.start_ts <= tripProp.end_ts;
var endChecks = (userInput.data.end_ts <= tripProp.end_ts ||
(userInput.data.end_ts - tripProp.end_ts) <= 15 * 60);
if (startChecks && !endChecks) {
if (angular.isDefined(nextTripgj)) {
endChecks = userInput.data.end_ts <= nextTripgj.data.properties.start_ts;
Logger.log("Second level of end checks when the next trip is defined("+userInput.data.end_ts+" <= "+ nextTripgj.data.properties.start_ts+") = "+endChecks);
} else {
// next trip is not defined, last trip
endChecks = (userInput.data.end_local_dt.day == userInput.data.start_local_dt.day)
Logger.log("Second level of end checks for the last trip of the day");
Logger.log("compare "+userInput.data.end_local_dt.day + " with " + userInput.data.start_local_dt.day + " = " + endChecks);
}
if (endChecks) {
// If we have flipped the values, check to see that there
// is sufficient overlap
const overlapDuration = Math.min(userInput.data.end_ts, tripProp.end_ts) - Math.max(userInput.data.start_ts, tripProp.start_ts)
Logger.log("Flipped endCheck, overlap("+overlapDuration+
")/trip("+tripProp.duration+") = "+ (overlapDuration / tripProp.duration));
endChecks = (overlapDuration/tripProp.duration) > 0.5;
}
}
return startChecks && endChecks;
}
});
if (potentialCandidates.length === 0) {
Expand Down
75 changes: 70 additions & 5 deletions www/js/intro.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

angular.module('emission.intro', ['emission.splash.startprefs',
'emission.splash.updatecheck',
'emission.survey.launch',
'ionic-toast'])

.config(function($stateProvider) {
Expand All @@ -20,7 +21,7 @@ angular.module('emission.intro', ['emission.splash.startprefs',
})

.controller('IntroCtrl', function($scope, $state, $window, $ionicSlideBoxDelegate,
$ionicPopup, $ionicHistory, ionicToast, $timeout, CommHelper, StartPrefs, UpdateCheck, $translate) {
$ionicPopup, $ionicHistory, ionicToast, $timeout, CommHelper, StartPrefs, SurveyLaunch, UpdateCheck, $translate) {

$scope.platform = $window.device.platform;
$scope.osver = $window.device.version.split(".")[0];
Expand Down Expand Up @@ -135,12 +136,25 @@ angular.module('emission.intro', ['emission.splash.startprefs',
});
};

// Adapted from https://stackoverflow.com/a/63363662/4040267
// made available under a CC BY-SA 4.0 license

$scope.generateRandomToken = function(length) {
var randomInts = window.crypto.getRandomValues(new Uint8Array(length * 2));
var randomChars = Array.from(randomInts).map((b) => String.fromCharCode(b));
var randomString = randomChars.join("");
var validRandomString = window.btoa(randomString).replace(/[+/]/g, "");
return validRandomString.substring(0, length);
}

$scope.disagree = function() {
$state.go('root.main.heatmap');
};

$scope.agree = function() {
StartPrefs.markConsented().then(function(response) {
$scope.randomToken = $scope.generateRandomToken(8);
window.Logger.log("Signing in with random token "+$scope.randomToken);
$ionicHistory.clearHistory();
if ($state.is('root.intro')) {
$scope.next();
Expand All @@ -166,12 +180,62 @@ angular.module('emission.intro', ['emission.splash.startprefs',
});

alertPopup.then(function(res) {
window.Logger.log(window.Logger.LEVEL_INFO, errorMsg + ' ' + res);
});
window.Logger.log(window.Logger.LEVEL_INFO, errorMsg + ' ' + res); });
}

$scope.login = function() {
window.cordova.plugins.BEMJWTAuth.signIn().then(function(userEmail) {
$scope.startSurvey = function () {
SurveyLaunch.startSurveyPrefilled(
'https://ee.kobotoolbox.org/x/hEkHk50v',
'd[/arcEm5iPB4F9CQZR258k4r/group_hg4zz25/Here_is_your_UUID_wh_ake_any_change_to_it]');
}

$scope.tokenToClipboard = function() {
navigator.clipboard.writeText($scope.randomToken);
};

$scope.loginNew = function() {
$scope.login($scope.randomToken);
};

$scope.loginExisting = function() {
$scope.data = {};
const tokenPopup = $ionicPopup.show({
template: '<input type="String" ng-model="data.existing_token">',
title: 'Enter the existing token that you have',
scope: $scope,
buttons: [
{
text: '<b>OK</b>',
type: 'button-positive',
onTap: function(e) {
if (!$scope.data.existing_token) {
//don't allow the user to close unless he enters a username

e.preventDefault();
} else {
return $scope.data.existing_token;
}
}
},{
text: '<b>Cancel</b>',
type: 'button-stable',
onTap: function(e) {
return null;
}
}
]
});
tokenPopup.then(function(token) {
if (token != null) {
$scope.login(token);
}
}).catch(function(err) {
$scope.alertError(err);
});
};

$scope.login = function(token) {
window.cordova.plugins.BEMJWTAuth.setPromptedAuthToken(token).then(function(userEmail) {
// ionicToast.show(message, position, stick, time);
// $scope.next();
ionicToast.show(userEmail, 'middle', false, 2500);
Expand All @@ -184,6 +248,7 @@ angular.module('emission.intro', ['emission.splash.startprefs',
client: retVal
});
});
$scope.startSurvey();
$scope.finish();
}, function(errorResult) {
$scope.alertError('User registration error', errorResult);
Expand Down
6 changes: 2 additions & 4 deletions www/js/splash/startprefs.js
Original file line number Diff line number Diff line change
Expand Up @@ -167,11 +167,9 @@ angular.module('emission.splash.startprefs', ['emission.plugin.logger',
var temp = ReferralHandler.getReferralNavigation();
if (temp == 'goals') {
return {state: 'root.main.goals', params: {}};
} else if ($rootScope.tripConfirmParams) {
} else if ($rootScope.displayingIncident) {
logger.log("Showing tripconfirm from startprefs");
var startEndParams = $rootScope.tripConfirmParams;
$rootScope.tripConfirmParams = angular.undefined;
return {state: 'root.main.tripconfirm', params: startEndParams};
return {state: 'root.main.diary'};
} else if (angular.isDefined($rootScope.redirectTo)) {
var redirState = $rootScope.redirectTo;
$rootScope.redirectTo = undefined;
Expand Down
5 changes: 5 additions & 0 deletions www/js/tripconfirm/post-trip-prompt.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,10 +119,15 @@ angular.module('emission.tripconfirm.posttrip.prompt', ['emission.plugin.logger'
};

var displayCompletedTrip = function(notification, eventOpts) {
/*
$rootScope.tripConfirmParams = notification.data;
Logger.log("About to display completed trip from notification "+
JSON.stringify(notification.data));
$state.go("root.main.tripconfirm", notification.data);
*/
Logger.log("About to go to diary, which now displays draft information");
$rootScope.displayingIncident = true;
$state.go("root.main.diary");
};

var checkCategory = function(notification) {
Expand Down
9 changes: 2 additions & 7 deletions www/templates/control/main-control.html
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,8 @@
</label>
</div>
<div class="control-list-item">
<div class="control-list-text" translate>{{'.dark-theme'}}</div>
<label ng-click="toggleDarkTheme()" class="toggle control-list-toggle toggle-color">
<input type="checkbox" ng-checked="getDarkTheme()">
<div class="track">
<div class="handle"></div>
</div>
</label>
<div class="control-list-text" translate>{{'.demographic-survey'}}</div>
<div ng-click="launchDemographicSurvey()" class="control-icon-button"><i class="ion-clipboard"></i></div>
</div>
<div class="control-list-item">
<div class="control-list-text">{{carbonDatasetString}}</div>
Expand Down
19 changes: 12 additions & 7 deletions www/templates/intro/login.html
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
<ion-content>
<div class="intro-title">
<center><h3>Login via google</h3></center></div>
<center><h3>Login via anonymous token</h3></center>
<center>Token {{randomToken}}</center></div>

<div class="intro-text">
Currently, we only support logging in via google, since they support techniques
such as two factor authentication for greater security. Participants at UC
Berkeley can choose to login using either their CalNet ID or a personal gmail
account.
This unique randomly generated token is your identifier in the system.
<p>&nbsp;</p>
Nobody other than you knows that you are associated with this token. If you
want to communicate with the research team about the data collected about you,
please be prepared to provide this token.
<div class="intro-space"></div>
<button class="button button-block button-balanced" ng-click="login()">Login via Google</button>
</div>
<button class="button button-block button-balanced" ng-click="loginNew()">Login as {{randomToken}}</button>

If you already have a token from a previous install, you can use it instead to retain the same account. Note that there are no incorrect tokens. If you enter a token that does not match an existing one, we will create a new account.
<div class="intro-space"></div>
<button class="button button-block button-energized" ng-click="loginExisting()">Login with existing token</button>
</div>

</ion-content>