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

Build UI for the Android NPS Survey #4881

Closed
adhiamboperes opened this issue Feb 22, 2023 · 0 comments · Fixed by #4945
Closed

Build UI for the Android NPS Survey #4881

adhiamboperes opened this issue Feb 22, 2023 · 0 comments · Fixed by #4945
Assignees
Labels
enhancement End user-perceivable enhancements. Impact: High High perceived user impact (breaks a critical feature or blocks a release). Work: High It's not clear what the solution is.

Comments

@adhiamboperes
Copy link
Collaborator

adhiamboperes commented Feb 22, 2023

Screens

Link to Mocks

a Required screens
1 Survey onboarding screen
2 Survey Multiple Choice Questions with ‘other option’ screen
3 Multiple Choice Question screen
4 Survey NPS question screen
5 Survey open-ended question screen
6 Survey thank you screen
7 Exit survey confirmation screen

This issue also tracks the databinding of these views

@adhiamboperes adhiamboperes self-assigned this Feb 22, 2023
@adhiamboperes adhiamboperes added Impact: High High perceived user impact (breaks a critical feature or blocks a release). Work: High It's not clear what the solution is. work label added labels May 3, 2023
@seanlip seanlip added enhancement End user-perceivable enhancements. and removed Type: Improvement labels Jun 16, 2023
adhiamboperes added a commit that referenced this issue Jul 7, 2023
## Explanation
Fixes #4881.

