Skip to content

Commit

Permalink
ANC module setup and Basic Flow (#504)
Browse files Browse the repository at this point in the history
* ANC module setup and Basic Flow

* Spotless apply

* Delete QuestionnaireActivityTest.kt

* Delete QuestionnaireViewModelTest.kt

* Delete QuestionnaireUtilsTest.kt

* Spotless Apply

* QuestionnaireViewModelTest fix

* Resolve feedback

* Spotless Apply

* Add theme and styles

* ANC Register list view loaded

* Update version number
  • Loading branch information
maimoonak authored Aug 31, 2021
1 parent 40339c7 commit 59d9ddb
Show file tree
Hide file tree
Showing 44 changed files with 1,376 additions and 264 deletions.
38 changes: 34 additions & 4 deletions android/anc/build.gradle
Original file line number Diff line number Diff line change
@@ -1,19 +1,47 @@
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'org.jetbrains.kotlin.plugin.serialization'
}

Properties props = new Properties()

def arr = ["FHIR_BASE_URL", "OAUTH_BASE_URL", "OAUTH_CIENT_ID", "OAUTH_CLIENT_SECRET", "OAUTH_SCOPE"]
if (rootProject.file("local.properties").exists()) {
props.load(rootProject.file("local.properties").newDataInputStream())

arr.each { prop ->
project.ext.set(prop, props.getProperty(prop, (prop == "FHIR_BASE_URL") ? "https://sample.url/fhir/" : "sample"))
}
} else {
println("local.properties does not exist. The following values are required " + arr.join(", "))
arr.each { prop ->
project.ext.set(prop, props.getProperty(prop, (prop.contains("URL")) ? "https://sample.url/fhir/" : "sample_" + prop))
}
}

