Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Deault label options #1055

Conversation

sebastianbarry
Copy link
Contributor

Added Default Label Options behavior

Configs without label_options value now use a default locally stored label-options.json.sample file to generate label options - no more i81nUtils


confirmHelper.ts

  • Removed archaic behavior or using old Angular i18nUtils module to get the filename of the translations' trip_confirm_options.json file
  • The "else" default "no label_options found in config" behavior is almost identical to the if(appConfig.label_options), but it just uses the default label options URL at label-options.json.sample
  • Pulled the language-specific text handling behavior out of the if statement, because either way (label_options or no label_options) the JSON data model will look the same

label-options.json.sample

trip_confirm_options.json.sample

  • Removed this file

JGreenlee and others added 4 commits October 3, 2023 19:38
We had this issue (e-mission/e-mission-docs#999) where if the app was exited in the middle of onboarding, and then opened again, this error would show.
I found out that this occured because the LabelTab was being rendered for a split second until the onboarding state was still being resolved.

It takes some time to determine the onboarding state, and it requires waiting for native calls, which is why `getPendingOnboardingState` in onboardingHelper returns a Promise.
But until this promise is resolved, we don't really know if we should show a) onboarding flow or b) the main app with tab navigation.

We had been keeping `pendingOnboardingState` as `null` if the onboarding was finished. In this case, there was no 'pending' onboarding state and we would just continue to the main app.

But a safer thing to do here is have onboarding state be null **only** if it hasn't been determined yet. If it *has* been determined, then we will explictly mark it with a route of DONE. So if it's DONE we show the main app, if it's something other than DONE, we show the onboarding flow, and if it's null, we can show a big loading spinner while we determine what state we are in.

In doing this, we no longer just keep track of *pending* onboarding states - we must always keep track of an onboarding state, whether it is DONE or not. So while making this adjustment, I renamed the variable throughout as simply 'onboardingState'.
- increase page padding
- increase gap between paragraphs
- increase font sizes
- have content vertically centered by margin: 'auto'
…el options

confirmHelper.ts
- Removed archaic behavior or using old Angular i18nUtils module to get the filename of the translations' trip_confirm_options.json file
- The "else" default "no label_options found in config" behavior is almost identical to the if(appConfig.label_options), but it just uses the default label options URL at label-options.json.sample
- Pulled the language-specific text handling behavior out of the if statement, because either way (label_options or no label_options) the JSON data model will look the same

label-options.json.sample
- Created new file
- Replaces trip_confirm_options.json.sample (this location in confirmHelper.ts was the only place in the codebase using this file)
- Modeled after https://github.com/e-mission/nrel-openpath-deploy-configs/blob/main/label_options/example-program-label-options.json
- Only has translations for EN and ES

trip_confirm_options.json.sample
- Removed this file
@sebastianbarry
Copy link
Contributor Author

sebastianbarry commented Oct 5, 2023

Testing:

iPhone 13 iOS 15.4
Labels being loaded locally Screenshot 2023-10-05 at 10 48 04 AM
Labels working Simulator Screenshot - iPhone 13 - 2023-10-05 at 10 45 20
Labels working Simulator Screenshot - iPhone 13 - 2023-10-05 at 10 45 23

@sebastianbarry
Copy link
Contributor Author

Next Steps:

label-options.json.sample is based off https://github.com/e-mission/nrel-openpath-deploy-configs/tree/main/label_options which only contain translations for EN and ES

  • Should we include the other translations in this sample file as well?
  • Should we somehow internationalize it so that the label translations come from es.json or en.json so that way we don't need to have some translations in here, requiring textual changes in the future to consider this "easily forgotten" file?

@shankari
Copy link
Contributor

  1. I don't think we need to include the translations in this sample file. The only other supported translation is Lao, and it has a separate set of translated entries anyway. If/when we need to support more translations of the default modes/purposes, we can deal with it then.
  2. I don't think so. The whole point of having dynamic labels is that programs/studies can have their own custom labels without having to change the app code. So the translations for dynamic labels must be in the dynamic labels file - it needs to be fully self-contained. And if we want the default and dynamic label files to have the same format, then the translations must be in the default options file as well. If you have an alternate suggestion, please make the case for it.

@sebastianbarry
Copy link
Contributor Author

sebastianbarry commented Oct 10, 2023

  1. I don't think so. The whole point of having dynamic labels is that programs/studies can have their own custom labels without having to change the app code. So the translations for dynamic labels must be in the dynamic labels file - it needs to be fully self-contained. And if we want the default and dynamic label files to have the same format, then the translations must be in the default options file as well. If you have an alternate suggestion, please make the case for it.

@shankari Here is my alternate suggestion, please let me know what you think:

Move the "translations" portion into all of the "en.json", "es.json", "lo.json"

Pros Cons
Keeping all the translations in one location makes updating translations and adding new languages/translations easier in the future Every time a new mode/purpose is added for any given program, the phone code will need to be updated to reflect that because "en.json" is by default located within the e-mission-phone code
There is less copying of code, since without this for every program/study using dynamic labels (label_options URL in config), there will be the same chunk of code for the english translations since we test in english (see code block below) Essentially, it would be better if the translations whether we use default label-options or dynamic label-options come from the same place Every time a new mode/purpose is added for any given program, all of the i18n translation json files will need to be updated to reflect that new mode
If there is a study/program in the future that needs one of the translations that is not in use in the default label-options, but is used in a different dynamic label-options, it will be very easy to implement. E.g. Lao uses "rickshaw" which nowhere else currently uses. But let's say that a program in the future wants to measure rickshaw travel data to/from the Rockies baseball games in Denver. We already have the infrastructure to support the translations in this case. There will be translations for modes that may not exist in every program (for example, rickshaw will have an "en.json" translation, but most programs and studies that don't use "usaid-laos-ev-label-options.json" or any other label options that have rickshaw listed as a mode of transportation)

