Skip to content

Commit

Permalink
Merge pull request #3499 from dhis2/ANDROAPP-4826-Display-message-whe…
Browse files Browse the repository at this point in the history
…n-event-has-no-sections-or-data-elements-config-issue

ANDROAPP-4826-Display-message-when-event-has-no-sections-or-data-elements-config-issue
  • Loading branch information
andresmr authored Feb 22, 2024
2 parents 80b307d + 57dfa82 commit ea9ef88
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 29 deletions.
1 change: 1 addition & 0 deletions form/src/main/java/org/dhis2/form/model/FormSection.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ data class FormSection(
val description: String? = null,
val state: SectionState,
val fields: List<FieldUiModel>,
var warningMessage: Int? = null,
) {
fun completedFields() = fields.count { it.value != null }
fun errorCount() = fields.count { it.error != null }
Expand Down
104 changes: 80 additions & 24 deletions form/src/main/java/org/dhis2/form/ui/Form.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,19 @@ import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Icon
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.ErrorOutline
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.MutableState
Expand All @@ -21,6 +27,7 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.focus.FocusDirection
import androidx.compose.ui.focus.FocusManager
import androidx.compose.ui.graphics.Color
Expand All @@ -29,13 +36,19 @@ import androidx.compose.ui.unit.dp
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import org.dhis2.commons.resources.ResourceManager
import org.dhis2.form.R
import org.dhis2.form.model.FieldUiModel
import org.dhis2.form.model.FormSection
import org.dhis2.form.ui.event.RecyclerViewUiEvents
import org.dhis2.form.ui.intent.FormIntent
import org.dhis2.form.ui.provider.inputfield.FieldProvider
import org.hisp.dhis.mobile.ui.designsystem.component.InfoBar
import org.hisp.dhis.mobile.ui.designsystem.component.InfoBarData
import org.hisp.dhis.mobile.ui.designsystem.component.Section
import org.hisp.dhis.mobile.ui.designsystem.component.SectionState
import org.hisp.dhis.mobile.ui.designsystem.theme.Radius
import org.hisp.dhis.mobile.ui.designsystem.theme.Spacing
import org.hisp.dhis.mobile.ui.designsystem.theme.SurfaceColor

@OptIn(ExperimentalFoundationApi::class)
@Composable
Expand Down Expand Up @@ -100,49 +113,92 @@ fun Form(
Section(
title = section.title,
isLastSection = getNextSection(section, sections) == null,
description = section.description,
description = if (section.fields.isNotEmpty()) section.description else null,
completedFields = section.completedFields(),
totalFields = section.fields.size,
state = section.state,
errorCount = section.errorCount(),
warningCount = section.warningCount(),
warningMessage = section.warningMessage?.let { resources.getString(it) },
onNextSection = onNextSection,
onSectionClick = {
intentHandler.invoke(FormIntent.OnSection(section.uid))
},
content = {
section.fields.forEachIndexed { index, fieldUiModel ->
fieldUiModel.setCallback(callback)
FieldProvider(
modifier = Modifier.animateItemPlacement(
animationSpec = tween(
durationMillis = 500,
easing = LinearOutSlowInEasing,
if (section.fields.isNotEmpty()) {
section.fields.forEachIndexed { index, fieldUiModel ->
fieldUiModel.setCallback(callback)
FieldProvider(
modifier = Modifier.animateItemPlacement(
animationSpec = tween(
durationMillis = 500,
easing = LinearOutSlowInEasing,
),
),
),
fieldUiModel = fieldUiModel,
uiEventHandler = uiEventHandler,
intentHandler = intentHandler,
resources = resources,
focusManager = focusManager,
onNextClicked = {
if (index == section.fields.size - 1) {
onNextSection()
focusNext.value = true
} else {
focusManager.moveFocus(FocusDirection.Down)
}
},
)
fieldUiModel = fieldUiModel,
uiEventHandler = uiEventHandler,
intentHandler = intentHandler,
resources = resources,
focusManager = focusManager,
onNextClicked = {
if (index == section.fields.size - 1) {
onNextSection()
focusNext.value = true
} else {
focusManager.moveFocus(FocusDirection.Down)
}
},
)
}
}
},
)
}
item(sections.size - 1) {
Spacer(modifier = Modifier.height(120.dp))
Spacer(modifier = Modifier.height(Spacing.Spacing120))
}
}
}
if (shouldDisplayNoFieldsWarning(sections)) {
NoFieldsWarning(resources)
}
}

