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 landscape support for Event Capture #3586

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
301bb31
Remove edit person button in the TeiDashboardMobileActivity landscape
yuzalsif Mar 25, 2024
fa0cd28
feat: Add Enrollment form in landscape TeidashboardMobileActivity
yuzalsif Mar 26, 2024
fbc19cf
feat: Remove the TEI name on the toobar of TeiDashboard in landscape
yuzalsif Mar 26, 2024
4366107
Merge branch 'develop' into feat/landscape-support-eventcapture
yuzalsif Mar 27, 2024
6f4c809
feat: Add support to not show data entry screen option in eventcaptur…
yuzalsif Mar 28, 2024
50e5d82
feat: Add a new layout file to support landscape view in EventCapture…
yuzalsif Mar 28, 2024
687e59c
Rename eventViewandPager to eventViewPager
yuzalsif Mar 28, 2024
b40b526
Add impementation to set ViewPagerAdapter for landscape view EventCap…
yuzalsif Mar 28, 2024
1b296c8
Show the DataEntry screen when it is portrait view
yuzalsif Mar 28, 2024
cecbd5e
feat: Hide DataEntry icon from the BottomNavBar in Landscape
yuzalsif Mar 28, 2024
9b95a7d
feat: Add support for EventCapture to adapt to orientation changes
yuzalsif Mar 28, 2024
a8588cf
Remove calling isPortrait() instead use isPortrait value from EventC…
yuzalsif Mar 28, 2024
5fb3cfb
Handle portrait pages and landscape pages in EventPagerAdapter
yuzalsif Mar 29, 2024
03e3833
feat: Add support to show complete actions on landscape
yuzalsif Mar 29, 2024
77dad4f
feat: Select the first page in navigationBar as the current page upon…
yuzalsif Mar 31, 2024
f443d67
Create a global property eventViewPager to avoid dupicate assignment …
yuzalsif Mar 31, 2024
89f4671
feat: Add event capture form in landscape
yuzalsif Mar 31, 2024
71e7a08
Add a method that will by dagger to return DashboardViewModelFactory
yuzalsif Mar 31, 2024
dda245c
Add support to instantiate DashboardViewModel in EventCaptureActivit…
yuzalsif Mar 31, 2024
af36463
Add interface class to enable EventCaptureActivity and TeiDashboardAc…
yuzalsif Mar 31, 2024
2a44578
feat: Add support to show the Tei detail card on the EventCaptureActi…
yuzalsif Mar 31, 2024
accddd4
fix: Remove saving EventCaptureFormFragment instance on configuration…
yuzalsif Mar 31, 2024
9289828
feat: Assign programUid a value from an intent to help load Events
yuzalsif Apr 1, 2024
c8af22f
feat: Add support to open new events without starting a new instance …
yuzalsif Apr 1, 2024
4a8b35e
feat: Add support to highlight the selected event
yuzalsif Apr 2, 2024
46777cd
Remove print statement in production codes
yuzalsif Apr 3, 2024
6eb16ee
fix: Fix a behavior where an app crash when selecting events without …
yuzalsif Apr 3, 2024
d53d550
feat: Make programs clickabe in EventCaptureActivity
yuzalsif Apr 4, 2024
457b4a7
fix: Remove highlighting OVERDUE, SCHEDULE and SKIPPED Events when se…
yuzalsif Apr 4, 2024
d380276
Remove logics to highlight the selected event for portrait view
yuzalsif Apr 8, 2024
07c9d46
Remove unused import
yuzalsif Apr 8, 2024
27ac8ae
feat: update dashboardViewModel after syncing Tei details in Eventcap…
yuzalsif Apr 8, 2024
a06fd82
Remove unused import directive
yuzalsif Apr 12, 2024
cf5feb9
Refactor codes with ktlintFormat
yuzalsif Apr 12, 2024
859d29a
Move default statement in switch statement to the end
yuzalsif Apr 15, 2024
fc0a539
retrigger github checks
yuzalsif Apr 15, 2024
9061e29
Merge branch 'develop' into feat/landscape-support-eventcapture
yuzalsif Apr 17, 2024
759622e
fix: Remove non-null assertions as they may cause NullPointerException
yuzalsif Apr 18, 2024
a7ad6f8
Add support to show Event details after updating scheduled events
yuzalsif Apr 18, 2024
264a756
Remove if null check for viewModelFactory and use ?.let instead
yuzalsif Apr 20, 2024
d42ba41
Format code with ./gradlew ktlintFormat
yuzalsif Apr 20, 2024
13e13a7
Merge branch 'develop' into feat/landscape-support-eventcapture
yuzalsif Apr 23, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@
<activity android:name=".usescases.reservedValue.ReservedValueActivity" />
<activity
android:name=".usescases.eventsWithoutRegistration.eventCapture.EventCaptureActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
andresmr marked this conversation as resolved.
Show resolved Hide resolved
android:configChanges="keyboardHidden|screenSize"
android:windowSoftInputMode="adjustResize|stateAlwaysHidden" />
<activity android:name=".usescases.sync.SyncActivity" />

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import android.widget.PopupMenu
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModelProvider
import androidx.viewpager2.widget.ViewPager2
import androidx.viewpager2.widget.ViewPager2.OnPageChangeCallback
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.snackbar.Snackbar
Expand All @@ -22,6 +24,7 @@ import org.dhis2.commons.dialogs.CustomDialog
import org.dhis2.commons.dialogs.DialogClickListener
import org.dhis2.commons.popupmenu.AppMenuHelper
import org.dhis2.commons.resources.ResourceManager
import org.dhis2.commons.sync.OnDismissListener
import org.dhis2.commons.sync.SyncContext
import org.dhis2.databinding.ActivityEventCaptureBinding
import org.dhis2.form.model.EventMode
Expand All @@ -31,14 +34,18 @@ import org.dhis2.ui.dialogs.bottomsheet.BottomSheetDialog
import org.dhis2.ui.dialogs.bottomsheet.BottomSheetDialogUiModel
import org.dhis2.ui.dialogs.bottomsheet.DialogButtonStyle.DiscardButton
import org.dhis2.ui.dialogs.bottomsheet.DialogButtonStyle.MainButton
import org.dhis2.usescases.eventsWithoutRegistration.eventCapture.eventCaptureFragment.EventCaptureFormFragment
import org.dhis2.usescases.eventsWithoutRegistration.eventCapture.eventCaptureFragment.OnEditionListener
import org.dhis2.usescases.eventsWithoutRegistration.eventCapture.model.EventCompletionDialog
import org.dhis2.usescases.eventsWithoutRegistration.eventDetails.injection.EventDetailsComponent
import org.dhis2.usescases.eventsWithoutRegistration.eventDetails.injection.EventDetailsComponentProvider
import org.dhis2.usescases.eventsWithoutRegistration.eventDetails.injection.EventDetailsModule
import org.dhis2.usescases.eventsWithoutRegistration.eventInitial.EventInitialActivity
import org.dhis2.usescases.general.ActivityGlobalAbstract
import org.dhis2.usescases.teiDashboard.DashboardViewModel
import org.dhis2.usescases.teiDashboard.dashboardfragments.relationships.MapButtonObservable
import org.dhis2.usescases.teiDashboard.dashboardfragments.teidata.TEIDataActivityContract
import org.dhis2.usescases.teiDashboard.dashboardfragments.teidata.TEIDataFragment.Companion.newInstance
import org.dhis2.utils.analytics.CLICK
import org.dhis2.utils.analytics.DELETE_EVENT
import org.dhis2.utils.analytics.SHOW_HELP
Expand All @@ -48,13 +55,16 @@ import org.dhis2.utils.customviews.navigationbar.NavigationPageConfigurator
import org.dhis2.utils.granularsync.OPEN_ERROR_LOCATION
import org.dhis2.utils.granularsync.SyncStatusDialog
import org.dhis2.utils.granularsync.shouldLaunchSyncDialog
import org.dhis2.utils.isLandscape
import org.dhis2.utils.isPortrait
import javax.inject.Inject

