Quad-Question - Edit
In the doctor's app, add a new question type to the question edit modal, allowing the user to quickly setup a question with exactly 4 answer options at values 0,1,2 and 3.
How to find the right place in the UI where this is relevant
Open the doctor's app. Click 'Start new session' at the home screen. Select any template, Click 'Add custom Question', click 'Question Type'. You'll be prompted with a list of available question types. (Browse them to get an idea of how they work). This list should include a new item, when this task is done.
What are question types and why the need for another one?
Question types are forms (implemented as WidgetComponents, see the Docs on Widgets) that allow the configuration of a QuestionConfig. Some question types / QuestionEditWidgets already exist in /lib/features/src/basic-question-edit-widgets
The QuestionConfig interface is declared in /lib/core/src/items/questions/questions.commons.ts
There is one special QuestionEditWidget – GenericQuestionEditWidgetComponent – that is used as Fallback. It can handle everything related to editing a QuestionConfig, but comes with a a rather large and complicated form.
All other QuestionEditWidgets are meant to have simpler less powerful forms that only produce certain kinds of QuestionConfigs. For example: ChoiceQuestionEditWidgetComponent can only configure questions that have preconfigured answer options. Users can add and remove options and set an answer type (integer, decimal or string). (And of course change the wording).
ScaleQuestionEditWidgetComponent on the other hand only supports numerical questions, asks for min and max values and adds a tag to the QuestionConfig that lets other parts of the app know that a scale/slider should be displayed when the user answers the question.
What is a QuadQuestion supposed to do?
A Quad-Question (needs a better name) is a QuestionConfig that has exactly four predefined answer options at values 0,1,2,3 (all numbers). The user should only be able to change the wording of the question and the labels for these 4 values. They should not be able to change the values, add or remove options. The answerType is fixed to 'integer'.
All of the curated question we deliver with the doctor's app are of this kind. That's why they are important. And sooner or later they will get a special treatmeant when displayed to be answered (i.e. four tiles instead of a list).
Requirements/Tasks
-
Create a new module at /lib/features/src -
All changes should apply, when adding the module to /app/generic/src/doc/features.module.ts -
Do not change files outside your module; if that is not doable we need another task to make it possible :D -
When the user edits a question, they should be able to choose the new question type. ('Quad Question' for now, still needs translation) -
When a question was "stored as" the new type, the new type should be the first in the list, when the same question is edited again. -
Add translation data to the new module (see provideTranslationMap) -
Take notes where better documentation would have been helpful in order to close this issue
Where to start
Take a look at ChoiceQuestionEditWidgetComponent in /lib/features/src/basic-question-edit-widgets/choice – this QuestionEditWidget is already very close to what we need here. Modifying a copy of this Component will most likely already do the trick. The drawback with this Component is that it extends GenericQuestionEditWidgetComponent. So in order to understand what ChoiceQuestionEditWidgetComponent does, you have to dig through the most complicated QuestionEditwidget of them all. The most part of what ChoiceQuestionEditWidgetComponent does is restrict the options/complexity of GenericQuestionEditWidgetComponent.
Still worth a look :D
If you do not extend GenericQuestionEditWidgetComponent, extend WidgetComponent<QuestionEditControl> instead.
In order to add the new QuadQuestionEditWidgetComponent (or something with a better name) to the app use provideWidget the way it is done in /lib/features/src/basic-question-edit-widgets/basic-question-edit-widgets.module.ts Add 'provideWidget(QuadQuestionEditWidgetComponent)' to the providers array of your module.
Each WidgetEditComponet will be injected with QuestionEditControl.
Read QuestionEditControl.questionConfig to get the current state of the config to be edited. When creating a new question this config will be rather barren, but will otherwise be populated with data if it is a question to be edited or if another QuestionEditWidget already put some data in.
Reading data from the .questionConfig serves two purposes:
- Determine how well suited the new QuestionEditWidget is for the question that is to be edited. (In this case, check if it has exactly 4 answer options...). This should be done in the static method QuadQuestionEditWidgetComponent#widgetMatch(). Note: never return -1 here for this kind of Widget. The user can forcibly choose a question type that is incompatible with the data currently present on the question (and with it change the question type). Returning -1 would hide the new question type. Return 0 instead.
- Prefill form inputs with data that is already available.
Setting .questionConfig will change/edit the Question and update the preview or output errors if need be. Always set .questionConfig as a whole; Do not set sub properties like .questionConfig.meaning. (Maybe needs refactoring on my part :D) (Note: Changes will only really take effect after the user clicked 'apply')
The second important property of QuestionEditControl is QuestionEditControl.editForms. This property is used to transfer form errors out of the current Component. It can be any AbstractForm, i.e. a FormArray. Just add all forms that might have input errors (or just all of them) to one FormArray set .editForms to this value and another part of the App will handle displaying the errors. Allways set this propery as a whole. (Maybe needs refactoring on my part) If possible set .editForms in the constructor right away, and with it override the the set of forms the previous QuestionEditWidget might have used.