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

Add configuration to generate MeasureReports in the background (#2515) #2520

Merged
merged 12 commits into from
Jul 12, 2023
  •  
  •  
  •  
9 changes: 4 additions & 5 deletions android/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ buildscript {
classpath("org.jetbrains.kotlin:kotlin-serialization:1.7.10")
classpath("com.google.dagger:hilt-android-gradle-plugin:2.42")
classpath("androidx.navigation:navigation-safe-args-gradle-plugin:2.5.3")
classpath("com.diffplug.spotless:spotless-plugin-gradle:5.11.0")
classpath("com.diffplug.spotless:spotless-plugin-gradle:6.19.0")
classpath("gradle.plugin.org.kt3k.gradle.plugin:coveralls-gradle-plugin:2.12.0")
classpath("de.mannodermaus.gradle.plugins:android-junit5:1.8.2.1")
classpath("com.android.tools.build:gradle:7.1.3")
Expand Down Expand Up @@ -52,19 +52,18 @@ subprojects {
}

configure<SpotlessExtension> {
val lintVersion = "0.41.0"
val lintOptions = mapOf("indent_size" to "2", "continuation_indent_size" to "2")
val lintVersion = "0.49.0"

kotlin {
target("**/*.kt")
ktlint(lintVersion).userData(lintOptions)
ktlint(lintVersion)
ktfmt().googleStyle()
licenseHeaderFile("${project.rootProject.projectDir}/license-header.txt")
}

kotlinGradle {
target("*.gradle.kts")
ktlint(lintVersion).userData(lintOptions)
ktlint(lintVersion)
ktfmt().googleStyle()
}

Expand Down
4 changes: 2 additions & 2 deletions android/engine/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,8 @@ android {
"META-INF/LGPL-3.0.txt",
"META-INF/sun-jaxb.episode",
"META-INF/*.kotlin_module",
"META-INF/INDEX.LIST"
)
"META-INF/INDEX.LIST",
),
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,21 +22,21 @@ import androidx.compose.ui.test.junit4.ComposeContentTestRule
fun ComposeContentTestRule.waitUntilNodeCount(
matcher: SemanticsMatcher,
count: Int = 1,
timeoutMillis: Long = 5_000L
timeoutMillis: Long = 5_000L,
) {
this.waitUntil(timeoutMillis) { this.onAllNodes(matcher).fetchSemanticsNodes().size == count }
}

fun ComposeContentTestRule.waitUntilExists(
matcher: SemanticsMatcher,
timeoutMillis: Long = 5_000L
timeoutMillis: Long = 5_000L,
) {
return this.waitUntilNodeCount(matcher, 1, timeoutMillis)
}

fun ComposeContentTestRule.waitUntilDoesNotExist(
matcher: SemanticsMatcher,
timeoutMillis: Long = 5_000L
timeoutMillis: Long = 5_000L,
) {
return this.waitUntilNodeCount(matcher, 0, timeoutMillis)
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class RegisterBottomSheetFragmentViewTest {
private val navigationMenuConfigs =
listOf(
NavigationMenuConfig(id = "UniqueTag1", display = "Menu 1"),
NavigationMenuConfig(id = "UniqueTag2", display = "Menu 2")
NavigationMenuConfig(id = "UniqueTag2", display = "Menu 2"),
)

@Test
Expand All @@ -47,6 +47,7 @@ class RegisterBottomSheetFragmentViewTest {
composeRule.onNodeWithText("Menu 1", useUnmergedTree = true).assertExists().assertIsDisplayed()
composeRule.onNodeWithText("Menu 2", useUnmergedTree = true).assertExists().assertIsDisplayed()
}

@Test
fun testTitleShowsWithGivenName() {
setContent("Other services")
Expand All @@ -55,13 +56,14 @@ class RegisterBottomSheetFragmentViewTest {
.assertExists()
.assertIsDisplayed()
}

private fun setContent(title: String) {
composeRule.setContent {
RegisterBottomSheetView(
menuClickListener = mockListener,
navigationMenuConfigs = navigationMenuConfigs,
onDismiss = {},
title = title
title = title,
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ internal class PinTest {
inputMode = true,
onPinSet = {},
onShowPinError = {},
onPinEntered = { _: CharArray, _: (Boolean) -> Unit -> }
onPinEntered = { _: CharArray, _: (Boolean) -> Unit -> },
)
}
composeRule.onNodeWithTag(PIN_TEXT_FIELD_TEST_TAG).performTextInput("1")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class LoaderViewTest {
composeRule
.onNodeWithTag(LOADER_DIALOG_PROGRESS_MSG_TAG)
.assertTextEquals(
ApplicationProvider.getApplicationContext<Application>().getString(R.string.syncing_down)
ApplicationProvider.getApplicationContext<Application>().getString(R.string.syncing_down),
)
}

Expand All @@ -56,7 +56,7 @@ class LoaderViewTest {
composeRule
.onNodeWithTag(LOADER_DIALOG_PROGRESS_MSG_TAG)
.assertTextEquals(
ApplicationProvider.getApplicationContext<Application>().getString(R.string.syncing_up)
ApplicationProvider.getApplicationContext<Application>().getString(R.string.syncing_up),
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class RegisterFooterKtTest {
currentPage = 2,
pagesCount = 5,
previousButtonClickListener = {},
nextButtonClickListener = {}
nextButtonClickListener = {},
)
}

Expand All @@ -52,7 +52,7 @@ class RegisterFooterKtTest {
composeRule
.onNodeWithTag(SEARCH_FOOTER_PREVIOUS_BUTTON_TAG)
.assertTextEquals(
ApplicationProvider.getApplicationContext<Application>().getString(R.string.str_previous)
ApplicationProvider.getApplicationContext<Application>().getString(R.string.str_previous),
)

composeRule.onNodeWithTag(SEARCH_FOOTER_PAGINATION_TAG).assertExists()
Expand All @@ -62,7 +62,7 @@ class RegisterFooterKtTest {
.onNodeWithTag(SEARCH_FOOTER_PAGINATION_TAG)
.assertTextEquals(
ApplicationProvider.getApplicationContext<Application>()
.getString(R.string.str_page_info, 2, 5)
.getString(R.string.str_page_info, 2, 5),
)

composeRule.onNodeWithTag(SEARCH_FOOTER_NEXT_BUTTON_TAG).assertExists()
Expand All @@ -71,7 +71,7 @@ class RegisterFooterKtTest {
composeRule
.onNodeWithTag(SEARCH_FOOTER_NEXT_BUTTON_TAG)
.assertTextEquals(
ApplicationProvider.getApplicationContext<Application>().getString(R.string.str_next)
ApplicationProvider.getApplicationContext<Application>().getString(R.string.str_next),
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,29 @@ package org.smartregister.fhircore.engine.configuration

/**
* Types of configurations supported
*
* @property name A unique name for configuration type. Typically provided in camelCase.
* @property parseAsResource Instructs that this configuration should be parsed into a FHIR resource
* (for configurations saved as Binary resource but can be directly converted to a eligible FHIR
* resource); generally a custom hard coded is used.
* (for configurations saved as Binary resource but can be directly converted to a eligible FHIR
* resource); generally a custom hard coded is used.
* @property multiConfig Denotes that we can have multiple instances of this type of config.
*/
sealed class ConfigType(
val name: String,
val parseAsResource: Boolean = false,
val multiConfig: Boolean = false
val multiConfig: Boolean = false,
) {
object Application : ConfigType("application")

object Sync : ConfigType("sync", true)

object Navigation : ConfigType("navigation")

object Register : ConfigType("register", multiConfig = true)

object MeasureReport : ConfigType("measureReport", multiConfig = true)

object Profile : ConfigType("profile", multiConfig = true)

object GeoWidget : ConfigType("geoWidget", multiConfig = true)
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ package org.smartregister.fhircore.engine.configuration
*
* @property appId Unique identifier for the application to which this configurations is applied
* @property configType Used to categorize multiple configurations of the same type. E.g. two
* RegisterViewConfigurations used in an application with two registers.
* RegisterViewConfigurations used in an application with two registers.
* @property resourceType Optional FHIR resource type
*/
abstract class Configuration {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ constructor(
val sharedPreferencesHelper: SharedPreferencesHelper,
val dispatcherProvider: DispatcherProvider,
val configService: ConfigService,
val json: Json
val json: Json,
) {

val configsJsonMap = mutableMapOf<String, String>()
Expand All @@ -86,18 +86,19 @@ constructor(
inline fun <reified T : Configuration> retrieveConfiguration(
configType: ConfigType,
configId: String? = null,
paramsMap: Map<String, String>? = emptyMap()
paramsMap: Map<String, String>? = emptyMap(),
): T {
require(!configType.parseAsResource) { "Configuration MUST be a template" }
val configKey = if (configType.multiConfig && configId != null) configId else configType.name
if (configCacheMap.contains(configKey) && paramsMap?.isEmpty() == true)
if (configCacheMap.contains(configKey) && paramsMap?.isEmpty() == true) {
return configCacheMap[configKey] as T
}
val decodedConfig =
localizationHelper
.parseTemplate(
bundleName = LocalizationHelper.STRINGS_BASE_BUNDLE_NAME,
locale = Locale.getDefault(),
template = getConfigValueWithParam(paramsMap, configKey)
template = getConfigValueWithParam(paramsMap, configKey),
)
.decodeJson<T>(jsonInstance = json)
configCacheMap[configKey] = decodedConfig
Expand All @@ -119,7 +120,7 @@ constructor(
.parseTemplate(
bundleName = LocalizationHelper.STRINGS_BASE_BUNDLE_NAME,
locale = Locale.getDefault(),
template = it
template = it,
)
.decodeJson<T>()
}
Expand Down Expand Up @@ -155,7 +156,7 @@ constructor(
}
if (bundleName.contains("_")) {
return retrieveResourceBundleConfiguration(
bundleName.substring(0, bundleName.lastIndexOf('_'))
bundleName.substring(0, bundleName.lastIndexOf('_')),
)
}
return null
Expand Down Expand Up @@ -211,16 +212,15 @@ constructor(
suspend fun loadConfigurations(
appId: String,
context: Context,
configsLoadedCallback: (Boolean) -> Unit = {}
configsLoadedCallback: (Boolean) -> Unit = {},
) {
// For appId that ends with suffix /debug e.g. app/debug, we load configurations from assets
// extract appId by removing the suffix e.g. app from above example
val loadFromAssets = appId.endsWith(DEBUG_SUFFIX, ignoreCase = true)
val parsedAppId = appId.substringBefore("/").trim()
if (loadFromAssets) {
try {
context
.assets
context.assets
.open(String.format(COMPOSITION_CONFIG_PATH, parsedAppId))
.bufferedReader()
.readText()
Expand All @@ -232,8 +232,9 @@ constructor(
}
if (iconConfigs.isNotEmpty()) {
val ids = iconConfigs.joinToString(",") { it.focus.extractId() }
fhirResourceDataSource.getResource(
"${ResourceType.Binary.name}?${Composition.SP_RES_ID}=$ids"
fhirResourceDataSource
.getResource(
"${ResourceType.Binary.name}?${Composition.SP_RES_ID}=$ids",
)
.entry
.forEach { addOrUpdate(it.resource) }
Expand All @@ -243,7 +244,7 @@ constructor(
loadFromAssets = true,
appId = parsedAppId,
configsLoadedCallback = configsLoadedCallback,
context = context
context = context,
)
}
} catch (fileNotFoundException: FileNotFoundException) {
Expand All @@ -262,7 +263,7 @@ constructor(
composition: Composition,
loadFromAssets: Boolean,
appId: String,
configsLoadedCallback: (Boolean) -> Unit
configsLoadedCallback: (Boolean) -> Unit,
) {
if (loadFromAssets) {
retrieveAssetConfigs(context, appId).forEach { fileName ->
Expand All @@ -276,7 +277,7 @@ constructor(
.lowercase(Locale.ENGLISH)
.substring(
fileName.indexOfLast { it == '/' }.plus(1),
fileName.lastIndexOf(CONFIG_SUFFIX)
fileName.lastIndexOf(CONFIG_SUFFIX),
)
.camelCase()

Expand Down Expand Up @@ -314,16 +315,16 @@ constructor(
val filesQueue = LinkedList<String>()
val configFiles = mutableListOf<String>()
context.assets.list(String.format(BASE_CONFIG_PATH, appId))?.onEach {
if (!supportedFileExtensions.contains(it.fileExtension))
if (!supportedFileExtensions.contains(it.fileExtension)) {
filesQueue.addLast(String.format(BASE_CONFIG_PATH, appId) + "/$it")
else configFiles.add(String.format(BASE_CONFIG_PATH, appId) + "/$it")
} else configFiles.add(String.format(BASE_CONFIG_PATH, appId) + "/$it")
}
while (filesQueue.isNotEmpty()) {
val currentPath = filesQueue.removeFirst()
context.assets.list(currentPath)?.onEach {
if (!supportedFileExtensions.contains(it.fileExtension))
if (!supportedFileExtensions.contains(it.fileExtension)) {
filesQueue.addLast("$currentPath/$it")
else configFiles.add("$currentPath/$it")
} else configFiles.add("$currentPath/$it")
}
}
return configFiles
Expand Down Expand Up @@ -359,7 +360,7 @@ constructor(
ResourceType.List.name,
ResourceType.PlanDefinition.name,
ResourceType.Library.name,
ResourceType.Measure.name
ResourceType.Measure.name,
)
}
.forEach { resourceGroup ->
Expand All @@ -379,7 +380,7 @@ constructor(

private suspend fun processCompositionManifestResources(
resourceType: String,
resourceIds: String
resourceIds: String,
) {
val searchPath = resourceType + "?${Composition.SP_RES_ID}=$resourceIds"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ data class QuestionnaireConfig(
val readOnlyLinkIds: List<String>? = emptyList(),
val configRules: List<RuleConfig>? = null,
val extraParams: List<ActionParameter>? = null,
val onSubmitActions: List<ActionConfig>? = null
val onSubmitActions: List<ActionConfig>? = null,
) : java.io.Serializable, Parcelable {

fun interpolate(computedValuesMap: Map<String, Any>) =
Expand All @@ -64,16 +64,16 @@ data class QuestionnaireConfig(
groupResource =
groupResource?.copy(
groupIdentifier =
groupResource.groupIdentifier.interpolate(computedValuesMap).extractLogicalIdUuid()
groupResource.groupIdentifier.interpolate(computedValuesMap).extractLogicalIdUuid(),
),
confirmationDialog =
confirmationDialog?.copy(
title = confirmationDialog.title.interpolate(computedValuesMap),
message = confirmationDialog.message.interpolate(computedValuesMap),
actionButtonText = confirmationDialog.actionButtonText.interpolate(computedValuesMap)
actionButtonText = confirmationDialog.actionButtonText.interpolate(computedValuesMap),
),
planDefinitions = planDefinitions?.map { it.interpolate(computedValuesMap) },
readOnlyLinkIds = readOnlyLinkIds?.map { it.interpolate(computedValuesMap) }
readOnlyLinkIds = readOnlyLinkIds?.map { it.interpolate(computedValuesMap) },
)
}

Expand All @@ -82,7 +82,7 @@ data class QuestionnaireConfig(
data class ConfirmationDialog(
val title: String = "",
val message: String = "",
val actionButtonText: String = ""
val actionButtonText: String = "",
) : java.io.Serializable, Parcelable

@Serializable
Expand All @@ -92,5 +92,5 @@ data class GroupResourceConfig(
val memberResourceType: String,
val removeMember: Boolean = false,
val removeGroup: Boolean = false,
val deactivateMembers: Boolean = true
val deactivateMembers: Boolean = true,
) : java.io.Serializable, Parcelable
Loading