class EventCaptureActivity :
ActivityGlobalAbstract(),
EventCaptureContract.View,
MapButtonObservable,
EventDetailsComponentProvider {
EventDetailsComponentProvider,
TEIDataActivityContract {
private lateinit var binding: ActivityEventCaptureBinding

@JvmField
Expand All @@ -78,37 +88,53 @@ class EventCaptureActivity :
var eventCaptureComponent: EventCaptureComponent? = null
var programUid: String? = null
var eventUid: String? = null
private var teiUid: String? = null
private var enrollmentUid: String? = null
private val relationshipMapButton: LiveData<Boolean> = MutableLiveData(false)
private var onEditionListener: OnEditionListener? = null
private var adapter: EventCapturePagerAdapter? = null
private var eventViewPager: ViewPager2? = null
private var dashboardViewModel: DashboardViewModel? = null
override fun onCreate(savedInstanceState: Bundle?) {
eventUid = intent.getStringExtra(Constants.EVENT_UID)
eventCaptureComponent = this.app().userComponent()!!.plus(
EventCaptureModule(
this,
eventUid,
),
)
eventCaptureComponent!!.inject(this)
programUid = intent.getStringExtra(Constants.PROGRAM_UID)
setUpEventCaptureComponent(eventUid)
teiUid = presenter!!.teiUid
enrollmentUid = presenter!!.enrollmentUid
themeManager!!.setProgramTheme(intent.getStringExtra(Constants.PROGRAM_UID)!!)
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_event_capture)
binding.presenter = presenter
eventViewPager = when {
this.isLandscape() -> binding.eventViewLandPager
else -> binding.eventViewPager
}
eventMode = intent.getSerializableExtra(Constants.EVENT_MODE) as EventMode?
setUpViewPagerAdapter()
setUpNavigationBar()
setUpEventCaptureFormLandscape(eventUid ?: "")
if (this.isLandscape() && areTeiUidAndEnrollmentUidNotNull()) {
val viewModelFactory = this.app().dashboardComponent()?.dashboardViewModelFactory()

viewModelFactory?.let {
dashboardViewModel =
ViewModelProvider(this, viewModelFactory)[DashboardViewModel::class.java]
supportFragmentManager.beginTransaction().replace(R.id.tei_column, newInstance(programUid, teiUid, enrollmentUid)).commit()
dashboardViewModel?.updateSelectedEventUid(eventUid)
}
}
showProgress()
presenter!!.initNoteCounter()
presenter!!.init()
binding.syncButton.setOnClickListener { showSyncDialog() }
binding.syncButton.setOnClickListener { showSyncDialog(EVENT_SYNC) }

if (intent.shouldLaunchSyncDialog()) {
showSyncDialog()
showSyncDialog(EVENT_SYNC)
}
}

private fun setUpViewPagerAdapter() {
binding.eventViewPager.isUserInputEnabled = false
eventViewPager?.isUserInputEnabled = false
adapter = EventCapturePagerAdapter(
this,
intent.getStringExtra(Constants.PROGRAM_UID),
Expand All @@ -118,8 +144,8 @@ class EventCaptureActivity :
intent.getBooleanExtra(OPEN_ERROR_LOCATION, false),
eventMode,
)
binding.eventViewPager.adapter = adapter
binding.eventViewPager.registerOnPageChangeCallback(object : OnPageChangeCallback() {
eventViewPager?.adapter = adapter
eventViewPager?.registerOnPageChangeCallback(object : OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
super.onPageSelected(position)
if (position == 0 && eventMode !== EventMode.NEW) {
Expand All @@ -136,12 +162,56 @@ class EventCaptureActivity :

private fun setUpNavigationBar() {
binding.navigationBar.pageConfiguration(pageConfigurator!!)
eventViewPager?.registerOnPageChangeCallback(
object : OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
super.onPageSelected(position)
binding.navigationBar.selectItemAt(position)
}
},
)
binding.navigationBar.setOnItemSelectedListener { item: MenuItem ->
binding.eventViewPager.currentItem = adapter!!.getDynamicTabIndex(item.itemId)
eventViewPager?.currentItem = adapter!!.getDynamicTabIndex(item.itemId)
true
}
}

private fun setUpEventCaptureFormLandscape(eventUid: String) {
if (this.isLandscape()) {
supportFragmentManager.beginTransaction()
.replace(R.id.event_form, EventCaptureFormFragment.newInstance(eventUid, false, eventMode))
.commit()
}
}

private fun setUpEventCaptureComponent(eventUid: String?) {
eventCaptureComponent = app().userComponent()!!.plus(
EventCaptureModule(
this,
eventUid,
this.isPortrait(),
),
)
eventCaptureComponent!!.inject(this)
}

private fun updateLandscapeViewsOnEventChange(newEventUid: String) {
if (newEventUid != this.eventUid) {
this.eventUid = newEventUid
setUpEventCaptureComponent(newEventUid)
setUpViewPagerAdapter()
setUpNavigationBar()
setUpEventCaptureFormLandscape(newEventUid)
showProgress()
presenter!!.initNoteCounter()
presenter!!.init()
}
}

private fun areTeiUidAndEnrollmentUidNotNull(): Boolean {
return teiUid != null && enrollmentUid != null
}

fun openDetails() {
binding.navigationBar.selectItemAt(0)
}
Expand All @@ -158,6 +228,9 @@ class EventCaptureActivity :
override fun onResume() {
super.onResume()
presenter!!.refreshTabCounters()
with(dashboardViewModel) {
this?.selectedEventUid()?.observe(this@EventCaptureActivity, ::updateLandscapeViewsOnEventChange)
}
}

override fun onDestroy() {
Expand Down Expand Up @@ -210,7 +283,11 @@ class EventCaptureActivity :
}

private fun isFormScreen(): Boolean {
return adapter?.isFormScreenShown(binding.eventViewPager.currentItem) == true
return if (this.isPortrait()) {
adapter?.isFormScreenShown(binding.eventViewPager?.currentItem) == true
} else {
true
}
}

override fun updatePercentage(primaryValue: Float) {
Expand All @@ -225,25 +302,28 @@ class EventCaptureActivity :
emptyMandatoryFields: Map<String, String>,
eventCompletionDialog: EventCompletionDialog,
) {
if (binding.navigationBar.selectedItemId == R.id.navigation_data_entry) {
val dialog = BottomSheetDialog(
bottomSheetDialogUiModel = eventCompletionDialog.bottomSheetDialogUiModel,
onMainButtonClicked = {
setAction(eventCompletionDialog.mainButtonAction)
},
onSecondaryButtonClicked = {
eventCompletionDialog.secondaryButtonAction?.let { setAction(it) }
},
content = if (eventCompletionDialog.fieldsWithIssues.isNotEmpty()) {
{ bottomSheetDialog ->
ErrorFieldList(eventCompletionDialog.fieldsWithIssues) {
bottomSheetDialog.dismiss()
}
val dialog = BottomSheetDialog(
bottomSheetDialogUiModel = eventCompletionDialog.bottomSheetDialogUiModel,
onMainButtonClicked = {
setAction(eventCompletionDialog.mainButtonAction)
},
onSecondaryButtonClicked = {
eventCompletionDialog.secondaryButtonAction?.let { setAction(it) }
},
content = if (eventCompletionDialog.fieldsWithIssues.isNotEmpty()) {
{ bottomSheetDialog ->
ErrorFieldList(eventCompletionDialog.fieldsWithIssues) {
bottomSheetDialog.dismiss()
}
} else {
null
},
)
}
} else {
null
},
)
if (binding.navigationBar.selectedItemId == R.id.navigation_data_entry) {
dialog.show(supportFragmentManager, SHOW_OPTIONS)
}
if (this.isLandscape()) {
dialog.show(supportFragmentManager, SHOW_OPTIONS)
}
}
Expand Down Expand Up @@ -452,23 +532,66 @@ class EventCaptureActivity :
return eventCaptureComponent!!.plus(module)
}

private fun showSyncDialog() {
SyncStatusDialog.Builder()
.withContext(this)
.withSyncContext(SyncContext.Event(eventUid!!))
.onNoConnectionListener {
val contextView = findViewById<View>(R.id.navigationBar)
Snackbar.make(
contextView,
R.string.sync_offline_check_connection,
Snackbar.LENGTH_SHORT,
).show()
}
.show("EVENT_SYNC")
private fun showSyncDialog(syncType: String) {
val syncContext = when (syncType) {
TEI_SYNC -> enrollmentUid?.let { SyncContext.Enrollment(it) }
EVENT_SYNC -> SyncContext.Event(eventUid!!)
else -> null
}

syncContext?.let {
SyncStatusDialog.Builder()
.withContext(this)
.withSyncContext(it)
.onDismissListener(object : OnDismissListener {
override fun onDismiss(hasChanged: Boolean) {
if (hasChanged && syncType == TEI_SYNC) {
dashboardViewModel?.updateDashboard()
}
}
})
.onNoConnectionListener {
val contextView = findViewById<View>(R.id.navigationBar)
Snackbar.make(
contextView,
R.string.sync_offline_check_connection,
Snackbar.LENGTH_SHORT,
).show()
}
.show(syncType)
}
}

override fun openSyncDialog() {
showSyncDialog(TEI_SYNC)
}

override fun finishActivity() {
finish()
}

override fun restoreAdapter(programUid: String, teiUid: String, enrollmentUid: String) {
// we do not restore adapter in events
}

override fun executeOnUIThread() {
activity.runOnUiThread {
showDescription(getString(R.string.error_applying_rule_effects))
}
}

override fun getContext(): Context {
return this
}

override fun activityTeiUid(): String? {
return teiUid
}

companion object {
private const val SHOW_OPTIONS = "SHOW_OPTIONS"
private const val TEI_SYNC = "SYNC_TEI"
private const val EVENT_SYNC = "EVENT_SYNC"

@JvmStatic
fun getActivityBundle(eventUid: String, programUid: String, eventMode: EventMode): Bundle {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,12 @@ void attemptFinish(boolean canComplete,
void emitAction(@NotNull EventCaptureAction onBack);

String programStage();

@Nullable
String getTeiUid();

@Nullable
String getEnrollmentUid();
}

public interface EventCaptureRepository {
Expand Down Expand Up @@ -149,6 +155,12 @@ public interface EventCaptureRepository {
boolean hasRelationships();

ValidationStrategy validationStrategy();

@Nullable
String getTeiUid();

@Nullable
String getEnrollmentUid();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,12 @@ public class EventCaptureModule {
private final String eventUid;
private final EventCaptureContract.View view;

public EventCaptureModule(EventCaptureContract.View view, String eventUid) {
private final boolean isPortrait;

public EventCaptureModule(EventCaptureContract.View view, String eventUid, boolean isPortrait) {
this.view = view;
this.eventUid = eventUid;
this.isPortrait = isPortrait;
}

@Provides
Expand Down Expand Up @@ -138,7 +141,7 @@ FlowableProcessor<RowAction> getProcessor() {
NavigationPageConfigurator pageConfigurator(
EventCaptureContract.EventCaptureRepository repository
) {
return new EventPageConfigurator(repository);
return new EventPageConfigurator(repository, isPortrait);
}

@Provides
Expand Down
Loading
Loading