diff --git a/.github/workflows/serve-install.yml b/.github/workflows/serve-install.yml index a5e634821..c78ce1f86 100644 --- a/.github/workflows/serve-install.yml +++ b/.github/workflows/serve-install.yml @@ -9,10 +9,13 @@ on: branches: - master - maint_upgrade_** + - ui_feature_** pull_request: branches: - master - maint_upgrade_** + - ui_feature_** + - service_rewrite_2023 schedule: # * is a special character in YAML so you have to quote this string - cron: '5 4 * * 0' diff --git a/README.md b/README.md index a1f23e99a..121684e0a 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,9 @@ e-mission phone app This is the phone component of the e-mission system. -:sparkles: This has now been upgraded to cordova android@9.0.0 and iOS@6.0.1 ([details](https://github.com/e-mission/e-mission-docs/issues/554)). It has also been upgraded to [android API 29](https://github.com/e-mission/e-mission-phone/pull/707/), [cordova-lib@10.0.0 and the most recent node and npm versions](https://github.com/e-mission/e-mission-phone/pull/708)It also now supports CI, so we should not have any build issues in the future. The limitations from the [previous upgrade](https://github.com/e-mission/e-mission-docs/issues/519) have all been resolved. This should be ready to build out of the box, after all the configuration files are changed. +:sparkles: This has been upgraded to the latest **Android**, **iOS**, **cordova-lib**, **node** and **npm** versions. __This is ready to build out of the box.__ + +The currently supported versions are in [`package.cordovabuild.json`](package.cordovabuild.json) Additional Documentation --- @@ -12,6 +14,14 @@ https://github.com/e-mission/e-mission-docs/tree/master/docs/e-mission-phone **Issues:** Since this repository is part of a larger project, all issues are tracked [in the central docs repository](https://github.com/e-mission/e-mission-docs/issues). If you have a question, [as suggested by the open source guide](https://opensource.guide/how-to-contribute/#communicating-effectively), please file an issue instead of sending an email. Since issues are public, other contributors can try to answer the question and benefit from the answer. +## Contents +#### 1. [Updating the UI only](#updating-the-ui-only) +#### 2. [End to End Testing](#end-to-end-testing) +#### 3. [Updating the e-mission-* plugins or adding new plugins](#updating-the-e-mission--plugins-or-adding-new-plugins) +#### 4. [Creating logos](#creating-logos) +#### 5. [Beta-testing debugging](#beta-testing-debugging) +#### 6. [Contributing](#contributing) + Updating the UI only --- [![osx-serve-install](https://github.com/e-mission/e-mission-phone/workflows/osx-serve-install/badge.svg)](https://github.com/e-mission/e-mission-phone/actions?query=workflow%3Aosx-serve-install) @@ -23,22 +33,13 @@ If you want to make only UI changes, (as opposed to modifying the existing plugi Run the setup script ``` -$ bash setup/setup_serve.sh -``` - -**(optional)** Configure by changing the files in `www/json`. -Defaults are in `www/json/*.sample` - -``` -$ ls www/json/*.sample -$ cp www/json/startupConfig.json.sample www/json/startupConfig.json -$ cp ..... www/json/connectionConfig.json +bash setup/setup_serve.sh ``` ### Activation (after install, and in every new shell) ``` -$ source setup/activate_serve.sh +source setup/activate_serve.sh ``` ### Running @@ -46,7 +47,7 @@ $ source setup/activate_serve.sh 1. Start the phonegap deployment server and note the URL(s) that the server is listening to. ``` - $ npm run serve + npm run serve .... [phonegap] listening on 10.0.0.14:3000 [phonegap] listening on 192.168.162.1:3000 @@ -56,7 +57,9 @@ $ source setup/activate_serve.sh .... ``` -1. Change the devapp connection URL to one of these (e.g. 192.168.162.1:3000) and press "Connect" +1. Change the devapp connection URL and press "Connect" + - If you are running the devapp in an emulator on the same machine as the devapp server, you may simply use localhost, which would be `127.0.0.1:3000` on iOS and `10.0.2.2:3000` on Android. + - If you are running the devapp on a different device, you must type the address manually (e.g. `192.168.162.1:3000`). Note that this is a local IP address; the devices must be on the same network 1. The app will now display the version of e-mission app that is in your local directory 1. The console logs will be displayed back in the server window (prefaced by `[console]`) 1. Breakpoints can be added by connecting through the browser @@ -65,7 +68,7 @@ $ source setup/activate_serve.sh **Ta-da!** :gift: If you change any of the files in the `www` directory, the app will automatically be re-loaded without manually restarting either the server or the app :tada: -**Note1**: You may need to scroll up, past all the warnings about `Content Security Policy has been added` to find the port that the server is listening to. +**Note**: You may need to scroll up, past all the warnings about `Content Security Policy has been added` to find the port that the server is listening to. End to end testing --- @@ -78,14 +81,15 @@ A lot of the visualizations that we display in the phone client come from the se are available in the [e-mission-server README](https://github.com/e-mission/e-mission-server/blob/master/README.md). -In order to make end to end testing easy, if the local server is started on a HTTP (versus HTTPS port), it is in development mode. By default, the phone app connects to the local server (localhost on iOS, [10.0.2.2 on android](https://stackoverflow.com/questions/5806220/how-to-connect-to-my-http-localhost-web-server-from-android-emulator-in-eclips)) with the `prompted-auth` authentication method. To connect to a different server, or to use a different authentication method, you need to create a `www/json/connectionConfig.json` file. More details on configuring authentication [can be found in the docs](https://github.com/e-mission/e-mission-docs/blob/master/docs/install/configuring_authentication.md). +The dynamic config (see https://github.com/e-mission/nrel-openpath-deploy-configs) controls the server endpoint that the phone app will connect to. If you are running the app in an emulator on the same machine as your local server (i.e. they share a `localhost`), you can use one of the `dev-emulator-*` configs (these configs have no `server` specified so `localhost` is assumed). -One advantage of using `skip` authentication in development mode is that any user email can be entered without a password. Developers can use one of the emails that they loaded test data for in step (3) above. So if the test data loaded was with `-u shankari@eecs.berkeley.edu`, then the login email for the phone app would also be `shankari@eecs.berkeley.edu`. +If you wish to connect to a different server, create your own config file according to https://github.com/e-mission/nrel-openpath-deploy-configs and specify the `server` field accordingly. The [deploy-configs](https://github.com/e-mission/nrel-openpath-deploy-configs/#testing-configs) repo has more information on this. Updating the e-mission-\* plugins or adding new plugins --- [![osx-build-ios](https://github.com/e-mission/e-mission-phone/actions/workflows/ios-build.yml/badge.svg)](https://github.com/e-mission/e-mission-phone/actions/workflows/ios-build.yml) [![osx-build-android](https://github.com/e-mission/e-mission-phone/actions/workflows/android-build.yml/badge.svg)](https://github.com/e-mission/e-mission-phone/actions/workflows/android-build.yml) +[![osx-android-prereq-sdk-install](https://github.com/e-mission/e-mission-phone/actions/workflows/android-automated-sdk-install.yml/badge.svg)](https://github.com/e-mission/e-mission-phone/actions/workflows/android-automated-sdk-install.yml) Pre-requisites --- @@ -97,7 +101,7 @@ Pre-requisites - Java 17. Tested with [OpenJDK 17 (Temurin) using Adoptium](https://adoptium.net). - android SDK; install manually or use setup script below. Note that you only need to run this once **per computer**. ``` - $ bash setup/prereq_android_sdk_install.sh + bash setup/prereq_android_sdk_install.sh ```
Expected output @@ -142,27 +146,38 @@ Installing (one time only) Run the setup script for the platform you want to build ``` -$ bash setup/setup_android_native.sh -AND/OR -$ bash setup/setup_ios_native.sh +bash setup/setup_android_native.sh ``` - -**(optional)** Configure by changing the files in `www/json`. -Defaults are in `www/json/*.sample` - +AND/OR ``` -$ ls www/json/*.sample -$ cp www/json/startupConfig.json.sample www/json/startupConfig.json -$ cp ..... www/json/connectionConfig.json +bash setup/setup_ios_native.sh ``` ### Activation (after install, and in every new shell) ``` -$ source setup/activate_native.sh +source setup/activate_native.sh ``` -### Activation (after install, and in every new shell) +
Expected Output + +``` +Activating nvm +Using version +Now using node (npm ) +npm version = +Adding cocoapods to the path +Verifying /Users//Library/Android/sk or /Users//Library/Android/sdk is set +Activating sdkman, and by default, gradle +Ensuring that we use the most recent version of the command line tools +Configuring the repo for building native code +Copied config.cordovabuild.xml -> config.xml and package.cordovabuild.json -> package.json +``` + +
+ + +### Enable HTTP support on android by editing `config.xml` If connecting to a development server over http, make sure to turn on http support on android @@ -172,14 +187,29 @@ If connecting to a development server over http, make sure to turn on http suppo ``` -### Run in the emulator +### Building the app + +We offer a set of build scripts to pick from, each of which: (i) bundle the JS with Webpack, and then (ii) proceed with a Cordova build. +The common use cases will be: + +- `npm run build` (to build for production on both Android and iOS platforms) +- `npm run build-prod-android` (to build for production on Android platform only) +- `npm run build-prod-ios` (to build for production on iOS platform only) + +There are a variety of options because Webpack can bundle the JS in 'production' or 'dev' mode, and you can build Android or iOS or both. +Find the full list of these scripts in [`package.cordovabuild.json`](package.cordovabuild.json) + +
Expected output (Android build) ``` -$ npx cordova emulate ios -AND/OR -$ npx cordova emulate android +BUILD SUCCESSFUL in 2m 48s +52 actionable tasks: 52 executed +Built the following apk(s): +/Users//e-mission-phone/platforms/android/app/build/outputs/apk/debug/app-debug.apk ``` +
+ Creating logos --- If you are building your own version of the app, you must have your own logo to @@ -223,19 +253,19 @@ Contributing Add the main repo as upstream - $ git remote add upstream https://github.com/covid19database/phone-app.git + git remote add upstream https://github.com/e-mission/e-mission-phone.git Create a new branch (IMPORTANT). Please do not submit pull requests from master - $ git checkout -b mybranch + git checkout -b mybranch Make changes to the branch and commit them - $ git commit + git commit Push the changes to your local fork - $ git push origin mybranch + git push origin mybranch Generate a pull request from the UI @@ -243,8 +273,14 @@ Address my review comments Once I merge the pull request, pull the changes to your fork and delete the branch ``` -$ git checkout master -$ git pull upstream master -$ git push origin master -$ git branch -d mybranch +git checkout master +``` +``` +git pull upstream master +``` +``` +git push origin master +``` +``` +git branch -d ``` diff --git a/bin/sign_and_align_keys.sh b/bin/sign_and_align_keys.sh index 261058bd5..9b60c3ade 100644 --- a/bin/sign_and_align_keys.sh +++ b/bin/sign_and_align_keys.sh @@ -4,13 +4,13 @@ PROJECT=$1 VERSION=$2 if [[ $# -eq 0 ]]; then - echo "No arguments supplied" + echo "sign_and_align_keys " exit 1 fi # Sign and release the L+ version # Make sure the highest supported version has the biggest version code -npm run build-prod-android +npm run build-prod-android-release # cp platforms/android/app/build/outputs/apk/release/app-release-unsigned.aab platforms/android/app/build/outputs/apk/app-release-signed-unaligned.apk jarsigner -verbose -sigalg SHA256withRSA -digestalg SHA-256 -keystore ../config_files/production.keystore ./platforms/android/app/build/outputs/bundle/release/app-release.aab androidproductionkey cp platforms/android/app/build/outputs/bundle/release/app-release.aab $1-build-$2.aab diff --git a/package.cordovabuild.json b/package.cordovabuild.json index b5d69872f..12da8b81a 100644 --- a/package.cordovabuild.json +++ b/package.cordovabuild.json @@ -125,7 +125,7 @@ "cordova-plugin-app-version": "0.1.14", "cordova-plugin-customurlscheme": "5.0.2", "cordova-plugin-device": "2.1.0", - "cordova-plugin-em-datacollection": "git+https://github.com/e-mission/e-mission-data-collection.git#v1.8.0", + "cordova-plugin-em-datacollection": "git+https://github.com/e-mission/e-mission-data-collection.git#v1.8.1", "cordova-plugin-em-opcodeauth": "git+https://github.com/e-mission/cordova-jwt-auth.git#v1.7.2", "cordova-plugin-em-server-communication": "git+https://github.com/e-mission/cordova-server-communication.git#v1.2.6", "cordova-plugin-em-serversync": "git+https://github.com/e-mission/cordova-server-sync.git#v1.3.2", diff --git a/setup/export_shared_dep_versions.sh b/setup/export_shared_dep_versions.sh index 930216b6e..2ac27d61b 100644 --- a/setup/export_shared_dep_versions.sh +++ b/setup/export_shared_dep_versions.sh @@ -11,4 +11,4 @@ export GRADLE_VERSION=7.6 export OSX_EXP_VERSION=12 export NVM_DIR="$HOME/.nvm" -export RUBY_PATH=$HOME/.gem/ruby/$RUBY_VERSION.0/bin +export RUBY_PATH=$HOME/.local/share/gem/ruby/$RUBY_VERSION.0/bin diff --git a/www/js/App.tsx b/www/js/App.tsx index 2187118fa..3c6c8bec9 100644 --- a/www/js/App.tsx +++ b/www/js/App.tsx @@ -91,9 +91,9 @@ const App = () => { {appContent} - { /* If we are past the consent page (route > CONSENT), the permissions popup can show if needed. - This also includes if onboarding is DONE altogether (because "DONE" is > "CONSENT") */ } - {(onboardingState && onboardingState.route > OnboardingRoute.CONSENT) && + { /* If we are fully consented, (route > PROTOCOL), the permissions popup can show if needed. + This also includes if onboarding is DONE altogether (because "DONE" is > "PROTOCOL") */ } + {(onboardingState && onboardingState.route > OnboardingRoute.PROTOCOL) && } diff --git a/www/js/components/QrCode.tsx b/www/js/components/QrCode.tsx index edd120c22..74c66863f 100644 --- a/www/js/components/QrCode.tsx +++ b/www/js/components/QrCode.tsx @@ -35,6 +35,11 @@ export function shareQR(message) { } const QrCode = ({ value, ...rest }) => { + let hasLink = value.toString().includes("//"); + if(!hasLink) { + value = "emission://login_token?token=" + value; + } + return ; }; diff --git a/www/js/control/ControlCollectionHelper.tsx b/www/js/control/ControlCollectionHelper.tsx index 99318b1ac..d93c498a9 100644 --- a/www/js/control/ControlCollectionHelper.tsx +++ b/www/js/control/ControlCollectionHelper.tsx @@ -21,7 +21,7 @@ type collectionConfig = { export async function forceTransition(transition) { try { - let result = forceTransitionWrapper(transition); + let result = await forceTransitionWrapper(transition); window.alert('success -> '+result); } catch (err) { window.alert('error -> '+err); @@ -132,7 +132,7 @@ const formatConfigForDisplay = function(config, accuracyOptions) { return retVal; } -const ControlSyncHelper = ({ editVis, setEditVis }) => { +const ControlCollectionHelper = ({ editVis, setEditVis }) => { const {colors} = useTheme(); const Logger = getAngularService("Logger"); @@ -172,7 +172,7 @@ const ControlSyncHelper = ({ editVis, setEditVis }) => { console.log("new config = ", localConfig); try{ let set = await setConfig(localConfig); - //TODO find way to not need control.update.complete event broadcast + setEditVis(false); } catch(err) { Logger.displayError("Error while setting collection config", err); } @@ -268,8 +268,7 @@ const ControlSyncHelper = ({ editVis, setEditVis }) => { {geofenceComponent} - @@ -282,4 +281,4 @@ const ControlSyncHelper = ({ editVis, setEditVis }) => { ); }; -export default ControlSyncHelper; +export default ControlCollectionHelper; diff --git a/www/js/control/ProfileSettings.jsx b/www/js/control/ProfileSettings.jsx index 8035c9462..e79a95d8d 100644 --- a/www/js/control/ProfileSettings.jsx +++ b/www/js/control/ProfileSettings.jsx @@ -42,7 +42,7 @@ const ProfileSettings = () => { const StartPrefs = getAngularService('StartPrefs'); //functions that come directly from an Angular service - const editCollectionConfig = () => setEditCollection(true); + const editCollectionConfig = () => setEditCollectionVis(true); const editSyncConfig = () => setEditSync(true); //states and variables used to control/create the settings @@ -60,7 +60,7 @@ const ProfileSettings = () => { const [showingSensed, setShowingSensed] = useState(false); const [showingLog, setShowingLog] = useState(false); const [editSync, setEditSync] = useState(false); - const [editCollection, setEditCollection] = useState(false); + const [editCollectionVis, setEditCollectionVis] = useState(false); // const [collectConfig, setCollectConfig] = useState({}); const [collectSettings, setCollectSettings] = useState({}); @@ -156,8 +156,13 @@ const ProfileSettings = () => { //ensure ui table updated when editor closes useEffect(() => { - refreshCollectSettings(); - }, [editCollection]) + if(editCollectionVis == false) { + setTimeout(function() { + console.log("closed editor, time to refresh collect"); + refreshCollectSettings(); + }, 1000); + } + }, [editCollectionVis]) async function refreshNotificationSettings() { console.debug('about to refreshNotificationSettings, notificationSettings = ', notificationSettings); @@ -252,13 +257,15 @@ const ProfileSettings = () => { async function userStartStopTracking() { const transitionToForce = collectSettings.trackingOn ? 'STOP_TRACKING' : 'START_TRACKING'; - forceTransition(transitionToForce); + await forceTransition(transitionToForce); refreshCollectSettings(); } - async function toggleLowAccuracy() { + async function toggleLowAccuracy() { let toggle = await helperToggleLowAccuracy(); - refreshCollectSettings(); + setTimeout(function() { + refreshCollectSettings(); + }, 1500); } const viewQRCode = function(e) { @@ -489,7 +496,7 @@ const ProfileSettings = () => { - + ); diff --git a/www/js/onboarding/OnboardingStack.tsx b/www/js/onboarding/OnboardingStack.tsx index a49bde3ab..c547fd074 100644 --- a/www/js/onboarding/OnboardingStack.tsx +++ b/www/js/onboarding/OnboardingStack.tsx @@ -2,7 +2,7 @@ import React, { useContext } from "react"; import { StyleSheet } from "react-native"; import { AppContext } from "../App"; import WelcomePage from "./WelcomePage"; -import ConsentPage from "./ConsentPage"; +import ProtocolPage from "./ProtocolPage"; import SurveyPage from "./SurveyPage"; import SaveQrPage from "./SaveQrPage"; import SummaryPage from "./SummaryPage"; @@ -19,8 +19,8 @@ const OnboardingStack = () => { return ; } else if (onboardingState.route == OnboardingRoute.SUMMARY) { return ; - } else if (onboardingState.route == OnboardingRoute.CONSENT) { - return ; + } else if (onboardingState.route == OnboardingRoute.PROTOCOL) { + return ; } else if (onboardingState.route == OnboardingRoute.SAVE_QR) { return ; } else if (onboardingState.route == OnboardingRoute.SURVEY) { diff --git a/www/js/onboarding/ConsentPage.tsx b/www/js/onboarding/ProtocolPage.tsx similarity index 85% rename from www/js/onboarding/ConsentPage.tsx rename to www/js/onboarding/ProtocolPage.tsx index 08aa3ab48..73961245a 100644 --- a/www/js/onboarding/ConsentPage.tsx +++ b/www/js/onboarding/ProtocolPage.tsx @@ -7,8 +7,9 @@ import { AppContext } from '../App'; import { getAngularService } from '../angular-react-helper'; import PrivacyPolicy from './PrivacyPolicy'; import { onboardingStyles } from './OnboardingStack'; +import { setProtocolDone } from './onboardingHelper'; -const ConsentPage = () => { +const ProtocolPage = () => { const { t } = useTranslation(); const context = useContext(AppContext); @@ -20,10 +21,8 @@ const ConsentPage = () => { }; function agree() { - const StartPrefs = getAngularService('StartPrefs'); - StartPrefs.markConsented().then((response) => { - refreshOnboardingState(); - }); + setProtocolDone(true); + refreshOnboardingState(); }; // privacy policy and data collection info, followed by accept/reject buttons @@ -40,4 +39,4 @@ const ConsentPage = () => { ); } -export default ConsentPage; +export default ProtocolPage; diff --git a/www/js/onboarding/SaveQrPage.tsx b/www/js/onboarding/SaveQrPage.tsx index 51f884886..658c66993 100644 --- a/www/js/onboarding/SaveQrPage.tsx +++ b/www/js/onboarding/SaveQrPage.tsx @@ -20,12 +20,15 @@ const SaveQrPage = ({ }) => { useEffect(() => { if (overallStatus == true && !registerUserDone) { - logDebug('permissions done, going to log in'); - login(onboardingState.opcode).then((response) => { - logDebug('login done, refreshing onboarding state'); - setRegisterUserDone(true); - preloadDemoSurveyResponse(); - refreshOnboardingState(); + const StartPrefs = getAngularService('StartPrefs'); + StartPrefs.markConsented().then((response) => { + logDebug('permissions done, going to log in'); + login(onboardingState.opcode).then((response) => { + logDebug('login done, refreshing onboarding state'); + setRegisterUserDone(true); + preloadDemoSurveyResponse(); + refreshOnboardingState(); + }); }); } else { logDebug('permissions not done, waiting'); diff --git a/www/js/onboarding/WelcomePage.tsx b/www/js/onboarding/WelcomePage.tsx index 3589923c8..5653218d7 100644 --- a/www/js/onboarding/WelcomePage.tsx +++ b/www/js/onboarding/WelcomePage.tsx @@ -5,7 +5,7 @@ import { Button, Dialog, Divider, IconButton, Surface, Text, TextInput, Touchabl import color from 'color'; import { initByUser } from '../config/dynamicConfig'; import { AppContext } from '../App'; -import { displayError } from "../plugin/logger"; +import { displayError, logDebug } from "../plugin/logger"; import { onboardingStyles } from './OnboardingStack'; import { Icon } from '../components/Icon'; @@ -20,12 +20,22 @@ const WelcomePage = () => { const [infoPopupVis, setInfoPopupVis] = useState(false); const [existingToken, setExistingToken] = useState(''); + const checkURL = function (result) { + let notCancelled = result.cancelled == false; + let isQR = result.format == "QR_CODE"; + let hasPrefix = result.text.split(":")[0] == "emission"; + let hasToken = result.text.includes("login_token?token"); + + logDebug("QR code " + result.text + " checks: cancel, format, prefix, params " + notCancelled + isQR + hasPrefix + hasToken); + + return notCancelled && isQR && hasPrefix && hasToken; + } + const scanCode = function() { - window.cordova.plugins.barcodeScanner.scan( + window['cordova'].plugins.barcodeScanner.scan( function (result) { console.debug("scanned code", result); - if (result.format == "QR_CODE" && - result.cancelled == false) { + if (checkURL(result)) { let text = result.text.split("=")[1]; console.log("found code", text); loginWithToken(text); diff --git a/www/js/onboarding/onboardingHelper.ts b/www/js/onboarding/onboardingHelper.ts index cfbebb40b..4a6ec202c 100644 --- a/www/js/onboarding/onboardingHelper.ts +++ b/www/js/onboarding/onboardingHelper.ts @@ -6,12 +6,12 @@ import { logDebug } from "../plugin/logger"; export const INTRO_DONE_KEY = 'intro_done'; // route = WELCOME if no config present -// route = SUMMARY if config present, but not consented and summary not done -// route = CONSENT if config present, but not consented and summary done -// route = SAVE_QR if config present, consented, but save qr not done +// route = SUMMARY if config present, but protocol not done and summary not done +// route = PROTOCOL if config present, but protocol not done and summary done +// route = SAVE_QR if config present, protocol done, but save qr not done // route = SURVEY if config present, consented and save qr done // route = DONE if onboarding is finished (intro_done marked) -export enum OnboardingRoute { WELCOME, SUMMARY, CONSENT, SAVE_QR, SURVEY, DONE }; +export enum OnboardingRoute { WELCOME, SUMMARY, PROTOCOL, SAVE_QR, SURVEY, DONE }; export type OnboardingState = { opcode: string, route: OnboardingRoute, @@ -20,6 +20,9 @@ export type OnboardingState = { export let summaryDone = false; export const setSummaryDone = (b) => summaryDone = b; +export let protocolDone = false; +export const setProtocolDone = (b) => protocolDone = b; + export let saveQrDone = false; export const setSaveQrDone = (b) => saveQrDone = b; @@ -40,10 +43,10 @@ export function getPendingOnboardingState(): Promise { route = OnboardingRoute.DONE; } else if (!config) { route = OnboardingRoute.WELCOME; - } else if (!isConsented && !summaryDone) { + } else if (!protocolDone && !summaryDone) { route = OnboardingRoute.SUMMARY; - } else if (!isConsented) { - route = OnboardingRoute.CONSENT; + } else if (!protocolDone) { + route = OnboardingRoute.PROTOCOL; } else if (!saveQrDone) { route = OnboardingRoute.SAVE_QR; } else { diff --git a/www/js/survey/multilabel/MultiLabelButtonGroup.tsx b/www/js/survey/multilabel/MultiLabelButtonGroup.tsx index ec56295eb..ca71721a7 100644 --- a/www/js/survey/multilabel/MultiLabelButtonGroup.tsx +++ b/www/js/survey/multilabel/MultiLabelButtonGroup.tsx @@ -100,11 +100,13 @@ const MultilabelButtonGroup = ({ trip, buttonsInline=false }) => { ) })} - - - + {trip.verifiability === 'can-verify' && ( + + + + )} dismiss()}> dismiss()}>