diff --git a/.github/workflows/android-automated-sdk-install.yml b/.github/workflows/android-automated-sdk-install.yml
index 5e1efbbf5..f4275a98d 100644
--- a/.github/workflows/android-automated-sdk-install.yml
+++ b/.github/workflows/android-automated-sdk-install.yml
@@ -13,7 +13,7 @@ on:
- '.github/workflows/android-automated-sdk-install.yml'
schedule:
# * is a special character in YAML so you have to quote this string
- - cron: '5 4 * * 0'
+ - cron: '5 4 * * 0'
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
@@ -27,73 +27,73 @@ jobs:
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
- # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- - uses: actions/checkout@v2
+ # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
+ - uses: actions/checkout@v2
- # Runs a single command using the runners shell
- - name: Print the current SDK root and version
- run: |
- echo "SDK root before install $ANDROID_SDK_ROOT"
- cat $ANDROID_SDK_ROOT/cmdline-tools/latest/source.properties
- echo "Existing installed packages"
- $ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager --list_installed
+ # Runs a single command using the runners shell
+ - name: Print the current SDK root and version
+ run: |
+ echo "SDK root before install $ANDROID_SDK_ROOT"
+ cat $ANDROID_SDK_ROOT/cmdline-tools/latest/source.properties
+ echo "Existing installed packages"
+ $ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager --list_installed
- - name: Install to a new SDK root
- run: |
- export JAVA_HOME=$JAVA_HOME_17_X64
- export ANDROID_SDK_ROOT=$NEW_ANDROID_SDK_ROOT
- echo "New SDK root $ANDROID_SDK_ROOT"
- printf "Y\nY\nY\nY\nY\n" | bash setup/prereq_android_sdk_install.sh
+ - name: Install to a new SDK root
+ run: |
+ export JAVA_HOME=$JAVA_HOME_17_X64
+ export ANDROID_SDK_ROOT=$NEW_ANDROID_SDK_ROOT
+ echo "New SDK root $ANDROID_SDK_ROOT"
+ printf "Y\nY\nY\nY\nY\n" | bash setup/prereq_android_sdk_install.sh
- - name: Verify that all packages are as expected
- shell: bash -l {0}
- run: |
- export JAVA_HOME=$JAVA_HOME_17_X64
- echo "Comparing $ANDROID_SDK_ROOT and $NEW_ANDROID_SDK_ROOT"
- $ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager --list_installed > /tmp/existing_packages
- $NEW_ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager --list_installed > /tmp/new_packages
- diff -uw /tmp/existing_packages /tmp/new_packages
- echo "Expected differences; emulators, SDK versions, tool versions"
+ - name: Verify that all packages are as expected
+ shell: bash -l {0}
+ run: |
+ export JAVA_HOME=$JAVA_HOME_17_X64
+ echo "Comparing $ANDROID_SDK_ROOT and $NEW_ANDROID_SDK_ROOT"
+ $ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager --list_installed > /tmp/existing_packages
+ $NEW_ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager --list_installed > /tmp/new_packages
+ diff -uw /tmp/existing_packages /tmp/new_packages
+ echo "Expected differences; emulators, SDK versions, tool versions"
- - name: Verify that directory structure is consistent
- shell: bash -l -x {0}
- run: |
- export JAVA_HOME=$JAVA_HOME_17_X64
- export ANDROID_SDK_ROOT=$NEW_ANDROID_SDK_ROOT
- echo "New SDK root $ANDROID_SDK_ROOT"
- ls -al $ANDROID_SDK_ROOT
- if [ ! -d $ANDROID_SDK_ROOT/emulator ]; then exit 1; fi
- if [ ! -d $ANDROID_SDK_ROOT/build-tools ]; then exit 1; fi
- if [ ! -d $ANDROID_SDK_ROOT/patcher ]; then exit 1; fi
- if [ ! -d $ANDROID_SDK_ROOT/extras ]; then exit 1; fi
- if [ ! -d $ANDROID_SDK_ROOT/platforms ]; then exit 1; fi
- if [ ! -d $ANDROID_SDK_ROOT/platform-tools ]; then exit 1; fi
- if [ ! -d $ANDROID_SDK_ROOT/system-images ]; then exit 1; fi
+ - name: Verify that directory structure is consistent
+ shell: bash -l -x {0}
+ run: |
+ export JAVA_HOME=$JAVA_HOME_17_X64
+ export ANDROID_SDK_ROOT=$NEW_ANDROID_SDK_ROOT
+ echo "New SDK root $ANDROID_SDK_ROOT"
+ ls -al $ANDROID_SDK_ROOT
+ if [ ! -d $ANDROID_SDK_ROOT/emulator ]; then exit 1; fi
+ if [ ! -d $ANDROID_SDK_ROOT/build-tools ]; then exit 1; fi
+ if [ ! -d $ANDROID_SDK_ROOT/patcher ]; then exit 1; fi
+ if [ ! -d $ANDROID_SDK_ROOT/extras ]; then exit 1; fi
+ if [ ! -d $ANDROID_SDK_ROOT/platforms ]; then exit 1; fi
+ if [ ! -d $ANDROID_SDK_ROOT/platform-tools ]; then exit 1; fi
+ if [ ! -d $ANDROID_SDK_ROOT/system-images ]; then exit 1; fi
- - name: Ensure that the path is correct and installed programs are runnable
- shell: bash -l {0}
- run: |
- export JAVA_HOME=$JAVA_HOME_17_X64
- export ANDROID_SDK_ROOT=$NEW_ANDROID_SDK_ROOT
- echo "New SDK root $ANDROID_SDK_ROOT"
- echo "About to run the emulator at $ANDROID_SDK_ROOT/emulator/emulator"
- $ANDROID_SDK_ROOT/emulator/emulator -list-avds
- echo "About to run the avdmanager at $ANDROID_SDK_ROOT/cmdline-tools/latest/bin/avdmanager"
- $ANDROID_SDK_ROOT/cmdline-tools/latest/bin/avdmanager list avds
+ - name: Ensure that the path is correct and installed programs are runnable
+ shell: bash -l {0}
+ run: |
+ export JAVA_HOME=$JAVA_HOME_17_X64
+ export ANDROID_SDK_ROOT=$NEW_ANDROID_SDK_ROOT
+ echo "New SDK root $ANDROID_SDK_ROOT"
+ echo "About to run the emulator at $ANDROID_SDK_ROOT/emulator/emulator"
+ $ANDROID_SDK_ROOT/emulator/emulator -list-avds
+ echo "About to run the avdmanager at $ANDROID_SDK_ROOT/cmdline-tools/latest/bin/avdmanager"
+ $ANDROID_SDK_ROOT/cmdline-tools/latest/bin/avdmanager list avds
- - name: Setup the cordova environment
- shell: bash -l {0}
- run: |
- export JAVA_HOME=$JAVA_HOME_17_X64
- export ANDROID_SDK_ROOT=$NEW_ANDROID_SDK_ROOT
- bash setup/setup_android_native.sh
+ - name: Setup the cordova environment
+ shell: bash -l {0}
+ run: |
+ export JAVA_HOME=$JAVA_HOME_17_X64
+ export ANDROID_SDK_ROOT=$NEW_ANDROID_SDK_ROOT
+ bash setup/setup_android_native.sh
- - name: Ensure that the path is correct and the project can be activated
- shell: bash -l {0}
- run: |
- export JAVA_HOME=$JAVA_HOME_17_X64
- export ANDROID_SDK_ROOT=$NEW_ANDROID_SDK_ROOT
- echo "New SDK root $ANDROID_SDK_ROOT"
- source setup/activate_native.sh
- echo "About to run the avdmanager from the path" `which avdmanager`
- avdmanager list avd
+ - name: Ensure that the path is correct and the project can be activated
+ shell: bash -l {0}
+ run: |
+ export JAVA_HOME=$JAVA_HOME_17_X64
+ export ANDROID_SDK_ROOT=$NEW_ANDROID_SDK_ROOT
+ echo "New SDK root $ANDROID_SDK_ROOT"
+ source setup/activate_native.sh
+ echo "About to run the avdmanager from the path" `which avdmanager`
+ avdmanager list avd
diff --git a/.github/workflows/android-build.yml b/.github/workflows/android-build.yml
index 398a82d14..25eb65317 100644
--- a/.github/workflows/android-build.yml
+++ b/.github/workflows/android-build.yml
@@ -7,15 +7,15 @@ name: osx-build-android
on:
push:
branches:
- - master
- - maint_upgrade_**
+ - master
+ - maint_upgrade_**
pull_request:
branches:
- - master
- - maint_upgrade_**
+ - master
+ - maint_upgrade_**
schedule:
# * is a special character in YAML so you have to quote this string
- - cron: '5 4 * * 0'
+ - cron: '5 4 * * 0'
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
@@ -26,55 +26,55 @@ jobs:
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
- # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- - uses: actions/checkout@v2
+ # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
+ - uses: actions/checkout@v2
- # Runs a single command using the runners shell
- - name: Print the java and gradle versions
- run: |
- echo "Default java version"
- java -version
- echo "Setting to Java 11 instead"
- export JAVA_HOME=$JAVA_HOME_11_X64
- java -version
- echo "Checking gradle"
- which gradle
- gradle -version
+ # Runs a single command using the runners shell
+ - name: Print the java and gradle versions
+ run: |
+ echo "Default java version"
+ java -version
+ echo "Setting to Java 11 instead"
+ export JAVA_HOME=$JAVA_HOME_11_X64
+ java -version
+ echo "Checking gradle"
+ which gradle
+ gradle -version
- - name: Tries to figure out where android is installed
- run: |
- echo "Android listed at $ANDROID_SDK_ROOT"
- ls -al /opt/
+ - name: Tries to figure out where android is installed
+ run: |
+ echo "Android listed at $ANDROID_SDK_ROOT"
+ ls -al /opt/
- - name: Setup the cordova environment
- shell: bash -l {0}
- run: |
- export JAVA_HOME=$JAVA_HOME_11_X64
- bash setup/setup_android_native.sh
+ - name: Setup the cordova environment
+ shell: bash -l {0}
+ run: |
+ export JAVA_HOME=$JAVA_HOME_11_X64
+ bash setup/setup_android_native.sh
- - name: Check tool versions
- shell: bash -l {0}
- run: |
- export JAVA_HOME=$JAVA_HOME_11_X64
- source setup/activate_native.sh
- echo "cordova version"
- npx cordova -version
- echo "ionic version"
- npx ionic --version
- which gradle
- echo "gradle version"
- gradle -version
+ - name: Check tool versions
+ shell: bash -l {0}
+ run: |
+ export JAVA_HOME=$JAVA_HOME_11_X64
+ source setup/activate_native.sh
+ echo "cordova version"
+ npx cordova -version
+ echo "ionic version"
+ npx ionic --version
+ which gradle
+ echo "gradle version"
+ gradle -version
- - name: Build android
- shell: bash -l {0}
- run: |
- echo $PATH
- which gradle
- gradle -version
- echo "Let's rerun the activation"
- source setup/activate_native.sh
- export JAVA_HOME=$JAVA_HOME_11_X64
- echo $PATH
- which gradle
- gradle --version
- npx cordova build android
+ - name: Build android
+ shell: bash -l {0}
+ run: |
+ echo $PATH
+ which gradle
+ gradle -version
+ echo "Let's rerun the activation"
+ source setup/activate_native.sh
+ export JAVA_HOME=$JAVA_HOME_11_X64
+ echo $PATH
+ which gradle
+ gradle --version
+ npx cordova build android
diff --git a/.github/workflows/ci-test.yml b/.github/workflows/ci-test.yml
index 352e56e73..2c4ee344f 100644
--- a/.github/workflows/ci-test.yml
+++ b/.github/workflows/ci-test.yml
@@ -6,13 +6,13 @@ name: CI
# events but only for the master branch
on:
push:
- branches:
- - master
- - maint_upgrade_**
+ branches:
+ - master
+ - maint_upgrade_**
pull_request:
branches:
- - master
- - maint_upgrade_**
+ - master
+ - maint_upgrade_**
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
@@ -23,15 +23,15 @@ jobs:
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
- # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- - uses: actions/checkout@v2
+ # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
+ - uses: actions/checkout@v2
- # Runs a single command using the runners shell
- - name: Run a one-line script
- run: echo Hello, world!
+ # Runs a single command using the runners shell
+ - name: Run a one-line script
+ run: echo Hello, world!
- # Runs a set of commands using the runners shell
- - name: Run a multi-line script
- run: |
- echo Add other actions to build,
- echo test, and deploy your project.
+ # Runs a set of commands using the runners shell
+ - name: Run a multi-line script
+ run: |
+ echo Add other actions to build,
+ echo test, and deploy your project.
diff --git a/.github/workflows/ios-build.yml b/.github/workflows/ios-build.yml
index 8e2ce82bd..ad0ce2f01 100644
--- a/.github/workflows/ios-build.yml
+++ b/.github/workflows/ios-build.yml
@@ -7,15 +7,15 @@ name: osx-build-ios
on:
push:
branches:
- - master
- - maint_upgrade_**
+ - master
+ - maint_upgrade_**
pull_request:
branches:
- - master
- - maint_upgrade_**
+ - master
+ - maint_upgrade_**
schedule:
# * is a special character in YAML so you have to quote this string
- - cron: '5 4 * * 0'
+ - cron: '5 4 * * 0'
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
@@ -26,47 +26,48 @@ jobs:
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
- # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- - uses: actions/checkout@v2
+ # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
+ - uses: actions/checkout@v2
- # Runs a single command using the runners shell
- - name: Print the xcode path
- run: xcode-select --print-path
+ # Runs a single command using the runners shell
+ - name: Print the xcode path
+ run: xcode-select --print-path
- - name: Print the xcode setup
- run: xcodebuild -version -sdk
+ - name: Print the xcode setup
+ run: xcodebuild -version -sdk
- - name: Print the brew and ruby versions
- run: |
- echo "brew version is "`brew --version`
- echo "ruby version is" `ruby --version`
+ - name: Print the brew and ruby versions
+ run: |
+ echo "brew version is "`brew --version`
+ echo "ruby version is" `ruby --version`
- - name: Print applications through dmg
- run: ls /Applications
+ - name: Print applications through dmg
+ run: ls /Applications
- - name: Print applications through brew
- run: brew list --formula
+ - name: Print applications through brew
+ run: brew list --formula
- - name: Setup the cordova environment
- shell: bash -l {0}
- run: |
- bash setup/setup_ios_native.sh
+ - name: Setup the cordova environment
+ shell: bash -l {0}
+ run: |
+ bash setup/setup_ios_native.sh
- - name: Check tool versions
- shell: bash -l {0}
- run: |
- source setup/activate_native.sh
- echo "cordova version"
- npx cordova -version
- echo "ionic version"
- npx ionic --version
+ - name: Check tool versions
+ shell: bash -l {0}
+ run: |
+ source setup/activate_native.sh
+ echo "cordova version"
+ npx cordova -version
+ echo "ionic version"
+ npx ionic --version
- - name: Build ios
- shell: bash -l {0}
- run: |
- source setup/activate_native.sh
- npx cordova build ios
+ - name: Build ios
+ shell: bash -l {0}
+ run: |
+ source setup/activate_native.sh
+ npx cordova build ios
+
+ - name: Cleanup the cordova environment
+ shell: bash -l {0}
+ run: bash setup/teardown_ios_native.sh
- - name: Cleanup the cordova environment
- shell: bash -l {0}
- run: bash setup/teardown_ios_native.sh
diff --git a/.github/workflows/serve-install.yml b/.github/workflows/serve-install.yml
index 7833abd82..a5e634821 100644
--- a/.github/workflows/serve-install.yml
+++ b/.github/workflows/serve-install.yml
@@ -7,15 +7,15 @@ name: osx-serve-install
on:
push:
branches:
- - master
- - maint_upgrade_**
+ - master
+ - maint_upgrade_**
pull_request:
branches:
- - master
- - maint_upgrade_**
+ - master
+ - maint_upgrade_**
schedule:
# * is a special character in YAML so you have to quote this string
- - cron: '5 4 * * 0'
+ - cron: '5 4 * * 0'
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
@@ -26,40 +26,40 @@ jobs:
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
- # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- - uses: actions/checkout@v2
+ # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
+ - uses: actions/checkout@v2
- # Runs a single command using the runners shell
- - name: Print the xcode path
- run: xcode-select --print-path
+ # Runs a single command using the runners shell
+ - name: Print the xcode path
+ run: xcode-select --print-path
- - name: Print the xcode setup
- run: xcodebuild -version -sdk
+ - name: Print the xcode setup
+ run: xcodebuild -version -sdk
- - name: Print applications through dmg
- run: ls /Applications
+ - name: Print applications through dmg
+ run: ls /Applications
- - name: Print applications through brew
- run: brew list --formula
+ - name: Print applications through brew
+ run: brew list --formula
- - name: Setup the serve environment
- shell: bash -l {0}
- run: |
- bash setup/setup_serve.sh
+ - name: Setup the serve environment
+ shell: bash -l {0}
+ run: |
+ bash setup/setup_serve.sh
+
+ - name: Check tool versions
+ shell: bash -l {0}
+ run: |
+ source setup/activate_serve.sh
+ echo "cordova version"
+ npx cordova -version
+ echo "ionic version"
+ npx ionic --version
- - name: Check tool versions
- shell: bash -l {0}
- run: |
- source setup/activate_serve.sh
- echo "cordova version"
- npx cordova -version
- echo "ionic version"
- npx ionic --version
-
- - name: Run Jest tests
- shell: bash -l {0}
- run: |
- npx jest
+ - name: Run Jest tests
+ shell: bash -l {0}
+ run: |
+ npx jest
# TODO: figure out how to check that a server started correctly
# - name: Try starting it
diff --git a/OpenSourceLicenses.md b/OpenSourceLicenses.md
index e727e8524..5b0140821 100644
--- a/OpenSourceLicenses.md
+++ b/OpenSourceLicenses.md
@@ -1,11 +1,11 @@
This file lists the module dependencies for the project and their licenses.
1. Most of this module code is **not** redistributed, either in source or binary
- form. Instead, it is downloaded automatically using package managers and linked
- from the code. The module download includes the license and appropriate credit.
+form. Instead, it is downloaded automatically using package managers and linked
+from the code. The module download includes the license and appropriate credit.
1. So our primary check here is for modules which do not have a license, or
- which are GPL licensed.
+which are GPL licensed.
The original project was created based on the ionic starter tabs template
https://github.com/ionic-team/ionic-starter-tabs
@@ -17,84 +17,84 @@ These dependencies were checked in over time in order to support libraries that
did not have bower entries, or libraries that were modified with minor changes
based on bugs. TODO: Go through the modules, determine the changes and submit them as PRs 🚧
-| Module | License | Original code |
-| ------------------------------------------ | ----------------------------------- | ----------------------------------------------------- |
-| `www/manual_lib/angularjs-nvd3-directives` | Apache |
-| `www/manual_lib/fontawesome` | Icons: CC BY 4.0, Code: MIT License | https://fontawesome.com |
-| `www/manual_lib/ionic-datepicker` | MIT | https://github.com/rajeshwarpatlolla/ionic-datepicker |
-| `www/manual_lib/leaflet` | BSD 2-clause | https://github.com/Leaflet/Leaflet |
-| `www/manual_lib/ui-leaflet` | MIT | https://github.com/angular-ui/ui-leaflet 🗄️ |
+| Module | License | Original code |
+|--------|---------|---------------|
+| `www/manual_lib/angularjs-nvd3-directives` | Apache |
+| `www/manual_lib/fontawesome` | Icons: CC BY 4.0, Code: MIT License | https://fontawesome.com |
+| `www/manual_lib/ionic-datepicker` | MIT | https://github.com/rajeshwarpatlolla/ionic-datepicker |
+| `www/manual_lib/leaflet` | BSD 2-clause | https://github.com/Leaflet/Leaflet |
+| `www/manual_lib/ui-leaflet` | MIT | https://github.com/angular-ui/ui-leaflet 🗄️ |
## Javascript dependencies installed via bower
-| Module | License |
-| ------------------------------------------------------- | ------------------------------------------------------------------------------------------- |
-| `www/lib/ionic` | MIT (from [`bower.json`](https://github.com/ionic-team/ionic-bower/blob/v1.3.0/bower.json)) |
-| `www/lib/ionic-toast` | MIT |
-| `www/lib/moment` | MIT |
-| `www/lib/moment-timezone` | MIT |
-| `www/lib/Leaflet.awesome-markers` | MIT |
-| `www/lib/angular` | MIT |
-| `www/lib/angular-animate` | MIT |
-| `www/lib/angular-sanitize` | MIT |
-| `www/lib/angular-nvd3` | MIT |
-| `www/lib/angularLocalStorage` | MIT |
-| `www/lib/ng-walkthrough` | MIT |
-| `www/lib/animate.css` | MIT |
-| `www/lib/nz-tour` | MIT |
-| `www/lib/leaflet-plugins` | MIT |
-| `www/lib/angularjs-slider` | MIT |
-| `www/lib/angular-translate` | MIT |
-| `www/lib/angular-translate-loader-static-files` | MIT |
-| `www/lib/angular-translate-interpolation-messageformat` | MIT |
+| Module | License |
+|--------|---------|
+| `www/lib/ionic` | MIT (from [`bower.json`](https://github.com/ionic-team/ionic-bower/blob/v1.3.0/bower.json)) |
+| `www/lib/ionic-toast` | MIT |
+| `www/lib/moment` | MIT |
+| `www/lib/moment-timezone` | MIT |
+| `www/lib/Leaflet.awesome-markers` | MIT |
+| `www/lib/angular` | MIT |
+| `www/lib/angular-animate` | MIT |
+| `www/lib/angular-sanitize` | MIT |
+| `www/lib/angular-nvd3` | MIT |
+| `www/lib/angularLocalStorage` | MIT |
+| `www/lib/ng-walkthrough` | MIT |
+| `www/lib/animate.css` | MIT |
+| `www/lib/nz-tour` | MIT |
+| `www/lib/leaflet-plugins` | MIT |
+| `www/lib/angularjs-slider` | MIT |
+| `www/lib/angular-translate` | MIT |
+| `www/lib/angular-translate-loader-static-files` | MIT |
+| `www/lib/angular-translate-interpolation-messageformat` | MIT |
## Javascript dependencies installed via npm `package.json`
Note that some of these are only required for development, not for proper operation.
Not sure whether we should list them or not, but it doesn't hurt.
-| Module | License |
-| --------- | ------- |
-| phonegap | Apache |
-| fs-extra | MIT |
-| klaw-sync | MIT |
+| Module | License |
+|--------|---------|
+| phonegap | Apache |
+| fs-extra | MIT |
+| klaw-sync | MIT |
## Javascript dependencies installed via npm command line
-| Module | License |
-| ------- | ------- |
-| cordova | Apache |
-| bower | MIT |
-| ionic | MIT |
+| Module | License |
+|--------|---------|
+| cordova | Apache |
+| bower | MIT |
+| ionic | MIT |
## Cordova platforms, installed automatically
-| Module | License |
-| --------------- | ------- |
-| cordova-ios | Apache |
-| cordova-android | Apache |
+| Module | License |
+|--------|---------|
+| cordova-ios | Apache |
+| cordova-android | Apache |
## Cordova plugins, installed automatically
-| Module | License |
-| ------------------------------------------------------ | ------------ |
-| phonegap-plugin-push | MIT |
-| ionic-plugin-keyboard | Apache |
-| cordova-plugin-app-version | MIT |
-| cordova-plugin-file | Apache |
-| cordova-plugin-device | Apache |
-| cordova-plugin-whitelist | Apache |
-| cordova-plugin-customurlscheme | MIT |
-| cordova-plugin-email-composer | Apache |
-| cordova-plugin-x-socialsharing | MIT |
-| cordova-plugin-inappbrowser | Apache |
-| de.appplant.cordova.plugin.local-notification-ios9-fix | Apache |
-| cordova-plugin-ionic | MIT |
-| edu.berkeley.eecs.emission.cordova.auth | BSD 3-clause |
-| edu.berkeley.eecs.emission.cordova.comm | BSD 3-clause |
-| edu.berkeley.eecs.emission.cordova.datacollection | BSD 3-clause |
-| edu.berkeley.eecs.emission.cordova.serversync | BSD 3-clause |
-| edu.berkeley.eecs.emission.cordova.settings | BSD 3-clause |
-| edu.berkeley.eecs.emission.cordova.transitionnotify | BSD 3-clause |
-| edu.berkeley.eecs.emission.cordova.unifiedlogger | BSD 3-clause |
-| edu.berkeley.eecs.emission.cordova.usercache | BSD 3-clause |
+| Module | License |
+|--------|---------|
+| phonegap-plugin-push | MIT |
+| ionic-plugin-keyboard | Apache |
+| cordova-plugin-app-version | MIT |
+| cordova-plugin-file | Apache |
+| cordova-plugin-device | Apache |
+| cordova-plugin-whitelist | Apache |
+| cordova-plugin-customurlscheme | MIT |
+| cordova-plugin-email-composer | Apache |
+| cordova-plugin-x-socialsharing | MIT |
+| cordova-plugin-inappbrowser | Apache |
+| de.appplant.cordova.plugin.local-notification-ios9-fix | Apache |
+| cordova-plugin-ionic | MIT |
+| edu.berkeley.eecs.emission.cordova.auth | BSD 3-clause |
+| edu.berkeley.eecs.emission.cordova.comm | BSD 3-clause |
+| edu.berkeley.eecs.emission.cordova.datacollection | BSD 3-clause |
+| edu.berkeley.eecs.emission.cordova.serversync | BSD 3-clause |
+| edu.berkeley.eecs.emission.cordova.settings | BSD 3-clause |
+| edu.berkeley.eecs.emission.cordova.transitionnotify | BSD 3-clause |
+| edu.berkeley.eecs.emission.cordova.unifiedlogger | BSD 3-clause |
+| edu.berkeley.eecs.emission.cordova.usercache | BSD 3-clause |
diff --git a/README.md b/README.md
index 95551e6e8..a1f23e99a 100644
--- a/README.md
+++ b/README.md
@@ -1,21 +1,22 @@
-## e-mission phone app
+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.
-## Additional Documentation
-
+Additional Documentation
+---
Additional documentation has been moved to its own repository [e-mission-docs](https://github.com/e-mission/e-mission-docs). Specific e-mission-phone wikis can be found here:
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.
-## Updating the UI only
-
+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)
-If you want to make only UI changes, (as opposed to modifying the existing plugins, adding new plugins, etc), you can use the **new and improved** (as of June 2018) [e-mission dev app](https://github.com/e-mission/e-mission-devapp/) and install the most recent version from [releases](https://github.com/e-mission/e-mission-devapp/releases).
+If you want to make only UI changes, (as opposed to modifying the existing plugins, adding new plugins, etc), you can use the **new and improved** (as of June 2018) [e-mission dev app](https://github.com/e-mission/e-mission-devapp/) and install the most recent version from [releases](https://github.com/e-mission/e-mission-devapp/releases).
### Installing (one-time)
@@ -39,100 +40,95 @@ $ cp ..... www/json/connectionConfig.json
```
$ source setup/activate_serve.sh
```
-
+
### Running
1. Start the phonegap deployment server and note the URL(s) that the server is listening to.
- ```
- $ npm run serve
- ....
- [phonegap] listening on 10.0.0.14:3000
- [phonegap] listening on 192.168.162.1:3000
- [phonegap]
- [phonegap] ctrl-c to stop the server
- [phonegap]
- ....
- ```
-
+ ```
+ $ npm run serve
+ ....
+ [phonegap] listening on 10.0.0.14:3000
+ [phonegap] listening on 192.168.162.1:3000
+ [phonegap]
+ [phonegap] ctrl-c to stop the server
+ [phonegap]
+ ....
+ ```
+
1. Change the devapp connection URL to one of these (e.g. 192.168.162.1:3000) and press "Connect"
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
-
-
+ 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
- Safari ([enable develop menu](https://support.apple.com/guide/safari/use-the-safari-develop-menu-sfri20948/mac)): Develop -> Simulator -> index.html
- Chrome: chrome://inspect -> Remote target (emulator)
-
+
**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.
-## End to end testing
-
+End to end testing
+---
A lot of the visualizations that we display in the phone client come from the server. In order to do end to end testing, we need to run a local server and connect to it. Instructions for:
1. installing a local server,
-2. running it,
+2. running it,
3. loading it with test data, and
4. running analysis on it
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).
+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).
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`.
-## Updating the e-mission-\* plugins or adding new plugins
-
+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)
-## Pre-requisites
-
+Pre-requisites
+---
- the version of xcode used by the CI
- - to install a particular version, use [xcode-select](https://www.unix.com/man-page/OSX/1/xcode-select/)
- - or this [supposedly easier to use repo](https://github.com/xcpretty/xcode-install)
- - **NOTE**: the basic xcode install on Catalina was messed up for me due to a prior installation of command line tools. [These workarounds helped](https://github.com/nodejs/node-gyp/blob/master/macOS_Catalina.md).
+ - to install a particular version, use [xcode-select](https://www.unix.com/man-page/OSX/1/xcode-select/)
+ - or this [supposedly easier to use repo](https://github.com/xcpretty/xcode-install)
+ - **NOTE**: the basic xcode install on Catalina was messed up for me due to a prior installation of command line tools. [These workarounds helped](https://github.com/nodejs/node-gyp/blob/master/macOS_Catalina.md).
- git
- 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
- ```
- Downloading the command line tools for mac
- % Total % Received % Xferd Average Speed Time Time Time Current
- Dload Upload Total Spent Left Speed
- 100 114M 100 114M 0 0 8092k 0 0:00:14 0:00:14 --:--:-- 8491k
- Found downloaded file at /tmp/commandlinetools-mac-8092744_latest.zip
- Installing the command line tools
- Archive: /tmp/commandlinetools-mac-8092744_latest.zip
- ...
- Downloading the android SDK. This will take a LONG time and will require you to agree to lots of licenses.
- Do you wish to continue? (Y/N)Y
- ...
- Accept? (y/N): Y
- ...
- [====== ] 17% Downloading x86_64-23_r33.zip... s
- ```
+ ```
+ Downloading the command line tools for mac
+ % Total % Received % Xferd Average Speed Time Time Time Current
+ Dload Upload Total Spent Left Speed
+ 100 114M 100 114M 0 0 8092k 0 0:00:14 0:00:14 --:--:-- 8491k
+ Found downloaded file at /tmp/commandlinetools-mac-8092744_latest.zip
+ Installing the command line tools
+ Archive: /tmp/commandlinetools-mac-8092744_latest.zip
+ ...
+ Downloading the android SDK. This will take a LONG time and will require you to agree to lots of licenses.
+ Do you wish to continue? (Y/N)Y
+ ...
+ Accept? (y/N): Y
+ ...
+ [====== ] 17% Downloading x86_64-23_r33.zip... s
+ ```
-
- if you are not on the most recent version of OSX, `homebrew`
- - this allows us to install the current version of cocoapods without
- running into ruby incompatibilities - e.g.
- https://github.com/CocoaPods/CocoaPods/issues/11763
-
-## Important
+ - this allows us to install the current version of cocoapods without
+ running into ruby incompatibilities - e.g.
+ https://github.com/CocoaPods/CocoaPods/issues/11763
+Important
+---
Most of the recent issues encountered have been due to incompatible setup. We
have now:
-
- locked down the dependencies,
- created setup and teardown scripts to setup self-contained environments with
those dependencies, and
@@ -141,8 +137,8 @@ have now:
If you have setup failures, please compare the configuration in the passing CI
builds with your configuration. That is almost certainly the source of the error.
-## Installing (one time only)
-
+Installing (one time only)
+---
Run the setup script for the platform you want to build
```
@@ -184,8 +180,8 @@ AND/OR
$ npx cordova emulate android
```
-## Creating logos
-
+Creating logos
+---
If you are building your own version of the app, you must have your own logo to
avoid app store conficts. Updating the logo is very simple using the [`ionic
cordova resources`](https://ionicframework.com/docs/v3/cli/cordova/resources/)
@@ -193,20 +189,21 @@ command.
**Note**: You may have to install the [`cordova-res` package](https://github.com/ionic-team/cordova-res) for the command to work
-## Troubleshooting
+Troubleshooting
+---
- Make sure to use `npx ionic` and `npx cordova`. This is
because the setup script installs all the modules locally in a self-contained
environment using `npm install` and not `npm install -g`
- Check the CI to see whether there is a known issue
- Run the commands from the script one by one and see which fails
- - compare the failed command with the CI logs
+ - compare the failed command with the CI logs
- Another workaround is to delete the local environment and recreate it
- - javascript errors: `rm -rf node_modules && npm install`
- - native code compile errors: `rm -rf plugins && rm -rf platforms && npx cordova prepare`
-
-## Beta-testing debugging
+ - javascript errors: `rm -rf node_modules && npm install`
+ - native code compile errors: `rm -rf plugins && rm -rf platforms && npx cordova prepare`
+Beta-testing debugging
+---
If users run into problems, they have the ability to email logs to the
maintainer. These logs are in the form of an sqlite3 database, so they have to
be opened using `sqlite3`. Alternatively, you can export it to a csv with
@@ -221,7 +218,8 @@ $ python bin/csv_export_add_date.py /tmp/loggerDB.
$ less /tmp/loggerDB..withdate.log
```
-## Contributing
+Contributing
+---
Add the main repo as upstream
@@ -244,7 +242,6 @@ Generate a pull request from the UI
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
diff --git a/hooks/README.md b/hooks/README.md
index 0750672c2..d2563eab1 100644
--- a/hooks/README.md
+++ b/hooks/README.md
@@ -18,7 +18,6 @@
# under the License.
#
-->
-
# Cordova Hooks
This directory may contain scripts used to customize cordova commands. This
@@ -27,10 +26,9 @@ project root. Any scripts you add to these directories will be executed before
and after the commands corresponding to the directory name. Useful for
integrating your own build systems or integrating with version control systems.
-**Remember**: Make your scripts executable.
+__Remember__: Make your scripts executable.
## Hook Directories
-
The following subdirectories will be used for hooks:
after_build/
@@ -67,17 +65,19 @@ The following subdirectories will be used for hooks:
All scripts are run from the project's root directory and have the root directory passes as the first argument. All other options are passed to the script using environment variables:
-- CORDOVA_VERSION - The version of the Cordova-CLI.
-- CORDOVA_PLATFORMS - Comma separated list of platforms that the command applies to (e.g.: android, ios).
-- CORDOVA_PLUGINS - Comma separated list of plugin IDs that the command applies to (e.g.: org.apache.cordova.file, org.apache.cordova.file-transfer)
-- CORDOVA_HOOK - Path to the hook that is being executed.
-- CORDOVA_CMDLINE - The exact command-line arguments passed to cordova (e.g.: cordova run ios --emulate)
+* CORDOVA_VERSION - The version of the Cordova-CLI.
+* CORDOVA_PLATFORMS - Comma separated list of platforms that the command applies to (e.g.: android, ios).
+* CORDOVA_PLUGINS - Comma separated list of plugin IDs that the command applies to (e.g.: org.apache.cordova.file, org.apache.cordova.file-transfer)
+* CORDOVA_HOOK - Path to the hook that is being executed.
+* CORDOVA_CMDLINE - The exact command-line arguments passed to cordova (e.g.: cordova run ios --emulate)
If a script returns a non-zero exit code, then the parent cordova command will be aborted.
+
## Writing hooks
We highly recommend writting your hooks using Node.js so that they are
cross-platform. Some good examples are shown here:
[http://devgirl.org/2013/11/12/three-hooks-your-cordovaphonegap-project-needs/](http://devgirl.org/2013/11/12/three-hooks-your-cordovaphonegap-project-needs/)
+
diff --git a/hooks/after_platform_add/ios/ios_copy_locales.js b/hooks/after_platform_add/ios/ios_copy_locales.js
index e2e86676c..8a1d9eaa3 100755
--- a/hooks/after_platform_add/ios/ios_copy_locales.js
+++ b/hooks/after_platform_add/ios/ios_copy_locales.js
@@ -4,63 +4,61 @@ var fs = require('fs-extra');
var path = require('path');
var et = require('elementtree');
-const LOG_NAME = 'Copying locales: ';
+const LOG_NAME = "Copying locales: ";
module.exports = function (context) {
- // If ios platform is not installed, don't even execute
- var localesFolder = path.join(context.opts.projectRoot, 'locales/');
-
- if (context.opts.cordova.platforms.indexOf('ios') < 0 || !fs.existsSync(localesFolder)) return;
-
- console.log(LOG_NAME + 'Retrieving application name...');
- var config_xml = path.join(context.opts.projectRoot, 'config.xml');
- var data = fs.readFileSync(config_xml).toString();
- // If no data then no config.xml
- if (data) {
- var etree = et.parse(data);
- var applicationName = etree.findtext('./name');
- console.log(LOG_NAME + 'Your application is ' + applicationName);
+ // If ios platform is not installed, don't even execute
var localesFolder = path.join(context.opts.projectRoot, 'locales/');
- var languagesFolders = fs.readdirSync(localesFolder);
- // It's not problematic but we will remove them to have cleaner logs.
- var filterItems = ['.git', 'LICENSE', 'README.md'];
- languagesFolders = languagesFolders.filter((item) => !filterItems.includes(item));
- console.log(LOG_NAME + 'Languages found -> ' + languagesFolders);
- languagesFolders.forEach(function (language) {
- console.log(LOG_NAME + 'I found ' + language + ', I will now copy the files.');
- var platformRes = path.join(
- context.opts.projectRoot,
- 'platforms/ios/' + applicationName + '/Resources/',
- );
- var wwwi18n = path.join(context.opts.projectRoot, 'www/i18n/');
- var languageFolder = localesFolder + '/' + language;
+ if (context.opts.cordova.platforms.indexOf('ios') < 0 || !fs.existsSync(localesFolder))
+ return;
+
+ console.log(LOG_NAME + "Retrieving application name...")
+ var config_xml = path.join(context.opts.projectRoot, 'config.xml');
+ var data = fs.readFileSync(config_xml).toString();
+ // If no data then no config.xml
+ if (data) {
+ var etree = et.parse(data);
+ var applicationName = etree.findtext('./name');
+ console.log(LOG_NAME + "Your application is " + applicationName);
+ var localesFolder = path.join(context.opts.projectRoot, 'locales/');
+
+ var languagesFolders = fs.readdirSync(localesFolder);
+ // It's not problematic but we will remove them to have cleaner logs.
+ var filterItems = ['.git', 'LICENSE', 'README.md']
+ languagesFolders = languagesFolders.filter(item => !filterItems.includes(item));
+ console.log(LOG_NAME + "Languages found -> " + languagesFolders);
+ languagesFolders.forEach(function (language) {
+ console.log(LOG_NAME + 'I found ' + language + ", I will now copy the files.")
+ var platformRes = path.join(context.opts.projectRoot, 'platforms/ios/' + applicationName + "/Resources/");
+ var wwwi18n = path.join(context.opts.projectRoot, 'www/i18n/');
+ var languageFolder = localesFolder + "/" + language;
- var lproj = '/' + language + '.lproj';
- var lprojFolder = path.join(languageFolder, lproj);
- if (fs.existsSync(lprojFolder)) {
- console.log(LOG_NAME + 'Copying ' + lprojFolder + ' to ' + platformRes);
+ var lproj = "/" + language + ".lproj";
+ var lprojFolder = path.join(languageFolder, lproj);
+ if (fs.existsSync(lprojFolder)) {
+ console.log(LOG_NAME + "Copying " + lprojFolder + " to " + platformRes);
- var platformlproj = platformRes + lproj;
- if (!fs.existsSync(platformlproj)) {
- console.log(LOG_NAME + platformlproj + 'does not exist, I will create it.');
- fs.mkdirSync(platformlproj, { recursive: true });
- }
+ var platformlproj = platformRes + lproj;
+ if (!fs.existsSync(platformlproj)) {
+ console.log(LOG_NAME + platformlproj + "does not exist, I will create it.");
+ fs.mkdirSync(platformlproj, {recursive: true} );
+ }
- fs.copySync(lprojFolder, platformlproj);
- console.log(LOG_NAME + lprojFolder + 'copied...');
- } else {
- console.log(LOG_NAME + lprojFolder + ' not found, I will continue.');
- }
+ fs.copySync(lprojFolder, platformlproj);
+ console.log(LOG_NAME + lprojFolder + "copied...")
+ } else {
+ console.log(LOG_NAME + lprojFolder + " not found, I will continue.")
+ }
- var languagei18n = path.join(languageFolder, '/i18n/');
- if (fs.existsSync(languagei18n)) {
- console.log(LOG_NAME + 'Copying ' + languagei18n + ' to ' + wwwi18n);
- fs.copySync(languagei18n, wwwi18n);
- console.log(LOG_NAME + languagei18n + 'copied...');
- } else {
- console.log(LOG_NAME + languagei18n + ' not found, I will continue.');
- }
- });
- }
-};
+ var languagei18n = path.join(languageFolder, "/i18n/");
+ if (fs.existsSync(languagei18n)) {
+ console.log(LOG_NAME + "Copying " + languagei18n + " to " + wwwi18n);
+ fs.copySync(languagei18n, wwwi18n);
+ console.log(LOG_NAME + languagei18n + "copied...")
+ } else {
+ console.log(LOG_NAME + languagei18n + " not found, I will continue.")
+ }
+ });
+ }
+}
diff --git a/hooks/after_prepare/010_add_platform_class.js b/hooks/after_prepare/010_add_platform_class.js
index 19ff5724b..bda3e4158 100755
--- a/hooks/after_prepare/010_add_platform_class.js
+++ b/hooks/after_prepare/010_add_platform_class.js
@@ -22,19 +22,20 @@ function addPlatformBodyTag(indexPath, platform) {
var html = fs.readFileSync(indexPath, 'utf8');
var bodyTag = findBodyTag(html);
- if (!bodyTag) return; // no opening body tag, something's wrong
+ if(!bodyTag) return; // no opening body tag, something's wrong
- if (bodyTag.indexOf(platformClass) > -1) return; // already added
+ if(bodyTag.indexOf(platformClass) > -1) return; // already added
var newBodyTag = bodyTag;
var classAttr = findClassAttr(bodyTag);
- if (classAttr) {
+ if(classAttr) {
// body tag has existing class attribute, add the classname
- var endingQuote = classAttr.substring(classAttr.length - 1);
- var newClassAttr = classAttr.substring(0, classAttr.length - 1);
+ var endingQuote = classAttr.substring(classAttr.length-1);
+ var newClassAttr = classAttr.substring(0, classAttr.length-1);
newClassAttr += ' ' + platformClass + ' ' + cordovaClass + endingQuote;
newBodyTag = bodyTag.replace(classAttr, newClassAttr);
+
} else {
// add class attribute to the body tag
newBodyTag = bodyTag.replace('>', ' class="' + platformClass + ' ' + cordovaClass + '">');
@@ -45,46 +46,49 @@ function addPlatformBodyTag(indexPath, platform) {
fs.writeFileSync(indexPath, html, 'utf8');
process.stdout.write('add to body class: ' + platformClass + '\n');
- } catch (e) {
+ } catch(e) {
process.stdout.write(e);
}
}
function findBodyTag(html) {
// get the body tag
- try {
+ try{
return html.match(/])(.*?)>/gi)[0];
- } catch (e) {}
+ }catch(e){}
}
function findClassAttr(bodyTag) {
// get the body tag's class attribute
- try {
+ try{
return bodyTag.match(/ class=["|'](.*?)["|']/gi)[0];
- } catch (e) {}
+ }catch(e){}
}
if (rootdir) {
+
// go through each of the platform directories that have been prepared
- var platforms = process.env.CORDOVA_PLATFORMS ? process.env.CORDOVA_PLATFORMS.split(',') : [];
+ var platforms = (process.env.CORDOVA_PLATFORMS ? process.env.CORDOVA_PLATFORMS.split(',') : []);
- for (var x = 0; x < platforms.length; x++) {
+ for(var x=0; x ' + dstName);
- fs.copySync(srcName, dstName);
- }
+var copyAllIcons = function(iconDir) {
+ var densityDirs = klawSync(iconDir, {nofile: true})
+ // console.log("densityDirs = "+JSON.stringify(densityDirs));
+ densityDirs.forEach(function(dDir) {
+ var files = klawSync(dDir.path, {nodir: true});
+ files.forEach(function(file) {
+ var dirName = path.basename(dDir.path);
+ var fileName = path.basename(file.path);
+ if (dirName.startsWith("mipmap")) {
+ var drawableName = dirName.replace("mipmap", "drawable");
+ var srcName = path.join(iconDir, dirName, fileName);
+ var dstName = path.join(iconDir, drawableName, fileName);
+ console.log("About to copy file "+srcName+" -> "+dstName);
+ fs.copySync(srcName, dstName);
+ }
+ });
});
- });
};
-var copyIconsFromAllDirs = function () {
+var copyIconsFromAllDirs = function() {
// Ensure that the res directory exists
fs.mkdirsSync(androidPlatformsDir);
copyAllIcons(androidPlatformsDir);
-};
+}
var platformList = process.env.CORDOVA_PLATFORMS;
if (platformList == undefined) {
- console.log('Testing by running standalone script, invoke anyway');
+ console.log("Testing by running standalone script, invoke anyway");
copyIconsFromAllDirs();
} else {
- var platforms = platformList.split(',');
+ var platforms = platformList.split(",");
if (platforms.indexOf('android') < 0) {
- console.log('Android platform not specified, skipping...');
+ console.log("Android platform not specified, skipping...");
} else {
copyIconsFromAllDirs();
}
diff --git a/hooks/after_prepare/020_copy_notification_icons.js b/hooks/after_prepare/020_copy_notification_icons.js
index 91ff6a5b0..f50171524 100755
--- a/hooks/after_prepare/020_copy_notification_icons.js
+++ b/hooks/after_prepare/020_copy_notification_icons.js
@@ -2,46 +2,45 @@
var fs = require('fs-extra');
var path = require('path');
-var klawSync = require('klaw-sync');
+var klawSync = require('klaw-sync')
-var androidPlatformsDir = path.resolve(__dirname, '../../platforms/android/res');
+var androidPlatformsDir = path.resolve(__dirname, '../../platforms/android/res');
var notificationIconsList = [
path.resolve(__dirname, '../../resources/android/ic_mood_question'),
- path.resolve(__dirname, '../../resources/android/ic_question_answer'),
-];
+ path.resolve(__dirname, '../../resources/android/ic_question_answer')];
-var copyAllIcons = function (iconDir) {
- var densityDirs = klawSync(iconDir, { nofile: true });
- // console.log("densityDirs = "+JSON.stringify(densityDirs));
- densityDirs.forEach(function (dDir) {
- var files = klawSync(dDir.path, { nodir: true });
- files.forEach(function (file) {
- var dirName = path.basename(dDir.path);
- var fileName = path.basename(file.path);
- var srcName = path.join(iconDir, dirName, fileName);
- var dstName = path.join(androidPlatformsDir, dirName, fileName);
- console.log('About to copy file ' + srcName + ' -> ' + dstName);
- fs.copySync(srcName, dstName);
+var copyAllIcons = function(iconDir) {
+ var densityDirs = klawSync(iconDir, {nofile: true})
+ // console.log("densityDirs = "+JSON.stringify(densityDirs));
+ densityDirs.forEach(function(dDir) {
+ var files = klawSync(dDir.path, {nodir: true});
+ files.forEach(function(file) {
+ var dirName = path.basename(dDir.path);
+ var fileName = path.basename(file.path);
+ var srcName = path.join(iconDir, dirName, fileName);
+ var dstName = path.join(androidPlatformsDir, dirName, fileName);
+ console.log("About to copy file "+srcName+" -> "+dstName);
+ fs.copySync(srcName, dstName);
+ });
});
- });
};
-var copyIconsFromAllDirs = function () {
- notificationIconsList.forEach(function (iconDir) {
- console.log('About to copy icons from ' + iconDir);
+var copyIconsFromAllDirs = function() {
+ notificationIconsList.forEach(function(iconDir) {
+ console.log("About to copy icons from "+iconDir);
copyAllIcons(iconDir);
});
-};
+}
var platformList = process.env.CORDOVA_PLATFORMS;
if (platformList == undefined) {
- console.log('Testing by running standalone script, invoke anyway');
+ console.log("Testing by running standalone script, invoke anyway");
copyIconsFromAllDirs();
} else {
- var platforms = platformList.split(',');
+ var platforms = platformList.split(",");
if (platforms.indexOf('android') < 0) {
- console.log('Android platform not specified, skipping...');
+ console.log("Android platform not specified, skipping...");
} else {
copyIconsFromAllDirs();
}
diff --git a/hooks/before_build/android/android_change_compile_implementation.js b/hooks/before_build/android/android_change_compile_implementation.js
index 8a5b51452..0e2e51999 100755
--- a/hooks/before_build/android/android_change_compile_implementation.js
+++ b/hooks/before_build/android/android_change_compile_implementation.js
@@ -6,46 +6,43 @@ var fs = require('fs');
var path = require('path');
var et = require('elementtree');
-const LOG_NAME = 'Changing compile to implementation ';
+const LOG_NAME = "Changing compile to implementation ";
var changeCompileToImplementation = function (file) {
- if (fs.existsSync(file)) {
- fs.readFile(file, 'utf8', function (err, data) {
- var result = data.replace('compile', 'implementation');
- fs.writeFile(file, result, 'utf8', function (err) {
- if (err) throw new Error(LOG_NAME + 'Unable to write into ' + file + ': ' + err);
- console.log(LOG_NAME + '' + file + ' updated...');
- });
- });
- } else {
- console.error('Could not find file ' + file + ' skipping compile -> implementation change');
- }
-};
+ if (fs.existsSync(file)) {
+ fs.readFile(file, 'utf8', function (err, data) {
+ var result = data.replace("compile", "implementation");
+ fs.writeFile(file, result, 'utf8', function (err) {
+ if (err) throw new Error(LOG_NAME + 'Unable to write into ' + file + ': ' + err);
+ console.log(LOG_NAME + "" + file + " updated...")
+ });
+ });
+ } else {
+ console.error("Could not find file "+file+" skipping compile -> implementation change");
+ }
+}
module.exports = function (context) {
- // If Android platform is not installed, don't even execute
- if (!context.opts.platforms.includes('android')) return;
+ // If Android platform is not installed, don't even execute
+ if (!context.opts.platforms.includes('android')) return;
- var config_xml = path.join(context.opts.projectRoot, 'config.xml');
- var data = fs.readFileSync(config_xml).toString();
- // If no data then no config.xml
- if (data) {
- var etree = et.parse(data);
- console.log(LOG_NAME + 'Retrieving application name...');
- var applicationName = etree._root.attrib.id;
- console.info(LOG_NAME + 'Your application is ' + applicationName);
- const splitParts = applicationName.split('.');
- var lastApplicationPart = splitParts[splitParts.length - 1];
+ var config_xml = path.join(context.opts.projectRoot, 'config.xml');
+ var data = fs.readFileSync(config_xml).toString();
+ // If no data then no config.xml
+ if (data) {
+ var etree = et.parse(data);
+ console.log(LOG_NAME + "Retrieving application name...")
+ var applicationName = etree._root.attrib.id;
+ console.info(LOG_NAME + "Your application is " + applicationName);
+ const splitParts = applicationName.split(".")
+ var lastApplicationPart = splitParts[splitParts.length - 1];
- var platformRoot = path.join(context.opts.projectRoot, 'platforms/android/');
+ var platformRoot = path.join(context.opts.projectRoot, 'platforms/android/')
- console.log(LOG_NAME + 'Updating barcode scanner gradle...');
- var gradleFile = path.join(
- platformRoot,
- 'phonegap-plugin-barcodescanner/' + lastApplicationPart + '-barcodescanner.gradle',
- );
- changeCompileToImplementation(gradleFile);
- } else {
- throw new Error(LOG_NAME + 'Could not retrieve application name.');
- }
-};
+ console.log(LOG_NAME + "Updating barcode scanner gradle...");
+ var gradleFile = path.join(platformRoot, 'phonegap-plugin-barcodescanner/'+lastApplicationPart+'-barcodescanner.gradle');
+ changeCompileToImplementation(gradleFile);
+ } else {
+ throw new Error(LOG_NAME + "Could not retrieve application name.");
+ }
+}
diff --git a/hooks/before_build/android/android_copy_locales.js b/hooks/before_build/android/android_copy_locales.js
index ad5afcb23..27fab1894 100755
--- a/hooks/before_build/android/android_copy_locales.js
+++ b/hooks/before_build/android/android_copy_locales.js
@@ -2,50 +2,50 @@
var fs = require('fs-extra');
var path = require('path');
-const LOG_NAME = 'Copying locales: ';
+const LOG_NAME = "Copying locales: ";
module.exports = function (context) {
- var localesFolder = path.join(context.opts.projectRoot, 'locales/');
-
- // If Android platform is not installed, don't even execute
- if (context.opts.cordova.platforms.indexOf('android') < 0 || !fs.existsSync(localesFolder))
- return;
-
- var languagesFolders = fs.readdirSync(localesFolder);
- // It's not problematic but we will remove them to have cleaner logs.
- var filterItems = ['.git', 'LICENSE', 'README.md'];
- languagesFolders = languagesFolders.filter((item) => !filterItems.includes(item));
- console.log(LOG_NAME + 'Languages found -> ' + languagesFolders);
- languagesFolders.forEach(function (language) {
- console.log(LOG_NAME + 'I found ' + language + ', I will now copy the files.');
- var platformRes = path.join(context.opts.projectRoot, 'platforms/android/app/src/main/res');
- var wwwi18n = path.join(context.opts.projectRoot, 'www/i18n/');
- var languageFolder = localesFolder + '/' + language;
-
- var values = '/values-' + language;
- var valuesFolder = path.join(languageFolder, values);
- if (fs.existsSync(valuesFolder)) {
- console.log(LOG_NAME + 'Copying ' + valuesFolder + ' to ' + platformRes);
-
- var platformValues = platformRes + values;
- if (!fs.existsSync(platformValues)) {
- console.log(LOG_NAME + platformValues + 'does not exist, I will create it.');
- fs.mkdirSync(platformValues, { recursive: true });
- }
-
- fs.copySync(valuesFolder, platformValues);
- console.log(LOG_NAME + valuesFolder + 'copied...');
- } else {
- console.log(LOG_NAME + valuesFolder + ' not found, I will continue.');
- }
-
- var languagei18n = path.join(languageFolder, '/i18n/');
- if (fs.existsSync(languagei18n)) {
- console.log(LOG_NAME + 'Copying ' + languagei18n + ' to ' + wwwi18n);
- fs.copySync(languagei18n, wwwi18n);
- console.log(LOG_NAME + languagei18n + 'copied...');
- } else {
- console.log(LOG_NAME + languagei18n + ' not found, I will continue.');
- }
- });
-};
+ var localesFolder = path.join(context.opts.projectRoot, 'locales/');
+
+ // If Android platform is not installed, don't even execute
+ if (context.opts.cordova.platforms.indexOf('android') < 0 || !fs.existsSync(localesFolder))
+ return;
+
+ var languagesFolders = fs.readdirSync(localesFolder);
+ // It's not problematic but we will remove them to have cleaner logs.
+ var filterItems = ['.git', 'LICENSE', 'README.md']
+ languagesFolders = languagesFolders.filter(item => !filterItems.includes(item));
+ console.log(LOG_NAME + "Languages found -> " + languagesFolders);
+ languagesFolders.forEach(function (language) {
+ console.log(LOG_NAME + 'I found ' + language + ", I will now copy the files.")
+ var platformRes = path.join(context.opts.projectRoot, 'platforms/android/app/src/main/res');
+ var wwwi18n = path.join(context.opts.projectRoot, 'www/i18n/');
+ var languageFolder = localesFolder + "/" + language;
+
+ var values = "/values-" + language;
+ var valuesFolder = path.join(languageFolder, values);
+ if (fs.existsSync(valuesFolder)) {
+ console.log(LOG_NAME + "Copying " + valuesFolder + " to " + platformRes);
+
+ var platformValues = platformRes + values;
+ if (!fs.existsSync(platformValues)) {
+ console.log(LOG_NAME + platformValues + "does not exist, I will create it.");
+ fs.mkdirSync(platformValues, {recursive: true});
+ }
+
+ fs.copySync(valuesFolder, platformValues);
+ console.log(LOG_NAME + valuesFolder + "copied...")
+ } else {
+ console.log(LOG_NAME + valuesFolder + " not found, I will continue.")
+ }
+
+ var languagei18n = path.join(languageFolder, "/i18n/");
+ if (fs.existsSync(languagei18n)) {
+ console.log(LOG_NAME + "Copying " + languagei18n + " to " + wwwi18n);
+ fs.copySync(languagei18n, wwwi18n);
+ console.log(LOG_NAME + languagei18n + "copied...")
+ } else {
+ console.log(LOG_NAME + languagei18n + " not found, I will continue.")
+ }
+ });
+}
diff --git a/hooks/before_build/android/android_set_provider.js b/hooks/before_build/android/android_set_provider.js
index 196def525..3200ab64e 100755
--- a/hooks/before_build/android/android_set_provider.js
+++ b/hooks/before_build/android/android_set_provider.js
@@ -6,105 +6,107 @@ var fs = require('fs');
var path = require('path');
var et = require('elementtree');
-const PROVIDER = 'edu.berkeley.eecs.emission.provider';
-const ACCOUNT_TYPE = 'eecs.berkeley.edu';
-const LOG_NAME = 'Changing Providers: ';
+const PROVIDER = "edu.berkeley.eecs.emission.provider";
+const ACCOUNT_TYPE = "eecs.berkeley.edu";
+const LOG_NAME = "Changing Providers: ";
var changeProvider = function (file, currentName, newName) {
- if (fs.existsSync(file)) {
- fs.readFile(file, 'utf8', function (err, data) {
- if (err) {
- throw new Error(LOG_NAME + 'Unable to find ' + file + ': ' + err);
- }
+ if (fs.existsSync(file)) {
+ fs.readFile(file, 'utf8', function (err, data) {
+ if (err) {
+ throw new Error(LOG_NAME + 'Unable to find ' + file + ': ' + err);
+ }
+
+ var regEx = new RegExp(currentName, 'g');
+
+ var result = data.replace(regEx, newName + '.provider');
+
+ fs.writeFile(file, result, 'utf8', function (err) {
+ if (err) throw new Error(LOG_NAME + 'Unable to write into ' + file + ': ' + err);
+ console.log(LOG_NAME + "" + file + " updated...")
+ });
+ });
+ }
+}
- var regEx = new RegExp(currentName, 'g');
+var changeAccountType = function (file, currentName, newName) {
+ if (fs.existsSync(file)) {
- var result = data.replace(regEx, newName + '.provider');
+ fs.readFile(file, 'utf8', function (err, data) {
+ if (err) {
+ throw new Error(LOG_NAME + 'Unable to find ' + file + ': ' + err);
+ }
- fs.writeFile(file, result, 'utf8', function (err) {
- if (err) throw new Error(LOG_NAME + 'Unable to write into ' + file + ': ' + err);
- console.log(LOG_NAME + '' + file + ' updated...');
- });
- });
- }
-};
+ var regEx = new RegExp(currentName, 'g');
-var changeAccountType = function (file, currentName, newName) {
- if (fs.existsSync(file)) {
- fs.readFile(file, 'utf8', function (err, data) {
- if (err) {
- throw new Error(LOG_NAME + 'Unable to find ' + file + ': ' + err);
- }
+ var result = data.replace(regEx, newName);
- var regEx = new RegExp(currentName, 'g');
+ fs.writeFile(file, result, 'utf8', function (err) {
+ if (err) throw new Error('Unable to write into ' + file + ': ' + err);
+ console.log(LOG_NAME + "" + file + " updated...")
+ });
- var result = data.replace(regEx, newName);
- fs.writeFile(file, result, 'utf8', function (err) {
- if (err) throw new Error('Unable to write into ' + file + ': ' + err);
- console.log(LOG_NAME + '' + file + ' updated...');
- });
- });
- }
-};
+ });
+ }
+}
+
var changeAccountTypeAndProvider = function (file, accountType, providerName, newName) {
- if (fs.existsSync(file)) {
- fs.readFile(file, 'utf8', function (err, data) {
- if (err) {
- throw new Error(LOG_NAME + 'Unable to find ' + file + ': ' + err);
- }
-
- var regEx1 = new RegExp(accountType, 'g');
- var regEx2 = new RegExp(providerName, 'g');
-
- var result = data.replace(regEx1, newName);
- result = result.replace(regEx2, newName + '.provider');
-
- fs.writeFile(file, result, 'utf8', function (err) {
- if (err) throw new Error(LOG_NAME + 'Unable to write into ' + file + ': ' + err);
- console.log(LOG_NAME + '' + file + ' updated...');
- });
- });
- } else {
- console.error(LOG_NAME + 'File ' + file + ' does not exist');
- }
-};
+ if (fs.existsSync(file)) {
+
+ fs.readFile(file, 'utf8', function (err, data) {
+ if (err) {
+ throw new Error(LOG_NAME + 'Unable to find ' + file + ': ' + err);
+ }
+
+ var regEx1 = new RegExp(accountType, 'g');
+ var regEx2 = new RegExp(providerName, 'g');
+
+ var result = data.replace(regEx1, newName);
+ result = result.replace(regEx2, newName + '.provider');
+
+ fs.writeFile(file, result, 'utf8', function (err) {
+ if (err) throw new Error(LOG_NAME + 'Unable to write into ' + file + ': ' + err);
+ console.log(LOG_NAME + "" + file + " updated...")
+ });
+ });
+ } else {
+ console.error(LOG_NAME + "File "+file+" does not exist");
+ }
+}
module.exports = function (context) {
- // If Android platform is not installed, don't even execute
- if (!context.opts.platforms.includes('android')) return;
-
- console.log(LOG_NAME + 'Retrieving application name...');
- var config_xml = path.join(context.opts.projectRoot, 'config.xml');
- var data = fs.readFileSync(config_xml).toString();
- // If no data then no config.xml
- if (data) {
- var etree = et.parse(data);
- var applicationName = etree._root.attrib.id;
- console.log(LOG_NAME + 'Your application is ' + applicationName);
-
- var platformRoot = path.join(context.opts.projectRoot, 'platforms/android/app/src/main');
-
- console.log(LOG_NAME + 'Updating AndroidManifest.xml...');
- var androidManifest = path.join(platformRoot, 'AndroidManifest.xml');
- changeProvider(androidManifest, PROVIDER, applicationName);
-
- console.log(LOG_NAME + 'Updating syncadapter.xml');
- var syncAdapter = path.join(platformRoot, 'res/xml/syncadapter.xml');
- changeAccountTypeAndProvider(syncAdapter, ACCOUNT_TYPE, PROVIDER, applicationName);
-
- console.log(LOG_NAME + 'Updating authenticator.xml');
- var authenticator = path.join(platformRoot, 'res/xml/authenticator.xml');
- changeAccountType(authenticator, ACCOUNT_TYPE, applicationName);
-
- console.log(LOG_NAME + 'Updating ServerSyncPlugin.java');
- var serverSyncPlugin = path.join(
- platformRoot,
- 'java/edu/berkeley/eecs/emission/cordova/serversync/ServerSyncPlugin.java',
- );
- changeAccountTypeAndProvider(serverSyncPlugin, ACCOUNT_TYPE, PROVIDER, applicationName);
- } else {
- throw new Error(LOG_NAME + 'Could not retrieve application name.');
- }
-};
+ // If Android platform is not installed, don't even execute
+ if (!context.opts.platforms.includes('android')) return;
+
+ console.log(LOG_NAME + "Retrieving application name...")
+ var config_xml = path.join(context.opts.projectRoot, 'config.xml');
+ var data = fs.readFileSync(config_xml).toString();
+ // If no data then no config.xml
+ if (data) {
+ var etree = et.parse(data);
+ var applicationName = etree._root.attrib.id;
+ console.log(LOG_NAME + "Your application is " + applicationName);
+
+ var platformRoot = path.join(context.opts.projectRoot, 'platforms/android/app/src/main')
+
+ console.log(LOG_NAME + "Updating AndroidManifest.xml...");
+ var androidManifest = path.join(platformRoot, 'AndroidManifest.xml');
+ changeProvider(androidManifest, PROVIDER, applicationName);
+
+ console.log(LOG_NAME + "Updating syncadapter.xml");
+ var syncAdapter = path.join(platformRoot, 'res/xml/syncadapter.xml');
+ changeAccountTypeAndProvider(syncAdapter, ACCOUNT_TYPE, PROVIDER, applicationName);
+
+ console.log(LOG_NAME + "Updating authenticator.xml");
+ var authenticator = path.join(platformRoot, 'res/xml/authenticator.xml');
+ changeAccountType(authenticator, ACCOUNT_TYPE, applicationName);
+
+ console.log(LOG_NAME + "Updating ServerSyncPlugin.java");
+ var serverSyncPlugin = path.join(platformRoot, 'java/edu/berkeley/eecs/emission/cordova/serversync/ServerSyncPlugin.java');
+ changeAccountTypeAndProvider(serverSyncPlugin, ACCOUNT_TYPE, PROVIDER, applicationName);
+ } else {
+ throw new Error(LOG_NAME + "Could not retrieve application name.");
+ }
+}
diff --git a/hooks/before_prepare/download_translation.js b/hooks/before_prepare/download_translation.js
index 4cefde8cc..d5d6a88f7 100755
--- a/hooks/before_prepare/download_translation.js
+++ b/hooks/before_prepare/download_translation.js
@@ -1,57 +1,46 @@
#!/usr/bin/env node
-'use strict';
+'use strict'
-var child_process = require('child_process');
+var child_process = require('child_process')
var fs = require('fs-extra');
var path = require('path');
-const LOG_NAME = 'Downloading locales: ';
-const CONF_FILE = 'bin/conf/translate_config.json';
+const LOG_NAME = "Downloading locales: ";
+const CONF_FILE = "bin/conf/translate_config.json";
module.exports = function (context) {
- var localesFolder = path.join(context.opts.projectRoot, 'locales/');
- var confFile = path.join(context.opts.projectRoot, CONF_FILE);
+ var localesFolder = path.join(context.opts.projectRoot, 'locales/');
+ var confFile = path.join(context.opts.projectRoot, CONF_FILE);
- // Checking if git is installed, return error if not.
- try {
- child_process.execSync('which git', { stdio: 'inherit' });
- } catch (err) {
- console.error(LOG_NAME + 'git not found, (' + err + ')');
- return;
- }
-
- var url = '';
- if (fs.existsSync(confFile)) {
- console.log(LOG_NAME + confFile + ' found, I will extract translate repo from it.');
- var data = fs.readFileSync(confFile, 'utf8');
- url = JSON.parse(data).url;
- } else {
- console.log(
- LOG_NAME +
- confFile +
- ' not found, I will extract translate repo from translation_config.json.sample.',
- );
- confFile = confFile + '.sample';
+ // Checking if git is installed, return error if not.
+ try {
+ child_process.execSync('which git', {'stdio': 'inherit' });
+ } catch (err) {
+ console.error(LOG_NAME + 'git not found, (' + err + ')');
+ return;
+ }
+
+ var url = "";
if (fs.existsSync(confFile)) {
- var data = fs.readFileSync(confFile, 'utf8');
- url = JSON.parse(data).url;
+ console.log(LOG_NAME + confFile + " found, I will extract translate repo from it.");
+ var data = fs.readFileSync(confFile, 'utf8');
+ url = JSON.parse(data).url;
} else {
- console.log(
- LOG_NAME +
- confFile +
- ' not found, you can find a sample at bin/conf in the e-mission-phone repo.',
- );
- return;
- }
- }
+ console.log(LOG_NAME + confFile + " not found, I will extract translate repo from translation_config.json.sample.");
+ confFile = confFile + ".sample";
+ if (fs.existsSync(confFile)) {
+ var data = fs.readFileSync(confFile, 'utf8');
+ url = JSON.parse(data).url;
+ } else {
+ console.log(LOG_NAME + confFile + " not found, you can find a sample at bin/conf in the e-mission-phone repo.");
+ return;
+ }
+ }
- if (!fs.existsSync(localesFolder)) {
- console.log(LOG_NAME + 'I will clone from ' + url);
- child_process.execSync('git clone ' + url + ' ' + localesFolder, {
- timeout: 10000,
- stdio: 'inherit',
- });
- } else {
- child_process.execSync('git pull', { cwd: localesFolder, timeout: 10000, stdio: 'inherit' });
- }
-};
+ if (!fs.existsSync(localesFolder)) {
+ console.log(LOG_NAME + "I will clone from " + url);
+ child_process.execSync('git clone ' + url + ' ' + localesFolder, { 'timeout': 10000, 'stdio': 'inherit'});
+ } else {
+ child_process.execSync('git pull', { 'cwd': localesFolder, 'timeout': 10000, 'stdio': 'inherit' });
+ }
+}
diff --git a/hooks/before_prepare/ios_use_apns_token.js b/hooks/before_prepare/ios_use_apns_token.js
index 36be89ce8..0c1b808f5 100755
--- a/hooks/before_prepare/ios_use_apns_token.js
+++ b/hooks/before_prepare/ios_use_apns_token.js
@@ -1,22 +1,22 @@
#!/usr/bin/env node
-'use strict';
+'use strict'
var fs = require('fs-extra');
-const LOG_NAME = 'Setting iOS push: FCM = false, APNS = true';
-const CONF_FILE = 'GoogleServicesInfo.plist';
+const LOG_NAME = "Setting iOS push: FCM = false, APNS = true";
+const CONF_FILE = "GoogleServicesInfo.plist";
module.exports = function (context) {
- const FCM_TOKEN_SETTING = new RegEx('IS_GCM_ENABLED(\n\\s*)', 'g');
- if (!ctx.opts.platforms.includes('ios')) return;
- if (fs.existsSync(confFile)) {
- console.log(LOG_NAME + confFile + ' found, modifying it');
- var regEx = new RegExp(currentName, 'g');
+ const FCM_TOKEN_SETTING = new RegEx("IS_GCM_ENABLED(\n\\s*)", "g");
+ if (!ctx.opts.platforms.includes('ios')) return;
+ if (fs.existsSync(confFile)) {
+ console.log(LOG_NAME + confFile + " found, modifying it");
+ var regEx = new RegExp(currentName, 'g');
- var data = fs.readFileSync(confFile, 'utf8');
- var replacedData = data.replace(regEx, 'IS_GCM_ENABLED$1');
- fs.writeFileSync(CONF_FILE, replacedData, 'utf8');
- console.log(LOG_NAME + confFile + ' modified file written');
- }
-};
+ var data = fs.readFileSync(confFile, 'utf8');
+ var replacedData = data.replace(regEx, "IS_GCM_ENABLED$1");
+ fs.writeFileSync(CONF_FILE, replacedData, 'utf8');
+ console.log(LOG_NAME + confFile + " modified file written");
+ }
+}
diff --git a/jest.config.json b/jest.config.json
index 725f3c51f..78dc839b4 100644
--- a/jest.config.json
+++ b/jest.config.json
@@ -1,5 +1,11 @@
{
- "testPathIgnorePatterns": ["/node_modules/", "/platforms/", "/plugins/", "/lib/", "/manual_lib/"],
+ "testPathIgnorePatterns": [
+ "/node_modules/",
+ "/platforms/",
+ "/plugins/",
+ "/lib/",
+ "/manual_lib/"
+ ],
"transform": {
"^.+\\.(ts|tsx|js|jsx)$": "ts-jest"
},
diff --git a/package.cordovabuild.json b/package.cordovabuild.json
index 0b0763567..943f06520 100644
--- a/package.cordovabuild.json
+++ b/package.cordovabuild.json
@@ -49,7 +49,10 @@
"webpack-cli": "^5.0.1"
},
"cordova": {
- "platforms": ["android", "ios"],
+ "platforms": [
+ "android",
+ "ios"
+ ],
"plugins": {
"@havesource/cordova-plugin-push": {
"ANDROIDX_CORE_VERSION": "1.6.+",
diff --git a/package.serve.json b/package.serve.json
index 334d21e6d..2bba5509f 100644
--- a/package.serve.json
+++ b/package.serve.json
@@ -99,6 +99,8 @@
"shelljs": "^0.8.5"
},
"cordova": {
- "platforms": ["browser"]
+ "platforms": [
+ "browser"
+ ]
}
}
diff --git a/tsconfig.json b/tsconfig.json
index 28ea586ca..29384751e 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -12,5 +12,5 @@
"moduleResolution": "node"
},
"include": ["www/**/*"],
- "exclude": ["**/www/manual_lib/*", "**/node_modules/*", "**/dist/*"]
+ "exclude": ["**/www/manual_lib/*", "**/node_modules/*", "**/dist/*"],
}
diff --git a/webpack.config.js b/webpack.config.js
index 55e631b28..d6e36fb18 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -1,5 +1,5 @@
-const path = require('path');
-const webpack = require('webpack');
+const path = require('path')
+const webpack = require('webpack')
module.exports = {
entry: './www/index.js',
@@ -12,31 +12,25 @@ module.exports = {
// to load CSS and SCSS (enketo-core only supplies SCSS)
{
test: /\.(scss|css)$/,
- include: [
- path.resolve(__dirname, 'www/css'),
- path.resolve(__dirname, 'www/manual_lib'),
- path.resolve(__dirname, 'node_modules/enketo-core'),
- path.resolve(__dirname, 'node_modules/leaflet'),
- ],
+ include: [path.resolve(__dirname, 'www/css'),
+ path.resolve(__dirname, 'www/manual_lib'),
+ path.resolve(__dirname, 'node_modules/enketo-core'),
+ path.resolve(__dirname, 'node_modules/leaflet')],
use: ['style-loader', 'css-loader', 'sass-loader'],
},
// to resolve url() in CSS
{
test: /\.(png|jpg)$/,
- include: [
- path.resolve(__dirname, 'www/css'),
- path.resolve(__dirname, 'node_modules/react-native-paper'),
- path.resolve(__dirname, 'node_modules/@react-navigation/elements'),
- ],
+ include: [path.resolve(__dirname, 'www/css'),
+ path.resolve(__dirname, 'node_modules/react-native-paper'),
+ path.resolve(__dirname, 'node_modules/@react-navigation/elements')],
use: 'url-loader',
},
// necessary for react-native-web to bundle JSX
{
test: /\.(js|jsx|ts|tsx)$/,
- include: [
- path.resolve(__dirname, 'www'),
- path.resolve(__dirname, 'node_modules/react-native-vector-icons'),
- ],
+ include: [path.resolve(__dirname, 'www'),
+ path.resolve(__dirname, 'node_modules/react-native-vector-icons')],
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env', '@babel/preset-react', '@babel/preset-typescript'],
@@ -55,10 +49,8 @@ module.exports = {
// necessary for react-native-paper to load images, fonts, and vector graphics
{
test: /\.(jpg|png|woff|woff2|eot|ttf|svg)$/,
- include: [
- path.resolve(__dirname, 'www'),
- path.resolve(__dirname, 'node_modules/react-native-vector-icons'),
- ],
+ include: [path.resolve(__dirname, 'www'),
+ path.resolve(__dirname, 'node_modules/react-native-vector-icons')],
type: 'asset/resource',
},
],
@@ -86,8 +78,8 @@ module.exports = {
/* Enketo expects its per-app configuration to be available as 'enketo-config',
so we have to alias it here.
https://github.com/enketo/enketo-core#global-configuration */
- 'enketo/config': path.resolve(__dirname, 'www/js/config/enketo-config'),
+ 'enketo/config': path.resolve(__dirname, 'www/js/config/enketo-config')
},
extensions: ['.web.js', '.jsx', '.tsx', '.ts', '.js'],
},
-};
+}
diff --git a/webpack.prod.js b/webpack.prod.js
index 4e61033e4..c08fc140c 100644
--- a/webpack.prod.js
+++ b/webpack.prod.js
@@ -1,4 +1,4 @@
-const path = require('path');
+const path = require('path')
const common = require('./webpack.config.js');
const { merge } = require('webpack-merge');
@@ -21,7 +21,7 @@ module.exports = merge(common, {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env'],
- plugins: ['angularjs-annotate'],
+ plugins: ["angularjs-annotate"],
},
},
{
diff --git a/www/__tests__/diaryHelper.test.ts b/www/__tests__/diaryHelper.test.ts
index 1ac143334..822b19bba 100644
--- a/www/__tests__/diaryHelper.test.ts
+++ b/www/__tests__/diaryHelper.test.ts
@@ -1,86 +1,63 @@
-import {
- getFormattedDate,
- isMultiDay,
- getFormattedDateAbbr,
- getFormattedTimeRange,
- getDetectedModes,
- getBaseModeByKey,
- modeColors,
-} from '../js/diary/diaryHelper';
+import { getFormattedDate, isMultiDay, getFormattedDateAbbr, getFormattedTimeRange, getDetectedModes, getBaseModeByKey, modeColors } from "../js/diary/diaryHelper";
it('returns a formatted date', () => {
- expect(getFormattedDate('2023-09-18T00:00:00-07:00')).toBe('Mon September 18, 2023');
- expect(getFormattedDate('')).toBeUndefined();
- expect(getFormattedDate('2023-09-18T00:00:00-07:00', '2023-09-21T00:00:00-07:00')).toBe(
- 'Mon September 18, 2023 - Thu September 21, 2023',
- );
+ expect(getFormattedDate("2023-09-18T00:00:00-07:00")).toBe("Mon September 18, 2023");
+ expect(getFormattedDate("")).toBeUndefined();
+ expect(getFormattedDate("2023-09-18T00:00:00-07:00", "2023-09-21T00:00:00-07:00")).toBe("Mon September 18, 2023 - Thu September 21, 2023");
});
it('returns an abbreviated formatted date', () => {
- expect(getFormattedDateAbbr('2023-09-18T00:00:00-07:00')).toBe('Mon, Sep 18');
- expect(getFormattedDateAbbr('')).toBeUndefined();
- expect(getFormattedDateAbbr('2023-09-18T00:00:00-07:00', '2023-09-21T00:00:00-07:00')).toBe(
- 'Mon, Sep 18 - Thu, Sep 21',
- );
+ expect(getFormattedDateAbbr("2023-09-18T00:00:00-07:00")).toBe("Mon, Sep 18");
+ expect(getFormattedDateAbbr("")).toBeUndefined();
+ expect(getFormattedDateAbbr("2023-09-18T00:00:00-07:00", "2023-09-21T00:00:00-07:00")).toBe("Mon, Sep 18 - Thu, Sep 21");
});
it('returns a human readable time range', () => {
- expect(getFormattedTimeRange('2023-09-18T00:00:00-07:00', '2023-09-18T00:00:00-09:20')).toBe(
- '2 hours',
- );
- expect(getFormattedTimeRange('2023-09-18T00:00:00-07:00', '2023-09-18T00:00:00-09:30')).toBe(
- '3 hours',
- );
- expect(getFormattedTimeRange('', '2023-09-18T00:00:00-09:30')).toBeFalsy();
+ expect(getFormattedTimeRange("2023-09-18T00:00:00-07:00", "2023-09-18T00:00:00-09:20")).toBe("2 hours");
+ expect(getFormattedTimeRange("2023-09-18T00:00:00-07:00", "2023-09-18T00:00:00-09:30")).toBe("3 hours");
+ expect(getFormattedTimeRange("", "2023-09-18T00:00:00-09:30")).toBeFalsy();
});
-it('returns a Base Mode for a given key', () => {
- expect(getBaseModeByKey('WALKING')).toEqual({
- name: 'WALKING',
- icon: 'walk',
- color: modeColors.blue,
- });
- expect(getBaseModeByKey('MotionTypes.WALKING')).toEqual({
- name: 'WALKING',
- icon: 'walk',
- color: modeColors.blue,
- });
- expect(getBaseModeByKey('I made this type up')).toEqual({
- name: 'UNKNOWN',
- icon: 'help',
- color: modeColors.grey,
- });
+it("returns a Base Mode for a given key", () => {
+ expect(getBaseModeByKey("WALKING")).toEqual({ name: "WALKING", icon: "walk", color: modeColors.blue });
+ expect(getBaseModeByKey("MotionTypes.WALKING")).toEqual({ name: "WALKING", icon: "walk", color: modeColors.blue });
+ expect(getBaseModeByKey("I made this type up")).toEqual({ name: "UNKNOWN", icon: "help", color: modeColors.grey });
});
it('returns true/false is multi day', () => {
- expect(isMultiDay('2023-09-18T00:00:00-07:00', '2023-09-19T00:00:00-07:00')).toBeTruthy();
- expect(isMultiDay('2023-09-18T00:00:00-07:00', '2023-09-18T00:00:00-09:00')).toBeFalsy();
- expect(isMultiDay('', '2023-09-18T00:00:00-09:00')).toBeFalsy();
+ expect(isMultiDay("2023-09-18T00:00:00-07:00", "2023-09-19T00:00:00-07:00")).toBeTruthy();
+ expect(isMultiDay("2023-09-18T00:00:00-07:00", "2023-09-18T00:00:00-09:00")).toBeFalsy();
+ expect(isMultiDay("", "2023-09-18T00:00:00-09:00")).toBeFalsy();
});
//created a fake trip with relevant sections by examining log statements
-let myFakeTrip = {
- sections: [
- { sensed_mode_str: 'BICYCLING', distance: 6013.73657416706 },
- { sensed_mode_str: 'WALKING', distance: 715.3078629361006 },
- ],
-};
-let myFakeTrip2 = {
- sections: [
- { sensed_mode_str: 'BICYCLING', distance: 6013.73657416706 },
- { sensed_mode_str: 'BICYCLING', distance: 715.3078629361006 },
- ],
-};
+let myFakeTrip = {sections: [
+ { "sensed_mode_str": "BICYCLING", "distance": 6013.73657416706 },
+ { "sensed_mode_str": "WALKING", "distance": 715.3078629361006 }
+]};
+let myFakeTrip2 = {sections: [
+ { "sensed_mode_str": "BICYCLING", "distance": 6013.73657416706 },
+ { "sensed_mode_str": "BICYCLING", "distance": 715.3078629361006 }
+]};
let myFakeDetectedModes = [
- { mode: 'BICYCLING', icon: 'bike', color: modeColors.green, pct: 89 },
- { mode: 'WALKING', icon: 'walk', color: modeColors.blue, pct: 11 },
-];
+ { mode: "BICYCLING",
+ icon: "bike",
+ color: modeColors.green,
+ pct: 89 },
+ { mode: "WALKING",
+ icon: "walk",
+ color: modeColors.blue,
+ pct: 11 }];
-let myFakeDetectedModes2 = [{ mode: 'BICYCLING', icon: 'bike', color: modeColors.green, pct: 100 }];
+let myFakeDetectedModes2 = [
+ { mode: "BICYCLING",
+ icon: "bike",
+ color: modeColors.green,
+ pct: 100 }];
it('returns the detected modes, with percentages, for a trip', () => {
expect(getDetectedModes(myFakeTrip)).toEqual(myFakeDetectedModes);
expect(getDetectedModes(myFakeTrip2)).toEqual(myFakeDetectedModes2);
expect(getDetectedModes({})).toEqual([]); // empty trip, no sections, no modes
-});
+})
diff --git a/www/i18n/en.json b/www/i18n/en.json
index 2ee46f8ca..fe0df617a 100644
--- a/www/i18n/en.json
+++ b/www/i18n/en.json
@@ -1,429 +1,429 @@
{
- "loading": "Loading...",
- "pull-to-refresh": "Pull to refresh",
+ "loading" : "Loading...",
+ "pull-to-refresh": "Pull to refresh",
- "weekdays-all": "All",
- "weekdays-select": "Select day of the week",
+ "weekdays-all": "All",
+ "weekdays-select": "Select day of the week",
- "trip-confirm": {
- "services-please-fill-in": "Please fill in the {{text}} not listed.",
- "services-cancel": "Cancel",
- "services-save": "Save"
- },
-
- "control": {
- "profile": "Profile",
- "edit-demographics": "Edit Demographics",
- "tracking": "Tracking",
- "app-status": "App Status",
- "incorrect-app-status": "Please update permissions",
- "fix-app-status": "Click to view and fix app status",
- "fix": "Fix",
- "medium-accuracy": "Medium accuracy",
- "force-sync": "Force sync",
- "share": "Share",
- "download-json-dump": "Download json dump",
- "email-log": "Email log",
- "upload-log": "Upload log",
- "view-privacy": "View Privacy Policy",
- "user-data": "User data",
- "erase-data": "Erase data",
- "dev-zone": "Developer zone",
- "refresh": "Refresh",
- "end-trip-sync": "End trip + sync",
- "check-consent": "Check consent",
- "invalidate-cached-docs": "Invalidate cached docs",
- "nuke-all": "Nuke all buffers and cache",
- "test-notification": "Test local notification",
- "check-log": "Check log",
- "log-title": "Log",
- "check-sensed-data": "Check sensed data",
- "sensed-title": "Sensed Data: Transitions",
- "collection": "Collection",
- "sync": "Sync",
- "button-accept": "I accept",
- "view-qrc": "My OPcode",
- "app-version": "App Version",
- "reminders-time-of-day": "Time of Day for Reminders ({{time}})",
- "upcoming-notifications": "Upcoming Notifications",
- "dummy-notification": "Dummy Notification in 5 Seconds",
- "log-out": "Log Out"
- },
+ "trip-confirm": {
+ "services-please-fill-in": "Please fill in the {{text}} not listed.",
+ "services-cancel": "Cancel",
+ "services-save": "Save"
+ },
- "general-settings": {
- "choose-date": "Choose date to download data",
- "choose-dataset": "Choose a dataset for carbon footprint calculations",
- "carbon-dataset": "Carbon dataset",
- "nuke-ui-state-only": "UI state only",
- "nuke-native-cache-only": "Native cache only",
- "nuke-everything": "Everything",
- "clear-data": "Clear data",
- "are-you-sure": "Are you sure?",
- "log-out-warning": "You will be logged out and your credentials will not be saved. Unsynced data may be lost.",
- "cancel": "Cancel",
- "confirm": "Confirm",
- "user-data-erased": "User data erased.",
- "consent-not-found": "Consent for data collection not found, consent now?",
- "no-consent-message": "OK! Note that you won't get any personalized stats until you do!",
- "consent-found": "Consent found!",
- "consented-to": "Consented to protocol {{protocol_id}}, {{approval_date}}",
- "consented-ok": "OK",
- "qrcode": "My OPcode",
- "qrcode-share-title": "You can save your OPcode to login easily in the future!"
- },
+ "control":{
+ "profile": "Profile",
+ "edit-demographics": "Edit Demographics",
+ "tracking": "Tracking",
+ "app-status": "App Status",
+ "incorrect-app-status": "Please update permissions",
+ "fix-app-status": "Click to view and fix app status",
+ "fix": "Fix",
+ "medium-accuracy": "Medium accuracy",
+ "force-sync": "Force sync",
+ "share": "Share",
+ "download-json-dump": "Download json dump",
+ "email-log": "Email log",
+ "upload-log": "Upload log",
+ "view-privacy": "View Privacy Policy",
+ "user-data": "User data",
+ "erase-data": "Erase data",
+ "dev-zone": "Developer zone",
+ "refresh": "Refresh",
+ "end-trip-sync": "End trip + sync",
+ "check-consent": "Check consent",
+ "invalidate-cached-docs": "Invalidate cached docs",
+ "nuke-all": "Nuke all buffers and cache",
+ "test-notification": "Test local notification",
+ "check-log": "Check log",
+ "log-title" : "Log",
+ "check-sensed-data": "Check sensed data",
+ "sensed-title": "Sensed Data: Transitions",
+ "collection": "Collection",
+ "sync": "Sync",
+ "button-accept": "I accept",
+ "view-qrc": "My OPcode",
+ "app-version": "App Version",
+ "reminders-time-of-day": "Time of Day for Reminders ({{time}})",
+ "upcoming-notifications": "Upcoming Notifications",
+ "dummy-notification" : "Dummy Notification in 5 Seconds",
+ "log-out": "Log Out"
+ },
- "metrics": {
- "cancel": "Cancel",
- "confirm": "Confirm",
- "get": "Get",
- "range": "Range",
- "filter": "Filter",
- "from": "From:",
- "to": "To:",
- "last-week": "last week",
- "frequency": "Frequency:",
- "pandafreqoptions-daily": "DAILY",
- "pandafreqoptions-weekly": "WEEKLY",
- "pandafreqoptions-biweekly": "BIWEEKLY",
- "pandafreqoptions-monthly": "MONTHLY",
- "pandafreqoptions-yearly": "YEARLY",
- "freqoptions-daily": "DAILY",
- "freqoptions-monthly": "MONTHLY",
- "freqoptions-yearly": "YEARLY",
- "select-pandafrequency": "Select summary freqency",
- "select-frequency": "Select summary freqency",
- "chart-xaxis-date": "Date",
- "chart-no-data": "No Data Available",
- "trips-yaxis-number": "Number",
- "calorie-data-change": " change",
- "calorie-data-unknown": "Unknown...",
- "greater-than": " greater than ",
- "greater": " greater ",
- "or": "or",
- "less-than": " less than ",
- "less": " less ",
- "week-before": "vs. week before",
- "this-week": "this week",
- "pick-a-date": "Pick a date",
- "trips": "trips",
- "hours": "hours",
- "minutes": "minutes",
- "custom": "Custom"
- },
+ "general-settings":{
+ "choose-date" : "Choose date to download data",
+ "choose-dataset" : "Choose a dataset for carbon footprint calculations",
+ "carbon-dataset" : "Carbon dataset",
+ "nuke-ui-state-only" : "UI state only",
+ "nuke-native-cache-only" : "Native cache only",
+ "nuke-everything" : "Everything",
+ "clear-data": "Clear data",
+ "are-you-sure": "Are you sure?",
+ "log-out-warning": "You will be logged out and your credentials will not be saved. Unsynced data may be lost.",
+ "cancel": "Cancel",
+ "confirm": "Confirm",
+ "user-data-erased": "User data erased.",
+ "consent-not-found": "Consent for data collection not found, consent now?",
+ "no-consent-message": "OK! Note that you won't get any personalized stats until you do!",
+ "consent-found": "Consent found!",
+ "consented-to": "Consented to protocol {{protocol_id}}, {{approval_date}}",
+ "consented-ok": "OK",
+ "qrcode": "My OPcode",
+ "qrcode-share-title": "You can save your OPcode to login easily in the future!"
+ },
- "diary": {
- "distance-in-time": "{{distance}} {{distsuffix}} in {{time}}",
- "distance": "Distance",
- "time": "Time",
- "mode": "Mode",
- "replaces": "Replaces",
- "purpose": "Purpose",
- "survey": "Details",
- "untracked-time-range": "Untracked: {{start}} - {{end}}",
- "unlabeled": "All Unlabeled",
- "invalid-ebike": "Invalid",
- "to-label": "To Label",
- "show-all": "All Trips",
- "no-trips-found": "No trips found",
- "choose-mode": "Mode 📝 ",
- "choose-replaced-mode": "Replaces 📝",
- "choose-purpose": "Purpose 📝",
- "choose-survey": "Add Trip Details 📝 ",
- "select-mode-scroll": "Mode (👇 for more)",
- "select-replaced-mode-scroll": "Replaces (👇 for more)",
- "select-purpose-scroll": "Purpose (👇 for more)",
- "delete-entry-confirm": "Are you sure you wish to delete this entry?",
- "detected": "Detected:",
- "labeled-mode": "Labeled Mode",
- "detected-modes": "Detected Modes",
- "today": "Today",
- "no-more-travel": "No more travel to show",
- "show-more-travel": "Show More Travel",
- "show-older-travel": "Show Older Travel",
- "no-travel": "No travel to show",
- "no-travel-hint": "To see more, change the filters above or go record some travel!"
- },
+ "metrics":{
+ "cancel": "Cancel",
+ "confirm": "Confirm",
+ "get": "Get",
+ "range": "Range",
+ "filter": "Filter",
+ "from": "From:",
+ "to": "To:",
+ "last-week": "last week",
+ "frequency": "Frequency:",
+ "pandafreqoptions-daily": "DAILY",
+ "pandafreqoptions-weekly": "WEEKLY",
+ "pandafreqoptions-biweekly": "BIWEEKLY",
+ "pandafreqoptions-monthly": "MONTHLY",
+ "pandafreqoptions-yearly": "YEARLY",
+ "freqoptions-daily": "DAILY",
+ "freqoptions-monthly": "MONTHLY",
+ "freqoptions-yearly": "YEARLY",
+ "select-pandafrequency": "Select summary freqency",
+ "select-frequency": "Select summary freqency",
+ "chart-xaxis-date": "Date",
+ "chart-no-data": "No Data Available",
+ "trips-yaxis-number": "Number",
+ "calorie-data-change": " change",
+ "calorie-data-unknown": "Unknown...",
+ "greater-than": " greater than ",
+ "greater": " greater ",
+ "or": "or",
+ "less-than": " less than ",
+ "less": " less ",
+ "week-before": "vs. week before",
+ "this-week": "this week",
+ "pick-a-date": "Pick a date",
+ "trips": "trips",
+ "hours": "hours",
+ "minutes": "minutes",
+ "custom": "Custom"
+ },
+
+ "diary": {
+ "distance-in-time": "{{distance}} {{distsuffix}} in {{time}}",
+ "distance": "Distance",
+ "time": "Time",
+ "mode": "Mode",
+ "replaces": "Replaces",
+ "purpose": "Purpose",
+ "survey": "Details",
+ "untracked-time-range": "Untracked: {{start}} - {{end}}",
+ "unlabeled": "All Unlabeled",
+ "invalid-ebike": "Invalid",
+ "to-label": "To Label",
+ "show-all": "All Trips",
+ "no-trips-found": "No trips found",
+ "choose-mode": "Mode 📝 ",
+ "choose-replaced-mode": "Replaces 📝",
+ "choose-purpose": "Purpose 📝",
+ "choose-survey": "Add Trip Details 📝 ",
+ "select-mode-scroll": "Mode (👇 for more)",
+ "select-replaced-mode-scroll": "Replaces (👇 for more)",
+ "select-purpose-scroll": "Purpose (👇 for more)",
+ "delete-entry-confirm": "Are you sure you wish to delete this entry?",
+ "detected": "Detected:",
+ "labeled-mode": "Labeled Mode",
+ "detected-modes": "Detected Modes",
+ "today": "Today",
+ "no-more-travel": "No more travel to show",
+ "show-more-travel": "Show More Travel",
+ "show-older-travel": "Show Older Travel",
+ "no-travel": "No travel to show",
+ "no-travel-hint": "To see more, change the filters above or go record some travel!"
+ },
- "main-metrics": {
- "dashboard": "Dashboard",
- "summary": "My Summary",
- "chart": "Chart",
- "change-data": "Change dates:",
- "distance": "Distance",
- "trips": "Trips",
- "duration": "Duration",
- "fav-mode": "My Favorite Mode",
- "speed": "My Speed",
- "footprint": "My Footprint",
- "estimated-emissions": "Estimated CO₂ emissions",
- "how-it-compares": "Ballpark comparisons",
- "optimal": "Optimal (perfect mode choice for all my trips)",
- "average": "Group Avg.",
- "worst-case": "Worse Case",
- "label-to-squish": "Label trips to collapse the range into a single number",
- "range-uncertain-footnote": "²Due to the uncertainty of unlabeled trips, estimates may fall anywhere within the shown range. Label more trips for richer estimates.",
- "lastweek": "My last week value:",
- "us-2030-goal": "2030 Guideline¹",
- "us-2050-goal": "2050 Guideline¹",
- "us-goals-footnote": "¹Guidelines based on US decarbonization goals, scaled to per-capita travel-related emissions.",
- "past-week": "Past Week",
- "prev-week": "Prev. Week",
- "no-summary-data": "No summary data",
- "mean-speed": "My Average Speed",
- "user-totals": "My Totals",
- "group-totals": "Group Totals",
- "active-minutes": "Active Minutes",
- "weekly-active-minutes": "Weekly minutes of active travel",
- "daily-active-minutes": "Daily minutes of active travel",
- "active-minutes-table": "Table of active minutes metrics",
- "weekly-goal": "Weekly Goal³",
- "weekly-goal-footnote": "³Weekly goal based on CDC recommendation of 150 minutes of moderate activity per week.",
- "labeled": "Labeled",
- "unlabeled": "Unlabeled²",
- "footprint-label": "Footprint (kg CO₂)"
- },
+ "main-metrics":{
+ "dashboard": "Dashboard",
+ "summary": "My Summary",
+ "chart": "Chart",
+ "change-data": "Change dates:",
+ "distance": "Distance",
+ "trips": "Trips",
+ "duration": "Duration",
+ "fav-mode": "My Favorite Mode",
+ "speed": "My Speed",
+ "footprint": "My Footprint",
+ "estimated-emissions": "Estimated CO₂ emissions",
+ "how-it-compares": "Ballpark comparisons",
+ "optimal": "Optimal (perfect mode choice for all my trips)",
+ "average": "Group Avg.",
+ "worst-case": "Worse Case",
+ "label-to-squish": "Label trips to collapse the range into a single number",
+ "range-uncertain-footnote": "²Due to the uncertainty of unlabeled trips, estimates may fall anywhere within the shown range. Label more trips for richer estimates.",
+ "lastweek": "My last week value:",
+ "us-2030-goal": "2030 Guideline¹",
+ "us-2050-goal": "2050 Guideline¹",
+ "us-goals-footnote": "¹Guidelines based on US decarbonization goals, scaled to per-capita travel-related emissions.",
+ "past-week" : "Past Week",
+ "prev-week" : "Prev. Week",
+ "no-summary-data": "No summary data",
+ "mean-speed": "My Average Speed",
+ "user-totals": "My Totals",
+ "group-totals": "Group Totals",
+ "active-minutes": "Active Minutes",
+ "weekly-active-minutes": "Weekly minutes of active travel",
+ "daily-active-minutes": "Daily minutes of active travel",
+ "active-minutes-table": "Table of active minutes metrics",
+ "weekly-goal": "Weekly Goal³",
+ "weekly-goal-footnote": "³Weekly goal based on CDC recommendation of 150 minutes of moderate activity per week.",
+ "labeled": "Labeled",
+ "unlabeled": "Unlabeled²",
+ "footprint-label": "Footprint (kg CO₂)"
+ },
- "main-inf-scroll": {
- "tab": "Label"
- },
+ "main-inf-scroll" : {
+ "tab": "Label"
+ },
- "details": {
- "speed": "Speed",
- "time": "Time"
- },
+ "details":{
+ "speed": "Speed",
+ "time": "Time"
+ },
- "list-datepicker-today": "Today",
- "list-datepicker-close": "Close",
- "list-datepicker-set": "Set",
+ "list-datepicker-today": "Today",
+ "list-datepicker-close": "Close",
+ "list-datepicker-set": "Set",
- "service": {
- "reading-server": "Reading from server...",
- "reading-unprocessed-data": "Reading unprocessed data..."
- },
+ "service":{
+ "reading-server": "Reading from server...",
+ "reading-unprocessed-data": "Reading unprocessed data..."
+ },
- "email-service": {
- "email-account-not-configured": "Email account is not configured, cannot send email",
- "email-account-mail-app": "You must have the mail app on your phone configured with an email address. Otherwise, this won't work",
- "going-to-email": "Going to email database from {{parentDir}}",
- "email-log": {
- "subject-logs": "emission logs",
- "body-please-fill-in-what-is-wrong": "please fill in what is wrong"
+ "email-service":{
+ "email-account-not-configured": "Email account is not configured, cannot send email",
+ "email-account-mail-app": "You must have the mail app on your phone configured with an email address. Otherwise, this won't work",
+ "going-to-email": "Going to email database from {{parentDir}}",
+ "email-log":{
+ "subject-logs": "emission logs",
+ "body-please-fill-in-what-is-wrong": "please fill in what is wrong"
+ },
+ "no-email-address-configured": "No email address configured.",
+ "email-data":{
+ "subject-data-dump-from-to": "Data dump from {{start}} to {{end}}",
+ "body-data-consists-of-list-of-entries": "Data consists of a list of entries.\nEntry formats are at https://github.com/e-mission/e-mission-server/tree/master/emission/core/wrapper \nData can be loaded locally using instructions at https://github.com/e-mission/e-mission-server#loading-test-data \n and can be manipulated using the example at https://github.com/e-mission/e-mission-server/blob/master/Timeseries_Sample.ipynb"
+ }
},
- "no-email-address-configured": "No email address configured.",
- "email-data": {
- "subject-data-dump-from-to": "Data dump from {{start}} to {{end}}",
- "body-data-consists-of-list-of-entries": "Data consists of a list of entries.\nEntry formats are at https://github.com/e-mission/e-mission-server/tree/master/emission/core/wrapper \nData can be loaded locally using instructions at https://github.com/e-mission/e-mission-server#loading-test-data \n and can be manipulated using the example at https://github.com/e-mission/e-mission-server/blob/master/Timeseries_Sample.ipynb"
- }
- },
- "upload-service": {
- "upload-database": "Uploading database {{db}}",
- "upload-from-dir": "from directory {{parentDir}}",
- "upload-to-server": "to servers {{serverURL}}",
- "please-fill-in-what-is-wrong": "please fill in what is wrong",
- "upload-success": "Upload successful",
- "upload-progress": "Sending {{filesizemb | number}} MB to {{serverURL}}",
- "upload-details": "Sent {{filesizemb | number}} MB to {{serverURL}}"
- },
+ "upload-service":{
+ "upload-database": "Uploading database {{db}}",
+ "upload-from-dir": "from directory {{parentDir}}",
+ "upload-to-server": "to servers {{serverURL}}",
+ "please-fill-in-what-is-wrong": "please fill in what is wrong",
+ "upload-success": "Upload successful",
+ "upload-progress": "Sending {{filesizemb | number}} MB to {{serverURL}}",
+ "upload-details": "Sent {{filesizemb | number}} MB to {{serverURL}}"
+ },
- "intro": {
- "appstatus": {
- "fix": "Fix",
- "refresh": "Refresh",
- "overall-description": "This app works in the background to automatically build a travel diary for you. Make sure that all the settings below are green so that the app can work properly!",
- "explanation-title": "What are these used for?",
- "overall-loc-name": "Location",
- "overall-loc-description": "We use the background location permission to track your location in the background, even when the app is closed. Reading background locations removes the need to turn tracking on and off, making the app easier to use and preventing battery drain.",
- "locsettings": {
- "name": "Location Settings",
- "description": {
- "android-lt-9": "Location services should be enabled and set to High Accuracy. This allows us to accurately record the trajectory of the travel",
- "android-gte-9": "Location services should be enabled. This allows us to access location data and generate the trip log",
- "ios": "Location services should be enabled. This allows us to access location data and generate the trip log"
- }
- },
- "locperms": {
- "name": "Location Permissions",
- "description": {
- "android-lt-6": "Enabled during app installation.",
- "android-6-9": "Please select 'allow'",
- "android-10": "Please select 'Allow all the time'",
- "android-11": "On the app settings page, choose the 'Location' permission and set it to 'Allow all the time'",
- "android-gte-12": "On the app settings page, choose the 'Location' permission and set it to 'Allow all the time' and 'Precise'",
- "ios-lt-13": "Please select 'Always allow'",
- "ios-gte-13": "On the app settings page, please select 'Always' and 'Precise' and return here to continue"
- }
- },
- "overall-fitness-name-android": "Physical activity",
- "overall-fitness-name-ios": "Motion and Fitness",
- "overall-fitness-description": "The fitness sensors distinguish between walking, bicycling and motorized modes. We use this data in order to separate the parts of multi-modal travel such as transit. We also use it to as a cross-check potentially spurious trips - if the location sensor jumps across town but the fitness sensor is stationary, we can guess that the trip was invalid.",
- "fitnessperms": {
- "name": "Fitness Permission",
- "description": {
- "android": "Please allow.",
- "ios": "Please allow."
+ "intro": {
+ "appstatus": {
+ "fix": "Fix",
+ "refresh":"Refresh",
+ "overall-description": "This app works in the background to automatically build a travel diary for you. Make sure that all the settings below are green so that the app can work properly!",
+ "explanation-title": "What are these used for?",
+ "overall-loc-name": "Location",
+ "overall-loc-description": "We use the background location permission to track your location in the background, even when the app is closed. Reading background locations removes the need to turn tracking on and off, making the app easier to use and preventing battery drain.",
+ "locsettings": {
+ "name": "Location Settings",
+ "description": {
+ "android-lt-9": "Location services should be enabled and set to High Accuracy. This allows us to accurately record the trajectory of the travel",
+ "android-gte-9": "Location services should be enabled. This allows us to access location data and generate the trip log",
+ "ios": "Location services should be enabled. This allows us to access location data and generate the trip log"
+ }
+ },
+ "locperms": {
+ "name": "Location Permissions",
+ "description": {
+ "android-lt-6": "Enabled during app installation.",
+ "android-6-9": "Please select 'allow'",
+ "android-10": "Please select 'Allow all the time'",
+ "android-11": "On the app settings page, choose the 'Location' permission and set it to 'Allow all the time'",
+ "android-gte-12": "On the app settings page, choose the 'Location' permission and set it to 'Allow all the time' and 'Precise'",
+ "ios-lt-13": "Please select 'Always allow'",
+ "ios-gte-13": "On the app settings page, please select 'Always' and 'Precise' and return here to continue"
+ }
+ },
+ "overall-fitness-name-android": "Physical activity",
+ "overall-fitness-name-ios": "Motion and Fitness",
+ "overall-fitness-description": "The fitness sensors distinguish between walking, bicycling and motorized modes. We use this data in order to separate the parts of multi-modal travel such as transit. We also use it to as a cross-check potentially spurious trips - if the location sensor jumps across town but the fitness sensor is stationary, we can guess that the trip was invalid.",
+ "fitnessperms": {
+ "name": "Fitness Permission",
+ "description": {
+ "android": "Please allow.",
+ "ios": "Please allow."
+ }
+ },
+ "overall-notification-name": "Notifications",
+ "overall-notification-description": "We need to use notifications to inform you if the settings are incorrect. We also use hourly invisible push notifications to wake up the app and allow it to upload data and check app status. We also use notifications to remind you to label your trips.",
+ "notificationperms": {
+ "app-enabled-name": "App Notifications",
+ "description": {
+ "android-enable": "On the app settings page, ensure that all notifications and channels are enabled.",
+ "ios-enable": "Please allow, on the popup or the app settings page if necessary"
+ }
+ },
+ "overall-background-restrictions-name": "Background restrictions",
+ "overall-background-restrictions-description": "The app runs in the background most of the time to make your life easier. You only need to open it periodically to label trips. Android sometimes restricts apps from working in the background. This prevents us from generating an accurate trip diary. Please remove background restrictions on this app.",
+ "unusedapprestrict": {
+ "name": "Unused apps disabled",
+ "description": {
+ "android-disable-lt-12": "On the app settings page, go to 'Permissions' and ensure that the app permissions will not be automatically reset.",
+ "android-disable-12": "On the app settings page, turn off 'Remove permissions and free up space.'",
+ "android-disable-gte-13": "On the app settings page, turn off 'Pause app activity if unused.'",
+ "ios": "Please allow."
+ }
+ },
+ "ignorebatteryopt": {
+ "name": "Ignore battery optimizations",
+ "description": {
+ "android-disable": "On the optimization page, go to all apps, search for this app and turn off optimizations.",
+ "ios": "Please allow."
+ }
+ }
+ },
+ "permissions": {
+ "locationPermExplanation-ios-lt-13": "please select 'Always allow'. This allows us to understand your travel even when you are not actively using the app",
+ "locationPermExplanation-ios-gte-13": "please select 'always' and 'precise' in the app settings page and return here to continue"
}
- },
- "overall-notification-name": "Notifications",
- "overall-notification-description": "We need to use notifications to inform you if the settings are incorrect. We also use hourly invisible push notifications to wake up the app and allow it to upload data and check app status. We also use notifications to remind you to label your trips.",
- "notificationperms": {
- "app-enabled-name": "App Notifications",
- "description": {
- "android-enable": "On the app settings page, ensure that all notifications and channels are enabled.",
- "ios-enable": "Please allow, on the popup or the app settings page if necessary"
- }
- },
- "overall-background-restrictions-name": "Background restrictions",
- "overall-background-restrictions-description": "The app runs in the background most of the time to make your life easier. You only need to open it periodically to label trips. Android sometimes restricts apps from working in the background. This prevents us from generating an accurate trip diary. Please remove background restrictions on this app.",
- "unusedapprestrict": {
- "name": "Unused apps disabled",
- "description": {
- "android-disable-lt-12": "On the app settings page, go to 'Permissions' and ensure that the app permissions will not be automatically reset.",
- "android-disable-12": "On the app settings page, turn off 'Remove permissions and free up space.'",
- "android-disable-gte-13": "On the app settings page, turn off 'Pause app activity if unused.'",
- "ios": "Please allow."
- }
- },
- "ignorebatteryopt": {
- "name": "Ignore battery optimizations",
- "description": {
- "android-disable": "On the optimization page, go to all apps, search for this app and turn off optimizations.",
- "ios": "Please allow."
- }
- }
},
- "permissions": {
- "locationPermExplanation-ios-lt-13": "please select 'Always allow'. This allows us to understand your travel even when you are not actively using the app",
- "locationPermExplanation-ios-gte-13": "please select 'always' and 'precise' in the app settings page and return here to continue"
- }
- },
- "allow_background": {
- "samsung": "Disable 'Medium power saving mode'"
- },
- "consent": {
- "permissions": "Permissions",
- "button-accept": "I accept",
- "button-decline": "I refuse"
- },
- "login": {
- "make-sure-save-your-opcode": "Make sure to save your OPcode!",
- "cannot-retrieve": "NREL cannot retrieve it for you later!",
- "save": "Save",
- "continue": "Continue",
- "enter-existing-token": "Enter the existing token that you have",
- "button-accept": "OK",
- "button-decline": "Cancel"
- },
- "survey": {
- "loading-prior-survey": "Loading prior survey responses...",
- "prev-survey-found": "Found previous survey response",
- "use-prior-response": "Use prior response",
- "edit-response": "Edit response",
- "move-on": "Move on",
- "survey": "Survey",
- "save": "Save",
- "back": "Back",
- "next": "Next",
- "powered-by": "Powered by",
- "dismiss": "Dismiss",
- "return-to-beginning": "Return to beginning",
- "go-to-end": "Go to End",
- "enketo-form-errors": "Form contains errors. Please see fields marked in red.",
- "enketo-timestamps-invalid": "The times you entered are invalid. Please ensure that the start time is before the end time."
- },
- "join": {
- "welcome-to-nrel-openpath": "Welcome to NREL OpenPATH",
- "proceed-further": "To proceed further, you need to enter a valid OPcode (token)",
- "what-is-opcode": "The OPcode is a long string starting with 'nrelop' that has been provided by your program admin through a website, email, text or printout.",
- "or": "or",
- "scan-button": "Scan the QR code ",
- "scan-details": "The OPcode will be written at the top of the image",
- "paste-button": "Paste the OPcode",
- "paste-details": "We suggest copy-pasting instead of typing since the OPcode is long and jumbled",
- "about-app-para-1": "The National Renewable Energy Laboratory’s Open Platform for Agile Trip Heuristics (NREL OpenPATH) enables people to track their travel modes—car, bus, bike, walking, etc.—and measure their associated energy use and carbon footprint.",
- "about-app-para-2": "The app empowers communities to understand their travel mode choices and patterns, experiment with options to make them more sustainable, and evaluate the results. Such results can inform effective transportation policy and planning and be used to build more sustainable and accessible cities.",
- "about-app-para-3": "It does so by building an automatic diary of all your trips, across all transportation modes. It reads multiple sensors, including location, in the background, and turns GPS tracking on and off automatically for minimal power consumption. The choice of the travel pattern information and the carbon footprint display style are study-specific.",
- "all-green-status": "Make sure that all status checks are green",
- "dont-force-kill": "Do not force kill the app",
- "background-restrictions": "On Samsung and Huwaei phones, make sure that background restrictions are turned off",
- "close": "Close",
- "tips-title": "Tip(s) for correct operation:"
- },
- "config": {
- "unable-read-saved-config": "Unable to read saved config",
- "unable-to-store-config": "Unable to store downladed config",
- "not-enough-parts-old-style": "OPcode {{token}} does not have at least two '_' characters",
- "no-nrelop-start": "OPcode {{token}} does not start with 'nrelop'",
- "not-enough-parts": "OPcode {{token}} does not have at least three '_' characters",
- "invalid-subgroup": "Invalid OPcode {{token}}, subgroup {{subgroup}} not found in list {{config_subgroups}}",
- "invalid-subgroup-no-default": "Invalid OPcode {{token}}, no subgroups, expected 'default' subgroup",
- "unable-download-config": "Unable to download study config",
- "invalid-opcode-format": "Invalid OPcode format",
- "error-loading-config-app-start": "Error loading config on app start",
- "survey-missing-formpath": "Error while fetching resources in config: survey_info.surveys has a survey without a formPath"
- },
- "errors": {
- "while-populating-composite": "Error while populating composite trips",
- "while-loading-another-week": "Error while loading travel of {{when}} week",
- "while-loading-specific-week": "Error while loading travel for the week of {{day}}",
- "while-log-messages": "While getting messages from the log ",
- "while-max-index": "While getting max index "
- },
- "consent-text": {
- "title": "NREL OPENPATH PRIVACY POLICY/TERMS OF USE",
- "introduction": {
- "header": "Introduction and Purpose",
- "what-is-openpath": "This data is being collected through OpenPATH, an NREL open-sourced platform. The smart phone application, NREL OpenPATH (“App”), combines data from smartphone sensors, semantic user labels and a short demographic survey.",
- "what-is-NREL": "NREL is a national laboratory of the U.S. Department of Energy, Office of Energy Efficiency and Renewable Energy, operated by Alliance for Sustainable Energy, LLC under Prime Contract No. DE-AC36-08GO28308. This Privacy Policy applies to the App provided by Alliance for Sustainable Energy, LLC. This App is provided solely for the purposes of collecting travel behavior data for the {{program_or_study}} and for research to inform public policy. None of the data collected by the App will never be sold or used for any commercial purposes, including advertising.",
- "if-disagree": "IF YOU DO NOT AGREE WITH THE TERMS OF THIS PRIVACY POLICY, PLEASE DELETE THE APP"
+ "allow_background": {
+ "samsung": "Disable 'Medium power saving mode'"
},
- "why": {
- "header": "Why we collect this information"
+ "consent":{
+ "permissions" : "Permissions",
+ "button-accept": "I accept",
+ "button-decline": "I refuse"
},
- "what": {
- "header": "What information we collect",
- "no-pii": "The App will never ask for any Personally Identifying Information (PII) such as name, email, address, or phone number.",
- "phone-sensor": "It collects phone sensor data pertaining to your location (including background location), accelerometer, device-generated activity and mode recognition, App usage time, and battery usage. The App will create a “travel diary” based on your background location data to determine your travel patterns and location history.",
- "labeling": "It will also ask you to periodically annotate these sensed trips with semantic labels, such as the trip mode, purpose, and replaced mode.",
- "demographics": "It will also request sociodemographic information such as your approximate age, gender, and household type. The sociodemographic factors can be used to understand the influence of lifestyle on travel behavior, as well as generalize the results to a broader population.",
- "open-source-data": "For the greatest transparency, the App is based on an open source platform, NREL’s OpenPATH. you can inspect the data that OpenPATH collects in the background at",
- "open-source-analysis": "the analysis pipeline at",
- "open-source-dashboard": "and the dashboard metrics at",
- "on-nrel-site": "For the greatest transparency, the App is based on an open source platform, NREL’s OpenPATH. you can inspect the data that OpenPATH collects in the background, the analysis pipeline, and the dashboard metrics through links on the NREL OpenPATH website."
+ "login":{
+ "make-sure-save-your-opcode":"Make sure to save your OPcode!",
+ "cannot-retrieve":"NREL cannot retrieve it for you later!",
+ "save":"Save",
+ "continue": "Continue",
+ "enter-existing-token": "Enter the existing token that you have",
+ "button-accept": "OK",
+ "button-decline": "Cancel"
},
- "opcode": {
- "header": "How we associate information with you",
- "not-autogen": "Program administrators will provide you with a 'opcode' that you will use to log in to the system. This long random string will be used for all further communication with the server. If you forget or lose your opcode, you may request it by providing your name and/or email address to the program administrator. Please do not contact NREL staff with opcode retrieval requests since we do not have access to the connection between your name/email and your opcode. The data that NREL automatically collects (phone sensor data, semidemographic data, etc.) will only be associated with your 'opcode'",
- "autogen": "You are logging in with a randomly generated 'opcode' that has been generated by the platform. This long random string will used for all further communication with the server. Only you know the opcode that is associated with you. There is no “Forgot password” option, and NREL staff cannot retrieve your opcode, even if you provide your name or email address. This means that, unless you store your opcode in a safe place, you will not have access to your prior data if you switch phones or uninstall and reinstall the App."
+ "survey": {
+ "loading-prior-survey": "Loading prior survey responses...",
+ "prev-survey-found": "Found previous survey response",
+ "use-prior-response": "Use prior response",
+ "edit-response": "Edit response",
+ "move-on": "Move on",
+ "survey": "Survey",
+ "save": "Save",
+ "back": "Back",
+ "next": "Next",
+ "powered-by": "Powered by",
+ "dismiss": "Dismiss",
+ "return-to-beginning": "Return to beginning",
+ "go-to-end": "Go to End",
+ "enketo-form-errors": "Form contains errors. Please see fields marked in red.",
+ "enketo-timestamps-invalid": "The times you entered are invalid. Please ensure that the start time is before the end time."
},
- "who-sees": {
- "header": "Who gets to see the information",
- "public-dash": "Aggregate metrics derived from the travel patterns will be made available on a public dashboard to provide transparency into the impact of the program. These metrics will focus on information summaries such as counts, distances and durations, and will not display individual travel locations or times.",
- "individual-info": "Individual labeling rates and trip level information will only be made available to:",
- "program-admins": "🧑 Program administrators from {{deployment_partner_name}} to {{raw_data_use}}, and",
- "nrel-devs": "💻 NREL OpenPATH developers for debugging",
- "TSDC-info": "The data will also be periodically archived in NREL’s Transportation Secure Data Center (TSDC) after a delay of 3 to 6 months. It will then be made available for legitimate research through existing, privacy-preserving TSDC operating procedures. Further information on the procedures is available",
- "on-website": " on the website ",
- "and-in": "and in",
- "this-pub": " this publication ",
- "and": "and",
- "fact-sheet": " fact sheet",
- "on-nrel-site": " through links on the NREL OpenPATH website."
+ "join": {
+ "welcome-to-nrel-openpath": "Welcome to NREL OpenPATH",
+ "proceed-further": "To proceed further, you need to enter a valid OPcode (token)",
+ "what-is-opcode": "The OPcode is a long string starting with 'nrelop' that has been provided by your program admin through a website, email, text or printout.",
+ "or": "or",
+ "scan-button": "Scan the QR code ",
+ "scan-details": "The OPcode will be written at the top of the image",
+ "paste-button": "Paste the OPcode",
+ "paste-details": "We suggest copy-pasting instead of typing since the OPcode is long and jumbled",
+ "about-app-para-1": "The National Renewable Energy Laboratory’s Open Platform for Agile Trip Heuristics (NREL OpenPATH) enables people to track their travel modes—car, bus, bike, walking, etc.—and measure their associated energy use and carbon footprint.",
+ "about-app-para-2": "The app empowers communities to understand their travel mode choices and patterns, experiment with options to make them more sustainable, and evaluate the results. Such results can inform effective transportation policy and planning and be used to build more sustainable and accessible cities.",
+ "about-app-para-3": "It does so by building an automatic diary of all your trips, across all transportation modes. It reads multiple sensors, including location, in the background, and turns GPS tracking on and off automatically for minimal power consumption. The choice of the travel pattern information and the carbon footprint display style are study-specific.",
+ "all-green-status": "Make sure that all status checks are green",
+ "dont-force-kill": "Do not force kill the app",
+ "background-restrictions": "On Samsung and Huwaei phones, make sure that background restrictions are turned off",
+ "close": "Close",
+ "tips-title": "Tip(s) for correct operation:"
},
- "rights": {
- "header": "Your rights",
- "app-required": "You are required to track your travel patterns using the App as a condition of participation in the Program. If you wish to withdraw from the Program, you should contact the program administrator, {{program_admin_contact}} to discuss termination options. If you wish to stay in the program but not use the app, please contact your program administrator to negotiate an alternative data collection procedure before uninstalling the app. If you uninstall the app without approval from the program administrator, you may not have access to the benefits provided by the program.",
- "app-not-required": "Participation in the {{program_or_study}} is completely voluntary. You have the right to decline to participate or to withdraw at any point in the Study without providing notice to NREL or the point of contact. If you do not wish to participate in the Study or to discontinue your participation in the Study, please delete the App.",
- "destroy-data-pt1": "If you would like to have your data destroyed, please contact K. Shankari ",
- "destroy-data-pt2": " requesting deletion. You must include your token in the request for deletion. Because we do not connect your identity with your token, we cannot delete your information without obtaining the token as part of the deletion request. We will then destroy all data associated with that deletion request, both in the online and archived datasets."
+ "config": {
+ "unable-read-saved-config": "Unable to read saved config",
+ "unable-to-store-config": "Unable to store downladed config",
+ "not-enough-parts-old-style": "OPcode {{token}} does not have at least two '_' characters",
+ "no-nrelop-start": "OPcode {{token}} does not start with 'nrelop'",
+ "not-enough-parts": "OPcode {{token}} does not have at least three '_' characters",
+ "invalid-subgroup": "Invalid OPcode {{token}}, subgroup {{subgroup}} not found in list {{config_subgroups}}",
+ "invalid-subgroup-no-default": "Invalid OPcode {{token}}, no subgroups, expected 'default' subgroup",
+ "unable-download-config": "Unable to download study config",
+ "invalid-opcode-format": "Invalid OPcode format",
+ "error-loading-config-app-start": "Error loading config on app start",
+ "survey-missing-formpath": "Error while fetching resources in config: survey_info.surveys has a survey without a formPath"
},
- "questions": {
- "header": "Questions",
- "for-questions": "If you have any questions about the data collection goals and results, please contact the primary point of contact for the study, {{program_admin_contact}}. If you have any technical questions about app operation, please contact NREL’s K. Shankari (k.shankari@nrel.gov)."
+ "errors": {
+ "while-populating-composite": "Error while populating composite trips",
+ "while-loading-another-week": "Error while loading travel of {{when}} week",
+ "while-loading-specific-week": "Error while loading travel for the week of {{day}}",
+ "while-log-messages": "While getting messages from the log ",
+ "while-max-index" : "While getting max index "
},
- "consent": {
- "header": "Consent",
- "press-button-to-consent": "Please select the button below to indicate that you have read and agree to this Privacy Policy, consent to the collection of your information, and want to participate in the {{program_or_study}}."
+ "consent-text": {
+ "title":"NREL OPENPATH PRIVACY POLICY/TERMS OF USE",
+ "introduction":{
+ "header":"Introduction and Purpose",
+ "what-is-openpath":"This data is being collected through OpenPATH, an NREL open-sourced platform. The smart phone application, NREL OpenPATH (“App”), combines data from smartphone sensors, semantic user labels and a short demographic survey.",
+ "what-is-NREL":"NREL is a national laboratory of the U.S. Department of Energy, Office of Energy Efficiency and Renewable Energy, operated by Alliance for Sustainable Energy, LLC under Prime Contract No. DE-AC36-08GO28308. This Privacy Policy applies to the App provided by Alliance for Sustainable Energy, LLC. This App is provided solely for the purposes of collecting travel behavior data for the {{program_or_study}} and for research to inform public policy. None of the data collected by the App will never be sold or used for any commercial purposes, including advertising.",
+ "if-disagree":"IF YOU DO NOT AGREE WITH THE TERMS OF THIS PRIVACY POLICY, PLEASE DELETE THE APP"
+ },
+ "why":{
+ "header":"Why we collect this information"
+ },
+ "what":{
+ "header":"What information we collect",
+ "no-pii":"The App will never ask for any Personally Identifying Information (PII) such as name, email, address, or phone number.",
+ "phone-sensor":"It collects phone sensor data pertaining to your location (including background location), accelerometer, device-generated activity and mode recognition, App usage time, and battery usage. The App will create a “travel diary” based on your background location data to determine your travel patterns and location history.",
+ "labeling":"It will also ask you to periodically annotate these sensed trips with semantic labels, such as the trip mode, purpose, and replaced mode.",
+ "demographics":"It will also request sociodemographic information such as your approximate age, gender, and household type. The sociodemographic factors can be used to understand the influence of lifestyle on travel behavior, as well as generalize the results to a broader population.",
+ "open-source-data":"For the greatest transparency, the App is based on an open source platform, NREL’s OpenPATH. you can inspect the data that OpenPATH collects in the background at",
+ "open-source-analysis":"the analysis pipeline at",
+ "open-source-dashboard":"and the dashboard metrics at",
+ "on-nrel-site": "For the greatest transparency, the App is based on an open source platform, NREL’s OpenPATH. you can inspect the data that OpenPATH collects in the background, the analysis pipeline, and the dashboard metrics through links on the NREL OpenPATH website."
+ },
+ "opcode":{
+ "header":"How we associate information with you",
+ "not-autogen":"Program administrators will provide you with a 'opcode' that you will use to log in to the system. This long random string will be used for all further communication with the server. If you forget or lose your opcode, you may request it by providing your name and/or email address to the program administrator. Please do not contact NREL staff with opcode retrieval requests since we do not have access to the connection between your name/email and your opcode. The data that NREL automatically collects (phone sensor data, semidemographic data, etc.) will only be associated with your 'opcode'",
+ "autogen":"You are logging in with a randomly generated 'opcode' that has been generated by the platform. This long random string will used for all further communication with the server. Only you know the opcode that is associated with you. There is no “Forgot password” option, and NREL staff cannot retrieve your opcode, even if you provide your name or email address. This means that, unless you store your opcode in a safe place, you will not have access to your prior data if you switch phones or uninstall and reinstall the App."
+ },
+ "who-sees":{
+ "header":"Who gets to see the information",
+ "public-dash":"Aggregate metrics derived from the travel patterns will be made available on a public dashboard to provide transparency into the impact of the program. These metrics will focus on information summaries such as counts, distances and durations, and will not display individual travel locations or times.",
+ "individual-info":"Individual labeling rates and trip level information will only be made available to:",
+ "program-admins":"🧑 Program administrators from {{deployment_partner_name}} to {{raw_data_use}}, and",
+ "nrel-devs":"💻 NREL OpenPATH developers for debugging",
+ "TSDC-info":"The data will also be periodically archived in NREL’s Transportation Secure Data Center (TSDC) after a delay of 3 to 6 months. It will then be made available for legitimate research through existing, privacy-preserving TSDC operating procedures. Further information on the procedures is available",
+ "on-website":" on the website ",
+ "and-in":"and in",
+ "this-pub":" this publication ",
+ "and":"and",
+ "fact-sheet":" fact sheet",
+ "on-nrel-site": " through links on the NREL OpenPATH website."
+ },
+ "rights":{
+ "header":"Your rights",
+ "app-required":"You are required to track your travel patterns using the App as a condition of participation in the Program. If you wish to withdraw from the Program, you should contact the program administrator, {{program_admin_contact}} to discuss termination options. If you wish to stay in the program but not use the app, please contact your program administrator to negotiate an alternative data collection procedure before uninstalling the app. If you uninstall the app without approval from the program administrator, you may not have access to the benefits provided by the program.",
+ "app-not-required":"Participation in the {{program_or_study}} is completely voluntary. You have the right to decline to participate or to withdraw at any point in the Study without providing notice to NREL or the point of contact. If you do not wish to participate in the Study or to discontinue your participation in the Study, please delete the App.",
+ "destroy-data-pt1":"If you would like to have your data destroyed, please contact K. Shankari ",
+ "destroy-data-pt2":" requesting deletion. You must include your token in the request for deletion. Because we do not connect your identity with your token, we cannot delete your information without obtaining the token as part of the deletion request. We will then destroy all data associated with that deletion request, both in the online and archived datasets."
+ },
+ "questions":{
+ "header":"Questions",
+ "for-questions":"If you have any questions about the data collection goals and results, please contact the primary point of contact for the study, {{program_admin_contact}}. If you have any technical questions about app operation, please contact NREL’s K. Shankari (k.shankari@nrel.gov)."
+ },
+ "consent":{
+ "header":"Consent",
+ "press-button-to-consent":"Please select the button below to indicate that you have read and agree to this Privacy Policy, consent to the collection of your information, and want to participate in the {{program_or_study}}."
+ }
}
- }
}
diff --git a/www/js/angular-react-helper.tsx b/www/js/angular-react-helper.tsx
index eefbcd6e5..984e529ff 100644
--- a/www/js/angular-react-helper.tsx
+++ b/www/js/angular-react-helper.tsx
@@ -5,29 +5,27 @@
import angular from 'angular';
import { createRoot } from 'react-dom/client';
import React from 'react';
-import {
- Provider as PaperProvider,
- MD3LightTheme as DefaultTheme,
- MD3Colors,
-} from 'react-native-paper';
+import { Provider as PaperProvider, MD3LightTheme as DefaultTheme, MD3Colors } from 'react-native-paper';
import { getTheme } from './appTheme';
function toBindings(propTypes) {
const bindings = {};
- Object.keys(propTypes).forEach((key) => (bindings[key] = '<'));
+ Object.keys(propTypes).forEach(key => bindings[key] = '<');
return bindings;
}
function toProps(propTypes, controller) {
const props = {};
- Object.keys(propTypes).forEach((key) => (props[key] = controller[key]));
+ Object.keys(propTypes).forEach(key => props[key] = controller[key]);
return props;
}
export function angularize(component, name, modulePath) {
component.module = modulePath;
const nameCamelCase = name[0].toLowerCase() + name.slice(1);
- angular.module(modulePath, []).component(nameCamelCase, makeComponentProps(component));
+ angular
+ .module(modulePath, [])
+ .component(nameCamelCase, makeComponentProps(component));
}
const theme = getTheme();
@@ -35,33 +33,29 @@ export function makeComponentProps(Component) {
const propTypes = Component.propTypes || {};
return {
bindings: toBindings(propTypes),
- controller: [
- '$element',
- function ($element) {
- /* TODO: once the inf scroll list is converted to React and no longer uses
+ controller: ['$element', function($element) {
+ /* TODO: once the inf scroll list is converted to React and no longer uses
collection-repeat, we can just set the root here one time
and will not have to reassign it in $onChanges. */
- /* Until then, React will complain everytime we reassign an element's root */
- let root;
- this.$onChanges = () => {
- root = createRoot($element[0]);
- const props = toProps(propTypes, this);
- root.render(
-
-
-
- ,
- );
- };
- this.$onDestroy = () => root.unmount();
- },
- ],
+
+
+
+ );
+ };
+ this.$onDestroy = () => root.unmount();
+ }]
};
}
@@ -76,11 +70,11 @@ export function getAngularService(name: string) {
throw new Error(`Couldn't find "${name}" angular service`);
}
- return service as any; // casting to 'any' because not all Angular services are typed
+ return (service as any); // casting to 'any' because not all Angular services are typed
}
export function createScopeWithVars(vars) {
- const scope = getAngularService('$rootScope').$new();
+ const scope = getAngularService("$rootScope").$new();
Object.assign(scope, vars);
return scope;
}
diff --git a/www/js/app.js b/www/js/app.js
index 7ebbb90c5..a52edaa12 100644
--- a/www/js/app.js
+++ b/www/js/app.js
@@ -25,122 +25,100 @@ import initializedI18next from './i18nextInit';
window.i18next = initializedI18next;
import 'ng-i18next';
-angular
- .module('emission', [
- 'ionic',
- 'jm.i18next',
- 'emission.controllers',
- 'emission.services',
- 'emission.plugin.logger',
- 'emission.splash.customURLScheme',
- 'emission.splash.referral',
+angular.module('emission', ['ionic', 'jm.i18next',
+ 'emission.controllers','emission.services', 'emission.plugin.logger',
+ 'emission.splash.customURLScheme', 'emission.splash.referral',
'emission.services.email',
- 'emission.intro',
- 'emission.main',
- 'emission.config.dynamic',
- 'emission.config.server_conn',
- 'emission.join.ctrl',
- 'pascalprecht.translate',
- 'LocalStorageModule',
- ])
-
- .run(
- function (
- $ionicPlatform,
- $rootScope,
- $http,
- Logger,
- CustomURLScheme,
- ReferralHandler,
- DynamicConfig,
- localStorageService,
- ServerConnConfig,
- ) {
- console.log('Starting run');
- // ensure that plugin events are delivered after the ionicPlatform is ready
- // https://github.com/katzer/cordova-plugin-local-notifications#launch-details
- window.skipLocalNotificationReady = true;
- // alert("Starting run");
- // BEGIN: Global listeners, no need to wait for the platform
- // TODO: Although the onLaunch call doesn't need to wait for the platform the
- // handlers do. Can we rely on the fact that the event is generated from
- // native code, so will only be launched after the platform is ready?
- CustomURLScheme.onLaunch(function (event, url, urlComponents) {
- console.log('GOT URL:' + url);
- // alert("GOT URL:"+url);
-
- if (urlComponents.route == 'join') {
- ReferralHandler.setupGroupReferral(urlComponents);
- StartPrefs.loadWithPrefs();
- } else if (urlComponents.route == 'login_token') {
- DynamicConfig.initByUser(urlComponents);
- }
- });
- // END: Global listeners
- $ionicPlatform.ready(function () {
- // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
- // for form inputs)
- Logger.log('ionicPlatform is ready');
-
- if (window.StatusBar) {
- // org.apache.cordova.statusbar required
- StatusBar.styleDefault();
- }
- cordova.plugin.http.setDataSerializer('json');
- // backwards compat hack to be consistent with
- // https://github.com/e-mission/e-mission-data-collection/commit/92f41145e58c49e3145a9222a78d1ccacd16d2a7#diff-962320754eba07107ecd413954411f725c98fd31cddbb5defd4a542d1607e5a3R160
- // remove during migration to react native
- localStorageService.remove('OP_GEOFENCE_CFG');
- cordova.plugins.BEMUserCache.removeLocalStorage('OP_GEOFENCE_CFG');
- });
- console.log('Ending run');
- },
- )
-
- .config(function ($stateProvider, $urlRouterProvider, $compileProvider) {
- console.log('Starting config');
- // alert("config");
-
- // Ionic uses AngularUI Router which uses the concept of states
- // Learn more here: https://github.com/angular-ui/ui-router
- // Set a few states which the app can be in.
- // The 'intro' and 'diary' states are found in their respective modules
- // Each state's controller can be found in controllers.js
- $compileProvider.imgSrcSanitizationWhitelist(/^\s*(https?|ftp|file|blob|ionic):|data:image/);
- $stateProvider
- // set up a state for the splash screen. This has no parents and no children
- // because it is basically just used to load the user's preferred screen.
- // This cannot directly use plugins - has to check for them first.
- .state('splash', {
+ 'emission.intro', 'emission.main', 'emission.config.dynamic',
+ 'emission.config.server_conn', 'emission.join.ctrl',
+ 'pascalprecht.translate', 'LocalStorageModule'])
+
+.run(function($ionicPlatform, $rootScope, $http, Logger,
+ CustomURLScheme, ReferralHandler, DynamicConfig, localStorageService, ServerConnConfig) {
+ console.log("Starting run");
+ // ensure that plugin events are delivered after the ionicPlatform is ready
+ // https://github.com/katzer/cordova-plugin-local-notifications#launch-details
+ window.skipLocalNotificationReady = true;
+ // alert("Starting run");
+ // BEGIN: Global listeners, no need to wait for the platform
+ // TODO: Although the onLaunch call doesn't need to wait for the platform the
+ // handlers do. Can we rely on the fact that the event is generated from
+ // native code, so will only be launched after the platform is ready?
+ CustomURLScheme.onLaunch(function(event, url, urlComponents){
+ console.log("GOT URL:"+url);
+ // alert("GOT URL:"+url);
+
+ if (urlComponents.route == 'join') {
+ ReferralHandler.setupGroupReferral(urlComponents);
+ StartPrefs.loadWithPrefs();
+ } else if (urlComponents.route == 'login_token') {
+ DynamicConfig.initByUser(urlComponents);
+ }
+ });
+ // END: Global listeners
+ $ionicPlatform.ready(function() {
+ // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
+ // for form inputs)
+ Logger.log("ionicPlatform is ready");
+
+ if (window.StatusBar) {
+ // org.apache.cordova.statusbar required
+ StatusBar.styleDefault();
+ }
+ cordova.plugin.http.setDataSerializer('json');
+ // backwards compat hack to be consistent with
+ // https://github.com/e-mission/e-mission-data-collection/commit/92f41145e58c49e3145a9222a78d1ccacd16d2a7#diff-962320754eba07107ecd413954411f725c98fd31cddbb5defd4a542d1607e5a3R160
+ // remove during migration to react native
+ localStorageService.remove("OP_GEOFENCE_CFG");
+ cordova.plugins.BEMUserCache.removeLocalStorage("OP_GEOFENCE_CFG");
+ });
+ console.log("Ending run");
+})
+
+.config(function($stateProvider, $urlRouterProvider, $compileProvider) {
+ console.log("Starting config");
+ // alert("config");
+
+ // Ionic uses AngularUI Router which uses the concept of states
+ // Learn more here: https://github.com/angular-ui/ui-router
+ // Set a few states which the app can be in.
+ // The 'intro' and 'diary' states are found in their respective modules
+ // Each state's controller can be found in controllers.js
+ $compileProvider.imgSrcSanitizationWhitelist(/^\s*(https?|ftp|file|blob|ionic):|data:image/);
+ $stateProvider
+ // set up a state for the splash screen. This has no parents and no children
+ // because it is basically just used to load the user's preferred screen.
+ // This cannot directly use plugins - has to check for them first.
+ .state('splash', {
url: '/splash',
templateUrl: 'templates/splash/splash.html',
- controller: 'SplashCtrl',
- })
-
- // add the join screen to the list of initially defined states
- // we can't put it in intro since it comes before it
- // we can't put it in main because it is also a temporary screen that only
- // shows up when we have no config.
- // so we put it in here
- .state('root.join', {
- url: '/join',
- templateUrl: 'templates/join/request_join.html',
- controller: 'JoinCtrl',
- })
-
- // setup an abstract state for the root. Only children of this can be loaded
- // as preferred screens, and all children of this can assume that the device
- // is ready.
- .state('root', {
- url: '/root',
- abstract: true,
- template: '',
- controller: 'RootCtrl',
- });
-
- // alert("about to fall back to otherwise");
- // if none of the above states are matched, use this as the fallback
- $urlRouterProvider.otherwise('/splash');
-
- console.log('Ending config');
+ controller: 'SplashCtrl'
+ })
+
+ // add the join screen to the list of initially defined states
+ // we can't put it in intro since it comes before it
+ // we can't put it in main because it is also a temporary screen that only
+ // shows up when we have no config.
+ // so we put it in here
+ .state('root.join', {
+ url: '/join',
+ templateUrl: 'templates/join/request_join.html',
+ controller: 'JoinCtrl'
+ })
+
+ // setup an abstract state for the root. Only children of this can be loaded
+ // as preferred screens, and all children of this can assume that the device
+ // is ready.
+ .state('root', {
+ url: '/root',
+ abstract: true,
+ template: '',
+ controller: 'RootCtrl'
});
+
+ // alert("about to fall back to otherwise");
+ // if none of the above states are matched, use this as the fallback
+ $urlRouterProvider.otherwise('/splash');
+
+ console.log("Ending config");
+});
diff --git a/www/js/appTheme.ts b/www/js/appTheme.ts
index 0a6834534..5f47f00b1 100644
--- a/www/js/appTheme.ts
+++ b/www/js/appTheme.ts
@@ -28,7 +28,7 @@ const AppTheme = {
},
success: '#00a665', // lch(60% 55 155)
warn: '#f8cf53', //lch(85% 65 85)
- danger: '#f23934', // lch(55% 85 35)
+ danger: '#f23934' // lch(55% 85 35)
},
roundness: 5,
};
@@ -47,26 +47,23 @@ type DPartial = { [P in keyof T]?: DPartial }; // https://stackoverflow
type PartialTheme = DPartial;
const flavorOverrides = {
- place: {
- // for PlaceCards; a blueish color scheme
+ place: { // for PlaceCards; a blueish color scheme
colors: {
elevation: {
level1: '#cbe6ff', // lch(90, 20, 250)
},
- },
+ }
},
- untracked: {
- // for UntrackedTimeCards; a reddish color scheme
+ untracked: { // for UntrackedTimeCards; a reddish color scheme
colors: {
primary: '#8c4a57', // lch(40 30 10)
primaryContainer: '#e3bdc2', // lch(80 15 10)
elevation: {
level1: '#f8ebec', // lch(94 5 10)
},
- },
+ }
},
- draft: {
- // for TripCards and LabelDetailsScreen of draft trips; a greyish color scheme
+ draft: { // for TripCards and LabelDetailsScreen of draft trips; a greyish color scheme
colors: {
primary: '#616971', // lch(44 6 250)
primaryContainer: '#b6bcc2', // lch(76 4 250)
@@ -77,7 +74,7 @@ const flavorOverrides = {
level1: '#e1e3e4', // lch(90 1 250)
level2: '#d2d5d8', // lch(85 2 250)
},
- },
+ }
},
} satisfies Record;
@@ -86,10 +83,7 @@ const flavorOverrides = {
export const getTheme = (flavor?: keyof typeof flavorOverrides) => {
if (!flavorOverrides[flavor]) return AppTheme;
const typeStyle = flavorOverrides[flavor];
- const scopedElevation = { ...AppTheme.colors.elevation, ...typeStyle?.colors?.elevation };
- const scopedColors = {
- ...AppTheme.colors,
- ...{ ...typeStyle.colors, elevation: scopedElevation },
- };
- return { ...AppTheme, colors: scopedColors };
-};
+ const scopedElevation = {...AppTheme.colors.elevation, ...typeStyle?.colors?.elevation};
+ const scopedColors = {...AppTheme.colors, ...{...typeStyle.colors, elevation: scopedElevation}};
+ return {...AppTheme, colors: scopedColors};
+}
diff --git a/www/js/appstatus/ExplainPermissions.tsx b/www/js/appstatus/ExplainPermissions.tsx
index d0d63ebe7..cb0db4bba 100644
--- a/www/js/appstatus/ExplainPermissions.tsx
+++ b/www/js/appstatus/ExplainPermissions.tsx
@@ -1,34 +1,41 @@
-import React from 'react';
-import { Modal, ScrollView, useWindowDimensions, View } from 'react-native';
+import React from "react";
+import { Modal, ScrollView, useWindowDimensions, View } from "react-native";
import { Button, Dialog, Text } from 'react-native-paper';
-import { useTranslation } from 'react-i18next';
+import { useTranslation } from "react-i18next";
const ExplainPermissions = ({ explanationList, visible, setVisible }) => {
- const { t } = useTranslation();
- const { height: windowHeight } = useWindowDimensions();
+ const { t } = useTranslation();
+ const { height: windowHeight } = useWindowDimensions();
- return (
- setVisible(false)}>
-
-
- );
+ return (
+ setVisible(false)} >
+
+
+ );
};
-export default ExplainPermissions;
+export default ExplainPermissions;
\ No newline at end of file
diff --git a/www/js/appstatus/PermissionItem.tsx b/www/js/appstatus/PermissionItem.tsx
index cd111f3b3..2899943f1 100644
--- a/www/js/appstatus/PermissionItem.tsx
+++ b/www/js/appstatus/PermissionItem.tsx
@@ -1,19 +1,21 @@
-import React from 'react';
+import React from "react";
import { List, Button } from 'react-native-paper';
-import { useTranslation } from 'react-i18next';
+import { useTranslation } from "react-i18next";
const PermissionItem = ({ check }) => {
- const { t } = useTranslation();
+ const { t } = useTranslation();
- return (
- }
- right={() => }
- />
- );
+ return (
+ }
+ right={() => }
+ />
+ );
};
-
-export default PermissionItem;
+
+export default PermissionItem;
\ No newline at end of file
diff --git a/www/js/appstatus/permissioncheck.js b/www/js/appstatus/permissioncheck.js
index 95d4f576c..84067a701 100644
--- a/www/js/appstatus/permissioncheck.js
+++ b/www/js/appstatus/permissioncheck.js
@@ -4,538 +4,426 @@
import angular from 'angular';
-angular
- .module('emission.appstatus.permissioncheck', [])
- .directive('permissioncheck', function () {
+angular.module('emission.appstatus.permissioncheck',
+ [])
+.directive('permissioncheck', function() {
return {
- scope: {
- overallstatus: '=',
- },
- controller: 'PermissionCheckControl',
- templateUrl: 'templates/appstatus/permissioncheck.html',
+ scope: {
+ overallstatus: "=",
+ },
+ controller: "PermissionCheckControl",
+ templateUrl: "templates/appstatus/permissioncheck.html"
};
- })
- .controller(
- 'PermissionCheckControl',
- function ($scope, $element, $attrs, $ionicPlatform, $ionicPopup, $window) {
- console.log('PermissionCheckControl initialized with status ' + $scope.overallstatus);
+}).
+controller("PermissionCheckControl", function($scope, $element, $attrs,
+ $ionicPlatform, $ionicPopup, $window) {
+ console.log("PermissionCheckControl initialized with status "+$scope.overallstatus);
- $scope.setupLocChecks = function (platform, version) {
- if (platform.toLowerCase() == 'android') {
- return $scope.setupAndroidLocChecks(version);
- } else if (platform.toLowerCase() == 'ios') {
- return $scope.setupIOSLocChecks(version);
+ $scope.setupLocChecks = function(platform, version) {
+ if (platform.toLowerCase() == "android") {
+ return $scope.setupAndroidLocChecks(version);
+ } else if (platform.toLowerCase() == "ios") {
+ return $scope.setupIOSLocChecks(version);
} else {
- alert('Unknown platform, no tracking');
+ alert("Unknown platform, no tracking");
}
- };
+ }
- $scope.setupFitnessChecks = function (platform, version) {
- if (platform.toLowerCase() == 'android') {
- return $scope.setupAndroidFitnessChecks(version);
- } else if (platform.toLowerCase() == 'ios') {
- return $scope.setupIOSFitnessChecks(version);
+ $scope.setupFitnessChecks = function(platform, version) {
+ if (platform.toLowerCase() == "android") {
+ return $scope.setupAndroidFitnessChecks(version);
+ } else if (platform.toLowerCase() == "ios") {
+ return $scope.setupIOSFitnessChecks(version);
} else {
- alert('Unknown platform, no tracking');
+ alert("Unknown platform, no tracking");
}
- };
+ }
- $scope.setupNotificationChecks = function (platform, version) {
- return $scope.setupAndroidNotificationChecks(version);
- };
+ $scope.setupNotificationChecks = function(platform, version) {
+ return $scope.setupAndroidNotificationChecks(version);
+ }
- $scope.setupBackgroundRestrictionChecks = function (platform, version) {
- if (platform.toLowerCase() == 'android') {
- $scope.backgroundUnrestrictionsNeeded = true;
- return $scope.setupAndroidBackgroundRestrictionChecks(version);
- } else if (platform.toLowerCase() == 'ios') {
- $scope.backgroundUnrestrictionsNeeded = false;
- $scope.overallBackgroundRestrictionStatus = true;
- $scope.backgroundRestrictionChecks = [];
- return true;
+ $scope.setupBackgroundRestrictionChecks = function(platform, version) {
+ if (platform.toLowerCase() == "android") {
+ $scope.backgroundUnrestrictionsNeeded = true;
+ return $scope.setupAndroidBackgroundRestrictionChecks(version);
+ } else if (platform.toLowerCase() == "ios") {
+ $scope.backgroundUnrestrictionsNeeded = false;
+ $scope.overallBackgroundRestrictionStatus = true;
+ $scope.backgroundRestrictionChecks = [];
+ return true;
} else {
- alert('Unknown platform, no tracking');
+ alert("Unknown platform, no tracking");
}
- };
+ }
- let iconMap = (statusState) => (statusState ? '✅' : '❌');
- let classMap = (statusState) => (statusState ? 'status-green' : 'status-red');
+ let iconMap = (statusState) => statusState? "✅" : "❌";
+ let classMap = (statusState) => statusState? "status-green" : "status-red";
- $scope.recomputeOverallStatus = function () {
- $scope.overallstatus =
- $scope.overallLocStatus &&
- $scope.overallFitnessStatus &&
- $scope.overallNotificationStatus &&
- $scope.overallBackgroundRestrictionStatus;
- };
+ $scope.recomputeOverallStatus = function() {
+ $scope.overallstatus = $scope.overallLocStatus
+ && $scope.overallFitnessStatus
+ && $scope.overallNotificationStatus
+ && $scope.overallBackgroundRestrictionStatus;
+ }
- $scope.recomputeLocStatus = function () {
+ $scope.recomputeLocStatus = function() {
$scope.locChecks.forEach((lc) => {
- lc.statusIcon = iconMap(lc.statusState);
- lc.statusClass = classMap(lc.statusState);
+ lc.statusIcon = iconMap(lc.statusState);
+ lc.statusClass = classMap(lc.statusState)
});
- $scope.overallLocStatus = $scope.locChecks
- .map((lc) => lc.statusState)
- .reduce((pv, cv) => pv && cv);
- console.log('overallLocStatus = ' + $scope.overallLocStatus + ' from ', $scope.locChecks);
+ $scope.overallLocStatus = $scope.locChecks.map((lc) => lc.statusState).reduce((pv, cv) => pv && cv);
+ console.log("overallLocStatus = "+$scope.overallLocStatus+" from ", $scope.locChecks);
$scope.overallLocStatusIcon = iconMap($scope.overallLocStatus);
$scope.overallLocStatusClass = classMap($scope.overallLocStatus);
$scope.recomputeOverallStatus();
- };
+ }
- $scope.recomputeFitnessStatus = function () {
+ $scope.recomputeFitnessStatus = function() {
$scope.fitnessChecks.forEach((fc) => {
- fc.statusIcon = iconMap(fc.statusState);
- fc.statusClass = classMap(fc.statusState);
+ fc.statusIcon = iconMap(fc.statusState);
+ fc.statusClass = classMap(fc.statusState)
});
- $scope.overallFitnessStatus = $scope.fitnessChecks
- .map((fc) => fc.statusState)
- .reduce((pv, cv) => pv && cv);
- console.log(
- 'overallFitnessStatus = ' + $scope.overallFitnessStatus + ' from ',
- $scope.fitnessChecks,
- );
+ $scope.overallFitnessStatus = $scope.fitnessChecks.map((fc) => fc.statusState).reduce((pv, cv) => pv && cv);
+ console.log("overallFitnessStatus = "+$scope.overallFitnessStatus+" from ", $scope.fitnessChecks);
$scope.overallFitnessStatusIcon = iconMap($scope.overallFitnessStatus);
$scope.overallFitnessStatusClass = classMap($scope.overallFitnessStatus);
$scope.recomputeOverallStatus();
- };
+ }
- $scope.recomputeNotificationStatus = function () {
+ $scope.recomputeNotificationStatus = function() {
$scope.notificationChecks.forEach((nc) => {
- nc.statusIcon = iconMap(nc.statusState);
- nc.statusClass = classMap(nc.statusState);
+ nc.statusIcon = iconMap(nc.statusState);
+ nc.statusClass = classMap(nc.statusState)
});
- $scope.overallNotificationStatus = $scope.notificationChecks
- .map((nc) => nc.statusState)
- .reduce((pv, cv) => pv && cv);
- console.log(
- 'overallNotificationStatus = ' + $scope.overallNotificationStatus + ' from ',
- $scope.notificationChecks,
- );
+ $scope.overallNotificationStatus = $scope.notificationChecks.map((nc) => nc.statusState).reduce((pv, cv) => pv && cv);
+ console.log("overallNotificationStatus = "+$scope.overallNotificationStatus+" from ", $scope.notificationChecks);
$scope.overallNotificationStatusIcon = iconMap($scope.overallNotificationStatus);
$scope.overallNotificationStatusClass = classMap($scope.overallNotificationStatus);
$scope.recomputeOverallStatus();
- };
+ }
- $scope.recomputeBackgroundRestrictionStatus = function () {
+ $scope.recomputeBackgroundRestrictionStatus = function() {
if (!$scope.backgroundRestrictionChecks) return;
$scope.backgroundRestrictionChecks.forEach((brc) => {
- brc.statusIcon = iconMap(brc.statusState);
- brc.statusClass = classMap(brc.statusState);
+ brc.statusIcon = iconMap(brc.statusState);
+ brc.statusClass = classMap(brc.statusState)
});
- $scope.overallBackgroundRestrictionStatus = $scope.backgroundRestrictionChecks
- .map((nc) => nc.statusState)
- .reduce((pv, cv) => pv && cv);
- console.log(
- 'overallBackgroundRestrictionStatus = ' +
- $scope.overallBackgroundRestrictionStatus +
- ' from ',
- $scope.backgroundRestrictionChecks,
- );
- $scope.overallBackgroundRestrictionStatusIcon = iconMap(
- $scope.overallBackgroundRestrictionStatus,
- );
- $scope.overallBackgroundRestrictionStatusClass = classMap(
- $scope.overallBackgroundRestrictionStatus,
- );
+ $scope.overallBackgroundRestrictionStatus = $scope.backgroundRestrictionChecks.map((nc) => nc.statusState).reduce((pv, cv) => pv && cv);
+ console.log("overallBackgroundRestrictionStatus = "+$scope.overallBackgroundRestrictionStatus+" from ", $scope.backgroundRestrictionChecks);
+ $scope.overallBackgroundRestrictionStatusIcon = iconMap($scope.overallBackgroundRestrictionStatus);
+ $scope.overallBackgroundRestrictionStatusClass = classMap($scope.overallBackgroundRestrictionStatus);
$scope.recomputeOverallStatus();
- };
+ }
- let checkOrFix = function (checkObj, nativeFn, recomputeFn, showError = true) {
+ let checkOrFix = function(checkObj, nativeFn, recomputeFn, showError=true) {
return nativeFn()
- .then((status) => {
- console.log('availability ', status);
- $scope.$apply(() => {
- checkObj.statusState = true;
- recomputeFn();
+ .then((status) => {
+ console.log("availability ", status)
+ $scope.$apply(() => {
+ checkObj.statusState = true;
+ recomputeFn();
+ });
+ return status;
+ }).catch((error) => {
+ console.log("Error", error)
+ if (showError) {
+ $ionicPopup.alert({
+ title: "Error",
+ template: "