This is PR 3 of 6 that adds the UI for the NPS survey as well as
completes the [key user
flows](https://docs.google.com/document/d/1aIr7cu7V5-9uvhfDgekq-iOXF57hbxEmjiL3mElly0I/edit#heading=h.rkqdyq11md2s).

### Layouts Introduced

#### Main Layouts
- Survey intro 
- Survey fragment for displaying the questions
- Exit confirmation dialog
- Thank you screen

#### Technical decisions
I used the `BindableAdapter.MultiTypeBuilder` from within the fragment
to populate the views. This allowed me to reuse the survey question
layout while creating individual layouts for each answer option group.

I created a viewmodel hierachy where:

- The root fragment viewmodel is responsible for retrieving the correct
question text, making the decision to allow navigation to the next
question by enabling/disabling the next button based on selected answer
availability, and updating the progressbar percentage and progress.
- For the answer option layouts, I created a Super-class,
`SurveyAnswerItemViewModel` for representing the different types of
different layouts that can exist for the recyclerView responsible for
displaying these views.
- Each question option layout has it's own viewmodel that is responsible
for retrieving the answer options to display from the app strings file,
notifying that an answer has been provided, and retrieving the selected
answer for handling.

I used view binding to display all the strings and control navigation.

I also created custom views where using regular views proved to be
complex to work with.

#### Custom Views
- SurveyOnboardingBackgroundView - for creating the custom background
needed on the intro and outro layouts
- SurveyMultipleChoiceOptionView - for binding lists in multiple choice
questions
- SurveyNpsItemOptionView - for binding the custom layout needed for the
NPS score question

### Navigation and Progress
I found it difficult to decouple the UI development work from the
progress work, since the survey and the questions are generated
dynaically so I needed to develop both in tandem.

The following changes pertain to the core survey logic:
#### SurveyController
Creates a survey with a list of questions.

#### SurveyProgressController
Tracks the non-persisted progress of a survey and is responsible for
handling the survey session, managing the commands for navigating
through and answer submission.

I opted to use a command pattern similar to what is used in the
[ExplorationProgressController](https://github.com/oppia/oppia-android/blob/develop/domain/src/main/java/org/oppia/android/domain/exploration/ExplorationProgressController.kt).

#### Navigation
The survey can be viewed as a series of linear questions, which we will
navigate through using methods defined in the SurveyQuestionDeck,
modeled after the
[StateDeck](https://github.com/oppia/oppia-android/blob/develop/domain/src/main/java/org/oppia/android/domain/state/StateDeck.kt).
To start with, we will create an EphemeralSurveyQuestion which
represents the question the user is currently viewing. It contains a
reference to the next and previous questions if applicable, and a
reference to whether it is the last question in the deck. The
SurveyQuestionDeck will define the conditions for navigating to the
previous and next questions as well as the exceptions thrown in case a
navigation action is invalid.

A SurveyQuestionGraph class will be created to provide functionality for
processing the behavior of a ‘next’ navigation action, which evaluates
which question is shown next.

### Survey Proto Changes:
- Refactored the order of the enum items in the `UserTypeAnswer` enum so
that they result into a properly indexed options list per the mocks.
- Modified the `EphemeralSurveyQuestion` to have a
`current_question_index` and a `total_question_count` to make it easy to
compute the survey progress.
- Added answer typecase `free_form_answer` to the `SurveySelectedAnswer`
message to hold the value of a free text response.
- Added ` SurveyQuestion optional_question = 3;` field to the survey so
that we have a clear seperation between the mandatory and optional
questions. This also supports the survey generation architecture.

### Bazel
Created `BUILD` definitions for all new classes and tests.

### Dagger
I changed [approximately 150 test
files](https://pbs.twimg.com/media/EAeaeOnU4AcXRQw.jpg) to include
`SurveyQuestionModule::class`, though I removed it in a subsequent
refactor. When I removed the module and it's usages, it was not a very
clean revert because some of the files were not properly formatted
before, but they are now -- hence some test files here with only
formatting changes.

### Usages, Future Work and Out of Scope
The domain layer of the survey is pretty much flexible to support any
survey question, including should the current list be reordered or the
number of questions changed. For example, if we wanted to show a
subsequent survey on the same profile:

####  Show One Question Only
We would be able to show only one question if we only passed that one
question name to the list in the `startSurveySession()` function. We
would also need to set `showOptionalQuestion` to false, to disable
adding the free-form question to the survey. This is otherwise created
by default as `showOptionalQuestion` is always true otherwise.

Further work would need to be done in the UI to to update the navigation
button behaviour, i.e currently the button will show next instead of
submit, and to ensure the submit answer functionality works to exit
survey once the one answer has been submitted.

#### Show Two or More Questions
We could for example want to show only the NPS score question and the
feedback question. We would need to pass in the NPS question's name as
an input to the `startSurveySession()` function. The feedback question
name never needs to be explicitly passed since we create a default
(promoter) question and typically update the actual question based on
the NPS score.

The UI currently supports this scenario.

#### Add More Question Types
The domain layer would be able to handle any question types, but the UI
will need to be updated to display this question by creating a new
layout, and viewmodel for it, as well as updating the
`SurveyAnswerItemViewModel`'s `ViewType` enum with this new viewType(s).

A more longterm solution for a dynamic UI would be to create
standardized survey questions and answer options, pretty much like
state/exploration interactions.

## Essential Checklist
<!-- Please tick the relevant boxes by putting an "x" in them. -->
- [x] The PR title and explanation each start with "Fix #bugnum: " (If
this PR fixes part of an issue, prefix the title with "Fix part of
#bugnum: ...".)
- [x] Any changes to
[scripts/assets](https://github.com/oppia/oppia-android/tree/develop/scripts/assets)
files have their rationale included in the PR explanation.
- [x] The PR follows the [style
guide](https://github.com/oppia/oppia-android/wiki/Coding-style-guide).
- [x] The PR does not contain any unnecessary code changes from Android
Studio
([reference](https://github.com/oppia/oppia-android/wiki/Guidance-on-submitting-a-PR#undo-unnecessary-changes)).
- [x] The PR is made from a branch that's **not** called "develop" and
is up-to-date with "develop".
- [x] The PR is **assigned** to the appropriate reviewers
([reference](https://github.com/oppia/oppia-android/wiki/Guidance-on-submitting-a-PR#clarification-regarding-assignees-and-reviewers-section)).

## For UI-specific PRs only
If your PR includes UI-related changes, then:
- Add screenshots for portrait/landscape for both a tablet & phone of
the before & after UI changes
- For the screenshots above, include both English and pseudo-localized
(RTL) screenshots (see [RTL guide]

| LTR  | RTL |   
|---|---|

|https://github.com/oppia/oppia-android/assets/59600948/d2411422-aa99-482d-a0e7-c6fd163e85e1|
https://github.com/oppia/oppia-android/assets/59600948/329e0672-8d4c-4f43-8c6c-b9036a78980a|
|Updated LTR video with restored answers|

|https://github.com/oppia/oppia-android/assets/59600948/1a0decff-7dbf-4a6a-a225-5f38f4191fd6|
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement End user-perceivable enhancements. Impact: High High perceived user impact (breaks a critical feature or blocks a release). Work: High It's not clear what the solution is.
Development

Successfully merging a pull request may close this issue.

2 participants