Skip to content

Commit

Permalink
Help button workflow (#1697)
Browse files Browse the repository at this point in the history
* help button workflow in catalog app.

* differentiate widgets and misc components header section.

* Move component help icon to catalog res folder.

* add new line to end of the file of questionnaire json

* Address review comments.

Co-authored-by: Santosh Pingle <[email protected]>
Co-authored-by: Omar Ismail <[email protected]>
Co-authored-by: Jing Tang <[email protected]>
  • Loading branch information
4 people committed Dec 4, 2022
1 parent 9f3fc87 commit 17e704e
Show file tree
Hide file tree
Showing 8 changed files with 220 additions and 28 deletions.
79 changes: 79 additions & 0 deletions catalog/src/main/assets/component_help.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
{
"resourceType": "Questionnaire",
"item": [
{
"linkId": "1",
"text": "Question title",
"type": "choice",
"extension": [
{
"url": "http:https://hl7.org/fhir/StructureDefinition/questionnaire-itemControl",
"valueCodeableConcept": {
"coding": [
{
"system": "http:https://hl7.org/fhir/questionnaire-item-control",
"code": "radio-button",
"display": "Radio Button"
}
]
}
}
],
"answerOption": [
{
"valueCoding": {
"display": "Yes"
}
},
{
"valueCoding": {
"display": "No"
}
},
{
"valueCoding": {
"display": "Unknown"
}
}
],
"item": [
{
"extension": [
{
"url": "http:https://hl7.org/fhir/StructureDefinition/questionnaire-displayCategory",
"valueCodeableConcept": {
"coding": [
{
"system": "http:https://hl7.org/fhir/questionnaire-display-category",
"code": "instructions"
}
]
}
}
],
"linkId": "1.3",
"text": "Select one",
"type": "display"
},
{
"extension": [
{
"url": "http:https://hl7.org/fhir/StructureDefinition/questionnaire-itemControl",
"valueCodeableConcept": {
"coding": [
{
"system": "http:https://hl7.org/fhir/questionnaire-item-control",
"code": "help"
}
]
}
}
],
"linkId": "1.3",
"text": "Only one answer can be selected. If none apply, skip the question.",
"type": "display"
}
]
}
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,24 @@ class ComponentListFragment : Fragment(R.layout.component_list_fragment) {

private fun setUpComponentsRecyclerView() {
val adapter =
ComponentsRecyclerViewAdapter(::onItemClick).apply {
submitList(viewModel.getComponentList())
}
val recyclerView = requireView().findViewById<RecyclerView>(R.id.componentsRecyclerView)
recyclerView.adapter = adapter
recyclerView.layoutManager = GridLayoutManager(requireContext(), 2)
ComponentsRecyclerViewAdapter(::onItemClick).apply { submitList(viewModel.viewItemList) }
with(requireView().findViewById<RecyclerView>(R.id.componentsRecyclerView)) {
this.adapter = adapter
layoutManager =
GridLayoutManager(requireContext(), ComponentsRecyclerViewAdapter.ViewType.HEADER.spanCount)
.apply {
spanSizeLookup =
object : GridLayoutManager.SpanSizeLookup() {
override fun getSpanSize(position: Int): Int {
return if (adapter.getItemViewType(position) ==
ComponentsRecyclerViewAdapter.ViewType.HEADER.ordinal
)
ComponentsRecyclerViewAdapter.ViewType.HEADER.spanCount
else ComponentsRecyclerViewAdapter.ViewType.ITEM.spanCount
}
}
}
}
}

private fun onItemClick(component: ComponentListViewModel.Component) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,14 @@ import androidx.lifecycle.SavedStateHandle
class ComponentListViewModel(application: Application, private val state: SavedStateHandle) :
AndroidViewModel(application) {

fun getComponentList(): List<Component> {
return Component.values().toList()
sealed class ViewItem {
data class HeaderItem(val header: Header) : ViewItem()
data class ComponentItem(val component: Component) : ViewItem()
}

enum class Header(@StringRes val textId: Int) {
WIDGETS(R.string.widgets),
MISC_COMPONENTS(R.string.misc_components)
}

enum class Component(
Expand Down Expand Up @@ -95,6 +101,7 @@ class ComponentListViewModel(application: Application, private val state: SavedS
"component_date_time_picker.json",
"component_date_time_picker_with_validation.json"
),

// TODO https://github.com/google/android-fhir/issues/1260
// SLIDER(
// R.drawable.ic_slider,
Expand All @@ -114,5 +121,25 @@ class ComponentListViewModel(application: Application, private val state: SavedS
R.string.component_name_repeated_group,
"component_repeated_group.json",
),
HELP(R.drawable.ic_help, R.string.component_name_help, "component_help.json")
}

val viewItemList =
listOf(
ViewItem.HeaderItem(Header.WIDGETS),
ViewItem.ComponentItem(Component.BOOLEAN_CHOICE),
ViewItem.ComponentItem(Component.SINGLE_CHOICE),
ViewItem.ComponentItem(Component.MULTIPLE_CHOICE),
ViewItem.ComponentItem(Component.DROPDOWN),
ViewItem.ComponentItem(Component.MODAL),
ViewItem.ComponentItem(Component.OPEN_CHOICE),
ViewItem.ComponentItem(Component.TEXT_FIELD),
ViewItem.ComponentItem(Component.DATE_PICKER),
ViewItem.ComponentItem(Component.DATE_TIME_PICKER),
ViewItem.ComponentItem(Component.IMAGE),
ViewItem.ComponentItem(Component.AUTO_COMPLETE),
ViewItem.ComponentItem(Component.REPEATED_GROUP),
ViewItem.HeaderItem(Header.MISC_COMPONENTS),
ViewItem.ComponentItem(Component.HELP),
)
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2021 Google LLC
* Copyright 2022 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -21,43 +21,81 @@ import android.view.ViewGroup
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import com.google.android.fhir.catalog.databinding.ComponentHeaderLayoutBinding
import com.google.android.fhir.catalog.databinding.LandingPageItemBinding

class ComponentsRecyclerViewAdapter(
private val onItemClick: (ComponentListViewModel.Component) -> Unit
) : ListAdapter<ComponentListViewModel.Component, ComponentListViewHolder>(ComponentDiffUtil()) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ComponentListViewHolder {
return ComponentListViewHolder(
LandingPageItemBinding.inflate(LayoutInflater.from(parent.context), parent, false),
onItemClick
)
) : ListAdapter<ComponentListViewModel.ViewItem, RecyclerView.ViewHolder>(ComponentDiffUtil()) {

enum class ViewType(val spanCount: Int) {
HEADER(2),
ITEM(1)
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return when (viewType) {
ViewType.HEADER.ordinal ->
ComponentHeaderViewHolder(
ComponentHeaderLayoutBinding.inflate(LayoutInflater.from(parent.context), parent, false)
)
ViewType.ITEM.ordinal ->
ComponentListViewHolder(
LandingPageItemBinding.inflate(LayoutInflater.from(parent.context), parent, false),
onItemClick
)
else -> throw IllegalArgumentException("$viewType must be ViewType.")
}
}

override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
if (holder is ComponentViewHolder) {
holder.bind(getItem(position))
}
}

override fun onBindViewHolder(holder: ComponentListViewHolder, position: Int) {
holder.bind(getItem(position))
override fun getItemViewType(position: Int): Int {
return when (getItem(position)) {
is ComponentListViewModel.ViewItem.HeaderItem -> ViewType.HEADER.ordinal
is ComponentListViewModel.ViewItem.ComponentItem -> ViewType.ITEM.ordinal
}
}
}

interface ComponentViewHolder {
fun bind(component: ComponentListViewModel.ViewItem)
}

class ComponentListViewHolder(
private val binding: LandingPageItemBinding,
private val onItemClick: (ComponentListViewModel.Component) -> Unit
) : RecyclerView.ViewHolder(binding.root) {
fun bind(component: ComponentListViewModel.Component) {
binding.componentLayoutIconImageview.setImageResource(component.iconId)
) : RecyclerView.ViewHolder(binding.root), ComponentViewHolder {
override fun bind(component: ComponentListViewModel.ViewItem) {
val componentItem = component as ComponentListViewModel.ViewItem.ComponentItem
binding.componentLayoutIconImageview.setImageResource(componentItem.component.iconId)
binding.componentLayoutTextView.text =
binding.componentLayoutTextView.context.getString(component.textId)
binding.root.setOnClickListener { onItemClick(component) }
binding.componentLayoutTextView.context.getString(componentItem.component.textId)
binding.root.setOnClickListener { onItemClick(component.component) }
}
}

class ComponentHeaderViewHolder(private val binding: ComponentHeaderLayoutBinding) :
RecyclerView.ViewHolder(binding.root), ComponentViewHolder {
override fun bind(viewItem: ComponentListViewModel.ViewItem) {
val headerItem = viewItem as ComponentListViewModel.ViewItem.HeaderItem
binding.tvComponentHeader.text =
binding.tvComponentHeader.context.getString(headerItem.header.textId)
}
}

class ComponentDiffUtil : DiffUtil.ItemCallback<ComponentListViewModel.Component>() {
class ComponentDiffUtil : DiffUtil.ItemCallback<ComponentListViewModel.ViewItem>() {
override fun areItemsTheSame(
oldComponent: ComponentListViewModel.Component,
newComponent: ComponentListViewModel.Component
oldComponent: ComponentListViewModel.ViewItem,
newComponent: ComponentListViewModel.ViewItem
) = oldComponent === newComponent

override fun areContentsTheSame(
oldComponent: ComponentListViewModel.Component,
newComponent: ComponentListViewModel.Component
oldComponent: ComponentListViewModel.ViewItem,
newComponent: ComponentListViewModel.ViewItem
) = oldComponent == newComponent
}
13 changes: 13 additions & 0 deletions catalog/src/main/res/drawable/ic_help.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<vector
android:autoMirrored="true"
android:height="128dp"
android:viewportHeight="128"
android:viewportWidth="194"
android:width="194dp"
xmlns:android="http:https://schemas.android.com/apk/res/android"
>
<path
android:fillColor="#1A73E8"
android:pathData="M97.267,79.533C97.978,79.533 98.578,79.289 99.067,78.8C99.555,78.311 99.8,77.711 99.8,77C99.8,76.289 99.555,75.689 99.067,75.2C98.578,74.711 97.978,74.467 97.267,74.467C96.555,74.467 95.955,74.711 95.467,75.2C94.978,75.689 94.733,76.289 94.733,77C94.733,77.711 94.978,78.311 95.467,78.8C95.955,79.289 96.555,79.533 97.267,79.533ZM94.933,69.8H98.867C98.867,68.644 99,67.6 99.267,66.667C99.578,65.689 100.489,64.578 102,63.333C103.378,62.178 104.356,61.044 104.933,59.933C105.511,58.822 105.8,57.6 105.8,56.267C105.8,53.911 105.022,52.022 103.467,50.6C101.956,49.178 99.933,48.467 97.4,48.467C95.222,48.467 93.289,49.022 91.6,50.133C89.955,51.2 88.756,52.689 88,54.6L91.533,55.933C92.022,54.689 92.756,53.733 93.733,53.067C94.711,52.355 95.867,52 97.2,52C98.711,52 99.933,52.422 100.867,53.267C101.8,54.067 102.267,55.111 102.267,56.4C102.267,57.378 101.978,58.311 101.4,59.2C100.822,60.044 99.978,60.933 98.867,61.867C97.533,63.022 96.533,64.178 95.867,65.333C95.244,66.444 94.933,67.933 94.933,69.8ZM97,90.667C93.355,90.667 89.911,89.978 86.667,88.6C83.422,87.178 80.578,85.267 78.133,82.867C75.733,80.422 73.822,77.578 72.4,74.333C71.022,71.089 70.333,67.644 70.333,64C70.333,60.311 71.022,56.844 72.4,53.6C73.822,50.355 75.733,47.533 78.133,45.133C80.578,42.733 83.422,40.844 86.667,39.467C89.911,38.044 93.355,37.333 97,37.333C100.689,37.333 104.156,38.044 107.4,39.467C110.644,40.844 113.467,42.733 115.867,45.133C118.267,47.533 120.156,50.355 121.533,53.6C122.956,56.844 123.667,60.311 123.667,64C123.667,67.644 122.956,71.089 121.533,74.333C120.156,77.578 118.267,80.422 115.867,82.867C113.467,85.267 110.644,87.178 107.4,88.6C104.156,89.978 100.689,90.667 97,90.667ZM97,86.667C103.311,86.667 108.667,84.467 113.067,80.067C117.467,75.622 119.667,70.267 119.667,64C119.667,57.689 117.467,52.333 113.067,47.933C108.667,43.533 103.311,41.333 97,41.333C90.733,41.333 85.378,43.533 80.933,47.933C76.533,52.333 74.333,57.689 74.333,64C74.333,70.267 76.533,75.622 80.933,80.067C85.378,84.467 90.733,86.667 97,86.667Z"
/>
</vector>
18 changes: 18 additions & 0 deletions catalog/src/main/res/layout/component_header_layout.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8" ?>
<LinearLayout
xmlns:android="http:https://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<TextView
android:id="@+id/tv_component_header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?attr/textAppearanceBodyMedium"
android:layout_marginTop="@dimen/component_header_top_margin"
android:layout_marginBottom="@dimen/component_header_bottom_margin"
android:gravity="center_horizontal"
/>

</LinearLayout>
2 changes: 2 additions & 0 deletions catalog/src/main/res/values/dimens.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,6 @@
<dimen name="info_card_header_margin_bottom">8dp</dimen>
<dimen name="info_card_header_margin">16dp</dimen>
<dimen name="info_card_icon_padding">8dp</dimen>
<dimen name="component_header_top_margin">24dp</dimen>
<dimen name="component_header_bottom_margin">12dp</dimen>
</resources>
5 changes: 4 additions & 1 deletion catalog/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,9 @@
<string name="component_name_dropdown">Dropdown</string>
<string name="component_name_image">Image</string>
<string name="component_name_auto_complete">Auto Complete</string>
<string name="component_name_help">Help</string>
<string name="component_name_repeated_group">Repeated Group</string>
<string name="layout_name_default_text">Default</string>
<string name="layout_name_default_text">Default</string>
<string name="layout_name_paginated">Paginated</string>
<string name="layout_name_review">Review</string>
<string name="layout_name_read_only">Read only</string>
Expand Down Expand Up @@ -60,4 +61,6 @@
<string name="hide_error_state">Hide error state</string>
<string name="options">Options</string>
<string name="error">Error</string>
<string name="widgets">Widgets</string>
<string name="misc_components">Miscellaneous components</string>
</resources>

0 comments on commit 17e704e

Please sign in to comment.