android {
compileSdkVersion 30

dataBinding {
enabled true
}
defaultConfig {
applicationId "org.smartregister.fhircore.anc"
minSdkVersion 21
targetSdkVersion 30
minSdkVersion sdk_versions.min_sdk
targetSdkVersion sdk_versions.target_sdk
versionCode 1
versionName "1.0"
versionName "0.0.1"
multiDexEnabled true

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

buildConfigField("boolean", 'SKIP_AUTH_CHECK', "false")

buildConfigField("String", 'FHIR_BASE_URL', "\"${FHIR_BASE_URL}\"")
buildConfigField("String", 'OAUTH_BASE_URL', "\"${OAUTH_BASE_URL}\"")
buildConfigField("String", 'OAUTH_CIENT_ID', "\"${OAUTH_CIENT_ID}\"")
buildConfigField("String", 'OAUTH_CLIENT_SECRET', "\"${OAUTH_CLIENT_SECRET}\"")
buildConfigField("String", 'OAUTH_SCOPE', "\"${OAUTH_SCOPE}\"")
}

buildTypes {
Expand Down Expand Up @@ -53,4 +81,6 @@ dependencies {
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'

implementation deps.work.runtime
}
29 changes: 28 additions & 1 deletion android/anc/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,39 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.smartregister.fhircore.anc">

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />

<application
android:name=".AncApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:networkSecurityConfig="@xml/network_security_config"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Fhircoreandroid" />
android:theme="@style/AppTheme.NoActionBar">
<activity
android:name=".ui.login.LoginActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".ui.anccare.register.AncRegisterActivity" />
<activity android:name="org.smartregister.fhircore.engine.ui.questionnaire.QuestionnaireActivity" />

<service android:name=".AncAuthAndroidService">
<intent-filter>
<action android:name="android.accounts.AccountAuthenticator" />
</intent-filter>

<meta-data
android:name="android.accounts.AccountAuthenticator"
android:resource="@xml/authenticator" />
</service>
</application>

</manifest>
9 changes: 9 additions & 0 deletions android/anc/src/main/assets/anc_client_register_config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"registerTitle": "ANC",
"registrationQuestionnaireIdentifier": "207",
"registrationQuestionnaireTitle": "Add ANC Patient",
"pregnancyLogQuestionnaireIdentifier": "???",
"pregnancyLogQuestionnaireTitle": "Log Pregnancy",
"deliveryLogQuestionnaireIdentifier": "???",
"deliveryLogQuestionnaireTitle": "Log Delivery"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/*
* Copyright 2021 Ona Systems, Inc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.smartregister.fhircore.anc

import android.app.Application
import androidx.work.Constraints
import com.google.android.fhir.FhirEngine
import com.google.android.fhir.FhirEngineBuilder
import com.google.android.fhir.sync.PeriodicSyncConfiguration
import com.google.android.fhir.sync.RepeatInterval
import com.google.android.fhir.sync.Sync
import java.util.concurrent.TimeUnit
import org.hl7.fhir.r4.model.ResourceType
import org.smartregister.fhircore.engine.auth.AuthenticationService
import org.smartregister.fhircore.engine.configuration.app.ApplicationConfiguration
import org.smartregister.fhircore.engine.configuration.app.ConfigurableApplication
import org.smartregister.fhircore.engine.configuration.app.applicationConfigurationOf
import org.smartregister.fhircore.engine.util.SecureSharedPreference
import org.smartregister.fhircore.engine.util.SharedPreferencesHelper
import timber.log.Timber

class AncApplication : Application(), ConfigurableApplication {
override val applicationConfiguration: ApplicationConfiguration by lazy {
constructConfiguration()
}

override val authenticationService: AuthenticationService
get() = AncAuthenticationService(applicationContext)

override val fhirEngine: FhirEngine by lazy { constructFhirEngine() }

override val secureSharedPreference: SecureSharedPreference
get() = SecureSharedPreference(applicationContext)

override val resourceSyncParams: Map<ResourceType, Map<String, String>>
get() =
mapOf(
ResourceType.Patient to emptyMap(),
ResourceType.Questionnaire to emptyMap(),
ResourceType.StructureMap to mapOf(),
ResourceType.RelatedPerson to mapOf()
)

private fun constructFhirEngine(): FhirEngine {
Sync.periodicSync<AncFhirSyncWorker>(
this,
PeriodicSyncConfiguration(
syncConstraints = Constraints.Builder().build(),
repeat = RepeatInterval(interval = 1, timeUnit = TimeUnit.HOURS)
)
)

return FhirEngineBuilder(this).build()
}

private fun constructConfiguration(): ApplicationConfiguration {
return applicationConfigurationOf(
oauthServerBaseUrl = BuildConfig.OAUTH_BASE_URL,
fhirServerBaseUrl = BuildConfig.FHIR_BASE_URL,
clientId = BuildConfig.OAUTH_CIENT_ID,
clientSecret = BuildConfig.OAUTH_CLIENT_SECRET,
languages = listOf("en", "sw")
)
}

override fun configureApplication(applicationConfiguration: ApplicationConfiguration) {
throw UnsupportedOperationException("Can not override existing configuration")
}

override fun onCreate() {
super.onCreate()
SharedPreferencesHelper.init(this)
ancApplication = this

if (BuildConfig.DEBUG) {
Timber.plant(Timber.DebugTree())
}
}

companion object {
private lateinit var ancApplication: AncApplication

fun getContext() = ancApplication
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright 2021 Ona Systems, Inc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.smartregister.fhircore.anc

import android.app.Service
import android.content.Intent
import android.os.IBinder
import org.smartregister.fhircore.engine.auth.AccountAuthenticator

class AncAuthAndroidService : Service() {

private lateinit var authenticator: AccountAuthenticator

override fun onCreate() {
authenticator = AccountAuthenticator(this, AncAuthenticationService(this))
}

override fun onBind(intent: Intent?): IBinder {
return authenticator.iBinder
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright 2021 Ona Systems, Inc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.smartregister.fhircore.anc

import android.content.Context
import org.smartregister.fhircore.anc.ui.login.LoginActivity
import org.smartregister.fhircore.engine.auth.AuthenticationService

class AncAuthenticationService(override val context: Context) : AuthenticationService(context) {
private val applicationConfiguration = AncApplication.getContext().applicationConfiguration

override fun skipLogin() = BuildConfig.DEBUG && BuildConfig.SKIP_AUTH_CHECK

override fun getLoginActivityClass() = LoginActivity::class.java

override fun getAccountType() = context.getString(R.string.authenticator_account_type)

override fun clientSecret() = applicationConfiguration.clientSecret

override fun clientId() = applicationConfiguration.clientId

override fun providerScope() = applicationConfiguration.scope

override fun getApplicationConfigurations() = applicationConfiguration
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright 2021 Ona Systems, Inc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.smartregister.fhircore.anc

import android.content.Context
import androidx.work.WorkerParameters
import com.google.android.fhir.sync.FhirSyncWorker
import org.smartregister.fhircore.engine.util.extension.buildDatasource

class AncFhirSyncWorker(appContext: Context, workerParams: WorkerParameters) :
FhirSyncWorker(appContext, workerParams) {

override fun getSyncData() = AncApplication.getContext().resourceSyncParams

override fun getDataSource() =
AncApplication.getContext()
.buildDatasource(AncApplication.getContext().applicationConfiguration)

override fun getFhirEngine() = AncApplication.getContext().fhirEngine
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Copyright 2021 Ona Systems, Inc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.smartregister.fhircore.anc.data

import com.google.android.fhir.FhirEngine
import com.google.android.fhir.search.Search
import com.google.android.fhir.search.StringFilterModifier
import org.hl7.fhir.r4.model.Patient
import org.smartregister.fhircore.anc.data.model.AncPatientItem
import org.smartregister.fhircore.engine.data.domain.util.DomainMapper
import org.smartregister.fhircore.engine.data.domain.util.PaginatedDataSource

class AncPatientPaginatedDataSource(
val fhirEngine: FhirEngine,
domainMapper: DomainMapper<Patient, AncPatientItem>
) : PaginatedDataSource<Patient, AncPatientItem>(AncPatientRepository(fhirEngine, domainMapper)) {

private var query: String = ""

override suspend fun loadData(pageNumber: Int): List<AncPatientItem> {
return registerRepository.loadData(
pageNumber = pageNumber,
query = query,
primaryFilterCallback = { search: Search -> search.filter(Patient.ACTIVE, true) },
secondaryFilterCallbacks =
arrayOf({ filterQuery: String, search: Search ->
search.filter(Patient.NAME) {
modifier = StringFilterModifier.CONTAINS
value = filterQuery.trim()
}
})
)
}
}
Loading

0 comments on commit 59d9ddb

Please sign in to comment.