fun shouldDisplayNoFieldsWarning(sections: List<FormSection>): Boolean {
return if (sections.size == 1) {
val section = sections.first()
section.state == SectionState.NO_HEADER && section.fields.isEmpty()
} else {
false
}
}

@Composable
fun NoFieldsWarning(resources: ResourceManager) {
Column(
modifier = Modifier
.padding(Spacing.Spacing16),
) {
InfoBar(
infoBarData = InfoBarData(
text = resources.getString(R.string.form_without_fields),
icon = {
Icon(
imageVector = Icons.Outlined.ErrorOutline,
contentDescription = "no fields",
tint = SurfaceColor.Warning,
)
},
color = SurfaceColor.Warning,
backgroundColor = SurfaceColor.WarningContainer,
actionText = null,
onClick = null,
),
modifier = Modifier
.clip(shape = RoundedCornerShape(Radius.Full))
.background(SurfaceColor.WarningContainer),
)
}
}

private fun FocusManager.moveFocusNext(focusNext: MutableState<Boolean>) {
Expand Down
12 changes: 9 additions & 3 deletions form/src/main/java/org/dhis2/form/ui/mapper/FormSectionMapper.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.dhis2.form.ui.mapper

import org.dhis2.form.R
import org.dhis2.form.model.FieldUiModel
import org.dhis2.form.model.FieldUiModelImpl
import org.dhis2.form.model.FormSection
Expand All @@ -13,6 +14,8 @@ class FormSectionMapper {
if (hasSections(items)) {
items.forEach { item ->
if (item is SectionUiModelImpl) {
val fields = items.filterIsInstance<FieldUiModelImpl>()
.filter { it.programStageSection == item.uid }
sections.add(
FormSection(
uid = item.uid,
Expand All @@ -23,8 +26,12 @@ class FormSectionMapper {
false -> SectionState.CLOSE
null -> SectionState.FIXED
},
fields = items.filterIsInstance<FieldUiModelImpl>()
.filter { it.programStageSection == item.uid },
fields = fields,
warningMessage = if (fields.isEmpty()) {
R.string.form_without_fields
} else {
null
},
),
)
}
Expand All @@ -40,7 +47,6 @@ class FormSectionMapper {
),
)
}

return sections
}

Expand Down
1 change: 1 addition & 0 deletions form/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -103,4 +103,5 @@
<string name="qr_code">QR code</string>
<string name="bar_code">Bar code</string>
<string name="add_location">Add location</string>
<string name="form_without_fields">This form has no fields configured</string>
</resources>
4 changes: 2 additions & 2 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ kotlin = '1.9.21'
hilt = '2.47'
hiltCompiler = '1.0.0'
jacoco = '0.8.10'
designSystem = "0.2-20240208.105715-18"
designSystem = "0.2-20240213.152311-21"
dhis2sdk = "1.10.0-20240207.110936-11"
ruleEngine = "2.1.9"
appcompat = "1.6.1"
Expand Down Expand Up @@ -102,7 +102,7 @@ hiltPlugin = { group = "com.google.dagger", name = "hilt-android-gradle-plugin",
jacoco = { group = "org.jacoco", name = "org.jacoco.core", version.ref = "jacoco" }
dhis2-android-sdk = { group = "org.hisp.dhis", name = "android-core", version.ref = "dhis2sdk" }
dhis2-ruleengine = { group = "org.hisp.dhis.rules", name = "rule-engine", version.ref = "ruleEngine" }
dhis2-mobile-designsystem = { group = "org.hisp.dhis.mobile", name = "designsystem", version.ref = "designSystem" }
dhis2-mobile-designsystem = { group = "org.hisp.dhis.mobile", name = "designsystem-android", version.ref = "designSystem" }
desugar = { group = "com.android.tools", name = "desugar_jdk_libs", version.ref = "desugar_jdk_libs" }
androidx-activityKtx = { group = "androidx.activity", name = "activity-ktx", version.ref = "activityCompose" }
androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
Expand Down

0 comments on commit ea9ef88

Please sign in to comment.