Every dynamic label-options file, including the default label-options file has the english translations...

"translations": {
    "en": {
        "walk": "Walk",
        
    },
    
}

Compare the default label-options file e-mission-phone/www/json/label-options.json.sample to a dynamic label-options file nrel-openpath-deploy-configs/label-options/usaid-laos-ev-label-options.json...

label-options.json.sample
{
  "MODE": [
    {"value":"walk", "baseMode":"WALKING", "met_equivalent":"WALKING", "kgCo2PerKm": 0},
    {"value":"e-bike", "baseMode":"E_BIKE", "met": {"ALL": {"range": [0, -1], "mets": 4.9}}, "kgCo2PerKm": 0.00728},
    {"value":"bike", "baseMode":"BICYCLING", "met_equivalent":"BICYCLING", "kgCo2PerKm": 0},
    {"value":"bikeshare", "baseMode":"BICYCLING", "met_equivalent":"BICYCLING", "kgCo2PerKm": 0},
    {"value":"scootershare", "baseMode":"E_SCOOTER", "met_equivalent":"IN_VEHICLE", "kgCo2PerKm": 0.00894},
    {"value":"drove_alone", "baseMode":"CAR", "met_equivalent":"IN_VEHICLE", "kgCo2PerKm": 0.22031},
    {"value":"shared_ride", "baseMode":"CAR", "met_equivalent":"IN_VEHICLE", "kgCo2PerKm": 0.11015},
    {"value":"e_car_drove_alone", "baseMode":"E_CAR", "met_equivalent":"IN_VEHICLE", "kgCo2PerKm": 0.08216},
    {"value":"e_car_shared_ride", "baseMode":"E_CAR", "met_equivalent":"IN_VEHICLE", "kgCo2PerKm": 0.04108},
    {"value":"moped", "baseMode":"MOPED", "met_equivalent":"IN_VEHICLE", "kgCo2PerKm": 0.05555},
    {"value":"taxi", "baseMode":"TAXI", "met_equivalent":"IN_VEHICLE", "kgCo2PerKm": 0.30741},
    {"value":"bus", "baseMode":"BUS", "met_equivalent":"IN_VEHICLE", "kgCo2PerKm": 0.20727},
    {"value":"train", "baseMode":"TRAIN", "met_equivalent":"IN_VEHICLE", "kgCo2PerKm": 0.12256},
    {"value":"free_shuttle", "baseMode":"BUS", "met_equivalent":"IN_VEHICLE", "kgCo2PerKm": 0.20727},
    {"value":"air", "baseMode":"AIR", "met_equivalent":"IN_VEHICLE", "kgCo2PerKm": 0.09975},
    {"value":"not_a_trip", "baseMode":"UNKNOWN", "met_equivalent":"UNKNOWN", "kgCo2PerKm": 0},
    {"value":"other", "baseMode":"OTHER", "met_equivalent":"UNKNOWN", "kgCo2PerKm": 0}
  ],
  "PURPOSE": [
    {"value":"home"},
    {"value":"work"},
    {"value":"at_work"},
    {"value":"school"},
    {"value":"transit_transfer"},
    {"value":"shopping"},
    {"value":"meal"},
    {"value":"pick_drop_person"},
    {"value":"pick_drop_item"},
    {"value":"personal_med"},
    {"value":"access_recreation"},
    {"value":"exercise"},
    {"value":"entertainment"},
    {"value":"religious"},
    {"value":"other"}
  ],
  "REPLACED_MODE": [
    {"value":"no_travel"},
    {"value":"walk"},
    {"value":"bike"},
    {"value":"bikeshare"},
    {"value":"scootershare"},
    {"value":"drove_alone"},
    {"value":"shared_ride"},
    {"value":"e_car_drove_alone"},
    {"value":"e_car_shared_ride"},
    {"value":"taxi"},
    {"value":"bus"},
    {"value":"train"},
    {"value":"free_shuttle"},
    {"value":"other"}
  ],
  "translations": {
    "en": {
      "walk": "Walk",
      "e-bike": "E-bike",
      "bike": "Regular Bike",
      "bikeshare": "Bikeshare",
      "scootershare": "Scooter share",
      "drove_alone": "Gas Car Drove Alone",
      "shared_ride": "Gas Car Shared Ride",
      "e_car_drove_alone": "E-Car Drove Alone",
      "e_car_shared_ride": "E-Car Shared Ride",
      "moped": "Moped",
      "taxi": "Taxi/Uber/Lyft",
      "bus": "Bus",
      "train": "Train",
      "free_shuttle": "Free Shuttle",
      "air": "Air",
      "not_a_trip": "Not a trip",
      "no_travel": "No travel",
      "home": "Home",
      "work": "To Work",
      "at_work": "At Work",
      "school": "School",
      "transit_transfer": "Transit transfer",
      "shopping": "Shopping",
      "meal": "Meal",
      "pick_drop_person": "Pick-up/ Drop off Person",
      "pick_drop_item": "Pick-up/ Drop off Item",
      "personal_med": "Personal/ Medical",
      "access_recreation": "Access Recreation",
      "exercise": "Recreation/ Exercise",
      "entertainment": "Entertainment/ Social",
      "religious": "Religious",
      "other": "Other"
    },
    "es": {
      "walk": "Caminando",
      "e-bike": "e-bicicleta",
      "bike": "Bicicleta",
      "bikeshare": "Bicicleta compartida",
      "scootershare": "Motoneta compartida",
      "drove_alone": "Coche de Gas, Condujo solo",
      "shared_ride": "Coche de Gas, Condujo con otros",
      "e_car_drove_alone": "e-coche, Condujo solo",
      "e_car_shared_ride": "e-coche, Condujo con ontras",
      "moped": "Ciclomotor",
      "taxi": "Taxi/Uber/Lyft",
      "bus": "Autobús",
      "train": "Tren",
      "free_shuttle": "Colectivo gratuito",
      "air": "Avión",
      "not_a_trip": "No es un viaje",
      "no_travel": "No viajar",
      "home": "Inicio",
      "work": "Trabajo",
      "at_work": "En el trabajo",
      "school": "Escuela",
      "transit_transfer": "Transbordo",
      "shopping": "Compras",
      "meal": "Comida",
      "pick_drop_person": "Recoger/ Entregar Individuo",
      "pick_drop_item": "Recoger/ Entregar Objeto",
      "personal_med": "Personal/ Médico",
      "access_recreation": "Acceder a Recreación",
      "exercise": "Recreación/ Ejercicio",
      "entertainment": "Entretenimiento/ Social",
      "religious": "Religioso",
      "other": "Otros"
    }
  }
}
usaid-laos-ev-label-options.json
{
    "MODE": [
      {"value":"walk", "baseMode":"WALKING", "met_equivalent":"WALKING", "kgCo2PerKm": 0},
      {"value":"e-auto_rickshaw", "baseMode":"MOPED", "met_equivalent":"IN_VEHICLE", "kgCo2PerKm": 0.085416859},
      {"value":"auto_rickshaw", "baseMode":"MOPED", "met_equivalent":"IN_VEHICLE", "kgCo2PerKm": 0.231943784},
      {"value":"motorcycle", "baseMode":"MOPED", "met_equivalent":"IN_VEHICLE", "kgCo2PerKm": 0.113143309},
      {"value":"e-bike", "baseMode":"E_BIKE", "met": {"ALL": {"range": [0, -1], "mets": 4.9}}, "kgCo2PerKm": 0.00728},
      {"value":"bike", "baseMode":"BICYCLING", "met_equivalent":"BICYCLING", "kgCo2PerKm": 0},
      {"value":"drove_alone", "baseMode":"CAR", "met_equivalent":"IN_VEHICLE", "kgCo2PerKm": 0.22031},
      {"value":"shared_ride", "baseMode":"CAR", "met_equivalent":"IN_VEHICLE", "kgCo2PerKm": 0.11015},
      {"value":"e_car_drove_alone", "baseMode":"E_CAR", "met_equivalent":"IN_VEHICLE", "kgCo2PerKm": 0.08216},
      {"value":"e_car_shared_ride", "baseMode":"E_CAR", "met_equivalent":"IN_VEHICLE", "kgCo2PerKm": 0.04108},
      {"value":"taxi", "baseMode":"TAXI", "met_equivalent":"IN_VEHICLE", "kgCo2PerKm": 0.30741},
      {"value":"bus", "baseMode":"BUS", "met_equivalent":"IN_VEHICLE", "kgCo2PerKm": 0.20727},
      {"value":"train", "baseMode":"TRAIN", "met_equivalent":"IN_VEHICLE", "kgCo2PerKm": 0.12256},
      {"value":"free_shuttle", "baseMode":"BUS", "met_equivalent":"IN_VEHICLE", "kgCo2PerKm": 0.20727},
      {"value":"air", "baseMode":"AIR", "met_equivalent":"IN_VEHICLE", "kgCo2PerKm": 0.09975},
      {"value":"not_a_trip", "baseMode":"UNKNOWN", "met_equivalent":"UNKNOWN", "kgCo2PerKm": 0},
      {"value":"other", "baseMode":"OTHER", "met_equivalent":"UNKNOWN", "kgCo2PerKm": 0}
    ],
    "PURPOSE": [
      {"value":"home"},
      {"value":"work"},
      {"value":"at_work"},
      {"value":"school"},
      {"value":"transit_transfer"},
      {"value":"shopping"},
      {"value":"meal"},
      {"value":"pick_drop_person"},
      {"value":"pick_drop_item"},
      {"value":"personal_med"},
      {"value":"access_recreation"},
      {"value":"exercise"},
      {"value":"entertainment"},
      {"value":"religious"},
      {"value":"other"}
    ],
    "translations": {
      "en": {
        "walk": "Walk",
        "e-auto_rickshaw":"E-tuk tuk",
        "auto_rickshaw":"Tuk Tuk",
        "motorcycle":"Motorcycle",
        "e-bike": "E-bike",
        "bike": "Bicycle",
        "drove_alone": "Car Drove Alone",
        "shared_ride": "Car Shared Ride",
        "e_car_drove_alone": "E-Car Drove Alone",
        "e_car_shared_ride": "E-Car Shared Ride",
        "taxi": "Taxi/Loca/inDrive",
        "bus": "Bus",
        "train": "Train",
        "free_shuttle": "Free Shuttle",
        "air": "Airplane",
        "not_a_trip": "Not a trip",
        "home": "Home",
        "work": "To Work",
        "at_work": "At Work",
        "school": "School",
        "transit_transfer": "Transit transfer",
        "shopping": "Shopping",
        "meal": "Meal",
        "pick_drop_person": "Pick-up/ Drop off Person",
        "pick_drop_item": "Pick-up/ Drop off Item",
        "personal_med": "Personal/ Medical",
        "access_recreation": "Access Recreation",
        "exercise": "Recreation/ Exercise",
        "entertainment": "Entertainment/ Social",
        "religious": "Religious",
        "other": "Other"
      },
      "lo": {
        "walk": "ດ້ວຍການຍ່າງ",
        "e-auto_rickshaw":"ລົດ 3 ລໍ້ໄຟຟ້າ ຫລື ຕຸກຕຸກໄຟຟ້າ",
        "auto_rickshaw":"ເດີນທາດ້ວຍ ລົດຕຸກຕຸກ ຫລື ລົດສາມລໍ້",
        "motorcycle":"ລົດຈັກ",
        "e-bike": "ວຍລົດຈັກໄຟຟ້າ",
        "bike": "ລົດຖີບ",
        "drove_alone": "ເດີນທາງ ດ້ວຍລົດໃຫ່ຍ ເຊີ່ງເປັນລົດທີ່ຂັບເອງ",
        "shared_ride": "ເດີນທາງດ້ວຍລົດໃຫ່ຍ ຮ່ວມກັບລົດຄົນອຶ່ນ",
        "e_car_drove_alone": "ດ້ວຍການຂັບລົດໄຟຟ້າໄປເອງ",
        "e_car_shared_ride": "ດ້ວຍການຈ້າງລົດໄຟຟ້າໄປ",
        "taxi": "ແທັກຊີ",
        "bus": "ລົດເມ",
        "train": "ລົດໄຟ",
        "free_shuttle": "ລົດຮັບສົ່ງຟຣີ",
        "air": "ຍົນ",
        "not_a_trip": "ບໍ່ແມ່ນການເດີນທາງ",
        "home": "ບ້ານ",
        "work": "ໄປເຮັດວຽກ",
        "at_work": "ຢູ່ບ່ອນເຮັດວຽກ",
        "school": "ໄປໂຮງຮຽນ",
        "transit_transfer": "ການຖ່າຍໂອນການເດີນທາງ",
        "shopping": "ຊອບປິ້ງ",
        "meal": "ອາຫານ",
        "pick_drop_person": "ໄປຮັບ ຫລື ສົນ ຄົນ",
        "pick_drop_item": "ໄປຮັບ ຫລື ສົ່ງສິນຄ້າ",
        "personal_med": "ໄປຫາໝໍ",
        "access_recreation": "ເຂົ້າເຖິງການພັກຜ່ອນ",
        "exercise": "ພັກຜ່ອນ/ອອກກຳລັງກາຍ",
        "entertainment": "ບັນເທີງ/ສັງຄົມ",
        "religious": "ຈຸດປະສົງທາງສາດສະໜາ",
        "other": "ອື່ນໆ"
      }
    }
  }

@shankari
Copy link
Contributor

shankari commented Oct 10, 2023

@sebastianbarry

Every time a new mode/purpose is added for any given program, the phone code will need to be updated to reflect that because "en.json" is by default located within the e-mission-phone code

I meant, "can you come up with a solution that doesn't require changing the phone code".
I see your points about reuse of modes, but people change the options all the time - Laos has changed the options at least 3 times already and might want to change it again. We cannot be changing the phone code every single time that happens.

There are other places where we want to unify the handling of modes (notably the public dashboard calculations being tracked in e-mission/em-public-dashboard#89) and we will be revisiting this when we include energy calculations in the app dashboard.

So I would suggest filing a new issue for the re-design and discussing solutions there as part of a bigger rewrite/refactor in the future.

@sebastianbarry
Copy link
Contributor Author

Created e-mission/e-mission-docs#1007 and marking this PR as ready for review for the next wave of reviews @shankari

@sebastianbarry
Copy link
Contributor Author

Closing this PR in favor of #1065

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants