From bf2aa62445a244e339824752a415300ee8455c6f Mon Sep 17 00:00:00 2001 From: Hamza Ahmed Khan Date: Fri, 10 Feb 2023 14:39:12 +0500 Subject: [PATCH 01/11] Fix offline map download --- .../EusmAvailableOfflineMapsFragment.java | 44 +++++++++---------- .../repository/AppLocationRepository.java | 15 +++++++ 2 files changed, 37 insertions(+), 22 deletions(-) diff --git a/opensrp-eusm/src/main/java/org/smartregister/eusm/fragment/EusmAvailableOfflineMapsFragment.java b/opensrp-eusm/src/main/java/org/smartregister/eusm/fragment/EusmAvailableOfflineMapsFragment.java index bbf6c33..8bb2d43 100644 --- a/opensrp-eusm/src/main/java/org/smartregister/eusm/fragment/EusmAvailableOfflineMapsFragment.java +++ b/opensrp-eusm/src/main/java/org/smartregister/eusm/fragment/EusmAvailableOfflineMapsFragment.java @@ -22,6 +22,7 @@ import org.smartregister.util.Utils; import java.util.List; +import java.util.Set; import timber.log.Timber; @@ -43,33 +44,32 @@ public static EusmAvailableOfflineMapsFragment newInstance(Bundle bundle, @NonNu @Override protected void downloadLocation(@NonNull Location location) { - getAppExecutors().diskIO().execute(new Runnable() { - @Override - public void run() { - String name = location.getId(); - List locationList = getAppStructureRepository().getStructuresByDistrictId(name); - if (locationList == null || locationList.isEmpty()) { + String locationId = location.getId(); + Set districts = EusmApplication.getInstance().getAppLocationRepository().getDistrictIdsForRegionId(locationId); + for (Location district : districts) { + downloadDistrictMap(district.getId()); + } + } + + protected void downloadDistrictMap(String districtId) { + getAppExecutors().diskIO().execute(() -> { + List locationList = getAppStructureRepository().getStructuresByDistrictId(districtId); + if (locationList == null || locationList.isEmpty()) { + getAppExecutors().mainThread().execute(() -> showToast(R.string.location_has_no_structures)); + } else { + JSONObject featureCollection = new JSONObject(); + try { + featureCollection.put(TaskingConstants.GeoJSON.TYPE, TaskingConstants.GeoJSON.FEATURE_COLLECTION); + featureCollection.put(TaskingConstants.GeoJSON.FEATURES, new JSONArray(gson.toJson(locationList))); getAppExecutors().mainThread().execute(new Runnable() { @Override public void run() { - showToast(R.string.location_has_no_structures); + showToast(R.string.download_starting); + downloadMap(FeatureCollection.fromJson(featureCollection.toString()), districtId); } }); - } else { - JSONObject featureCollection = new JSONObject(); - try { - featureCollection.put(TaskingConstants.GeoJSON.TYPE, TaskingConstants.GeoJSON.FEATURE_COLLECTION); - featureCollection.put(TaskingConstants.GeoJSON.FEATURES, new JSONArray(gson.toJson(locationList))); - getAppExecutors().mainThread().execute(new Runnable() { - @Override - public void run() { - showToast(R.string.download_starting); - downloadMap(FeatureCollection.fromJson(featureCollection.toString()), name); - } - }); - } catch (JSONException e) { - Timber.e(e); - } + } catch (JSONException e) { + Timber.e(e); } } }); diff --git a/opensrp-eusm/src/main/java/org/smartregister/eusm/repository/AppLocationRepository.java b/opensrp-eusm/src/main/java/org/smartregister/eusm/repository/AppLocationRepository.java index 0e09057..92f9b4d 100644 --- a/opensrp-eusm/src/main/java/org/smartregister/eusm/repository/AppLocationRepository.java +++ b/opensrp-eusm/src/main/java/org/smartregister/eusm/repository/AppLocationRepository.java @@ -82,4 +82,19 @@ public Set getLocationByNameAndGeoLevel(Set names, String leve } return locations; } + + public Set getDistrictIdsForRegionId(String regionId) { + Set districts = new HashSet<>(); + if (StringUtils.isBlank(regionId)) + return districts; + try (Cursor cursor = getReadableDatabase().rawQuery("SELECT * FROM " + getLocationTableName() + + " WHERE " + PARENT_ID + " =? ", new String[]{regionId})) { + if (cursor.moveToFirst()) { + districts.add(readCursor(cursor)); + } + } catch (SQLException e) { + Timber.e(e); + } + return districts; + } } From 4c46738a5508ffd917f337896f058eaf3513da45 Mon Sep 17 00:00:00 2001 From: Hamza Ahmed Khan Date: Fri, 10 Feb 2023 17:20:13 +0500 Subject: [PATCH 02/11] Fix adapter update issues --- .../EusmAvailableOfflineMapsFragment.java | 26 ++++++++++++++++--- .../EUSMAvailableOfflineMapsPresenter.java | 24 +++++++++++++++++ .../repository/AppLocationRepository.java | 13 ++++++++++ 3 files changed, 60 insertions(+), 3 deletions(-) create mode 100644 opensrp-eusm/src/main/java/org/smartregister/eusm/presenter/EUSMAvailableOfflineMapsPresenter.java diff --git a/opensrp-eusm/src/main/java/org/smartregister/eusm/fragment/EusmAvailableOfflineMapsFragment.java b/opensrp-eusm/src/main/java/org/smartregister/eusm/fragment/EusmAvailableOfflineMapsFragment.java index 8bb2d43..9a0f708 100644 --- a/opensrp-eusm/src/main/java/org/smartregister/eusm/fragment/EusmAvailableOfflineMapsFragment.java +++ b/opensrp-eusm/src/main/java/org/smartregister/eusm/fragment/EusmAvailableOfflineMapsFragment.java @@ -11,11 +11,13 @@ import org.json.JSONException; import org.json.JSONObject; import org.smartregister.domain.Location; +import org.smartregister.domain.LocationTag; import org.smartregister.eusm.R; import org.smartregister.eusm.application.EusmApplication; +import org.smartregister.eusm.presenter.EUSMAvailableOfflineMapsPresenter; import org.smartregister.eusm.repository.AppStructureRepository; import org.smartregister.tasking.fragment.AvailableOfflineMapsFragment; -import org.smartregister.tasking.presenter.AvailableOfflineMapsPresenter; +import org.smartregister.tasking.model.OfflineMapModel; import org.smartregister.tasking.util.OfflineMapHelper; import org.smartregister.tasking.util.TaskingConstants; import org.smartregister.util.AppExecutors; @@ -37,14 +39,14 @@ public static EusmAvailableOfflineMapsFragment newInstance(Bundle bundle, @NonNu if (bundle != null) { fragment.setArguments(bundle); } - fragment.setPresenter(new AvailableOfflineMapsPresenter(fragment)); + fragment.setPresenter(new EUSMAvailableOfflineMapsPresenter(fragment)); fragment.setMapStyleAssetPath(mapStyleAssetPath); return fragment; } @Override protected void downloadLocation(@NonNull Location location) { - String locationId = location.getId(); + String locationId = location.getId(); Set districts = EusmApplication.getInstance().getAppLocationRepository().getDistrictIdsForRegionId(locationId); for (Location district : districts) { downloadDistrictMap(district.getId()); @@ -96,4 +98,22 @@ public AppExecutors getAppExecutors() { } return appExecutors; } + + @Override + public void moveDownloadedOAToDownloadedList(String operationalAreaId) { + String regionId = EusmApplication.getInstance().getAppLocationRepository().getRegionIdForDistrictId(operationalAreaId).getId(); + super.moveDownloadedOAToDownloadedList(regionId); + } + + @Override + public void updateOperationalAreasToDownload(OfflineMapModel offlineMapModel) { + Set tags = offlineMapModel.getLocation().getLocationTags(); + for (LocationTag tag : tags) { + if (tag.getName().equalsIgnoreCase("district")) { + Location region = EusmApplication.getInstance().getAppLocationRepository().getRegionIdForDistrictId(offlineMapModel.getLocation().getId()); + offlineMapModel.setLocation(region); + } + } + super.updateOperationalAreasToDownload(offlineMapModel); + } } diff --git a/opensrp-eusm/src/main/java/org/smartregister/eusm/presenter/EUSMAvailableOfflineMapsPresenter.java b/opensrp-eusm/src/main/java/org/smartregister/eusm/presenter/EUSMAvailableOfflineMapsPresenter.java new file mode 100644 index 0000000..074825d --- /dev/null +++ b/opensrp-eusm/src/main/java/org/smartregister/eusm/presenter/EUSMAvailableOfflineMapsPresenter.java @@ -0,0 +1,24 @@ +package org.smartregister.eusm.presenter; + +import org.smartregister.eusm.application.EusmApplication; +import org.smartregister.tasking.contract.AvailableOfflineMapsContract; +import org.smartregister.tasking.presenter.AvailableOfflineMapsPresenter; + +import java.util.ArrayList; +import java.util.List; + +public class EUSMAvailableOfflineMapsPresenter extends AvailableOfflineMapsPresenter { + + public EUSMAvailableOfflineMapsPresenter(AvailableOfflineMapsContract.View view) { + super(view); + } + + @Override + public void fetchAvailableOAsForMapDownLoad(List locationIds) { + List regionIds = new ArrayList<>(); + for (String districtId : locationIds) { + regionIds.add(EusmApplication.getInstance().getAppLocationRepository().getRegionIdForDistrictId(districtId).getId()); + } + super.fetchAvailableOAsForMapDownLoad(regionIds); + } +} diff --git a/opensrp-eusm/src/main/java/org/smartregister/eusm/repository/AppLocationRepository.java b/opensrp-eusm/src/main/java/org/smartregister/eusm/repository/AppLocationRepository.java index 92f9b4d..d3e6b19 100644 --- a/opensrp-eusm/src/main/java/org/smartregister/eusm/repository/AppLocationRepository.java +++ b/opensrp-eusm/src/main/java/org/smartregister/eusm/repository/AppLocationRepository.java @@ -97,4 +97,17 @@ public Set getDistrictIdsForRegionId(String regionId) { } return districts; } + + public Location getRegionIdForDistrictId(String districtId) { + try (Cursor cursor = getReadableDatabase().rawQuery("SELECT * FROM " + getLocationTableName() + + " WHERE " + ID + " IN (SELECT " + PARENT_ID + " FROM " + getLocationTableName() + " WHERE " + + ID + " =? )", new String[]{districtId})) { + if (cursor.moveToFirst()) { + return readCursor(cursor); + } + } catch (SQLException e) { + Timber.e(e); + } + return null; + } } From aaaff44644551433b212c582677ff6f155be1f3f Mon Sep 17 00:00:00 2001 From: Hamza Ahmed Khan Date: Mon, 13 Feb 2023 11:04:21 +0500 Subject: [PATCH 03/11] Disable multi download selection --- .../AppTaskingLibraryConfiguration.java | 2 +- .../EusmAvailableOfflineMapsFragment.java | 69 ++++++++++++++++++- .../EUSMAvailableOfflineMapsPresenter.java | 14 +++- 3 files changed, 81 insertions(+), 4 deletions(-) diff --git a/opensrp-eusm/src/main/java/org/smartregister/eusm/config/AppTaskingLibraryConfiguration.java b/opensrp-eusm/src/main/java/org/smartregister/eusm/config/AppTaskingLibraryConfiguration.java index 531e543..9f1654e 100644 --- a/opensrp-eusm/src/main/java/org/smartregister/eusm/config/AppTaskingLibraryConfiguration.java +++ b/opensrp-eusm/src/main/java/org/smartregister/eusm/config/AppTaskingLibraryConfiguration.java @@ -431,7 +431,7 @@ public String getProvinceFromTreeDialogValue(List arrayList) { @Override public String getDistrictFromTreeDialogValue(List arrayList) { try { - return arrayList.get(2); + return arrayList.get(1); } catch (IndexOutOfBoundsException e) { Timber.e(e); } diff --git a/opensrp-eusm/src/main/java/org/smartregister/eusm/fragment/EusmAvailableOfflineMapsFragment.java b/opensrp-eusm/src/main/java/org/smartregister/eusm/fragment/EusmAvailableOfflineMapsFragment.java index 9a0f708..2ab7346 100644 --- a/opensrp-eusm/src/main/java/org/smartregister/eusm/fragment/EusmAvailableOfflineMapsFragment.java +++ b/opensrp-eusm/src/main/java/org/smartregister/eusm/fragment/EusmAvailableOfflineMapsFragment.java @@ -1,6 +1,8 @@ package org.smartregister.eusm.fragment; import android.os.Bundle; +import android.view.View; +import android.widget.CheckBox; import androidx.annotation.NonNull; import androidx.annotation.StringRes; @@ -23,6 +25,7 @@ import org.smartregister.util.AppExecutors; import org.smartregister.util.Utils; +import java.util.ArrayList; import java.util.List; import java.util.Set; @@ -34,6 +37,10 @@ public class EusmAvailableOfflineMapsFragment extends AvailableOfflineMapsFragme private AppExecutors appExecutors; + private List offlineMapModelList = new ArrayList<>(); + + private List operationalAreasToDownload = new ArrayList<>(); + public static EusmAvailableOfflineMapsFragment newInstance(Bundle bundle, @NonNull String mapStyleAssetPath) { EusmAvailableOfflineMapsFragment fragment = new EusmAvailableOfflineMapsFragment(); if (bundle != null) { @@ -102,7 +109,19 @@ public AppExecutors getAppExecutors() { @Override public void moveDownloadedOAToDownloadedList(String operationalAreaId) { String regionId = EusmApplication.getInstance().getAppLocationRepository().getRegionIdForDistrictId(operationalAreaId).getId(); - super.moveDownloadedOAToDownloadedList(regionId); + List toRemoveFromAvailableList = new ArrayList<>(); + List toRemoveFromDownloadList = new ArrayList<>(); + for (OfflineMapModel offlineMapModel : offlineMapModelList) { + if (offlineMapModel.getDownloadAreaId().equals(regionId)) { + offlineMapModel.setOfflineMapStatus(OfflineMapModel.OfflineMapStatus.DOWNLOADED); + callback.onMapDownloaded(offlineMapModel); + toRemoveFromAvailableList.add(offlineMapModel); + toRemoveFromDownloadList.add(offlineMapModel.getLocation()); + setOfflineMapModelList(offlineMapModelList); + break; + } + } + operationalAreasToDownload.removeAll(toRemoveFromDownloadList); } @Override @@ -116,4 +135,52 @@ public void updateOperationalAreasToDownload(OfflineMapModel offlineMapModel) { } super.updateOperationalAreasToDownload(offlineMapModel); } + + @Override + public void updateOperationalAreasToDownload(View view) { + CheckBox checkBox = (CheckBox) view; + OfflineMapModel offlineMapModel = (OfflineMapModel) view.getTag(R.id.offline_map_checkbox); + + if (checkBox.isChecked()) { + offlineMapModel.setOfflineMapStatus(OfflineMapModel.OfflineMapStatus.SELECTED_FOR_DOWNLOAD); + operationalAreasToDownload.clear(); + operationalAreasToDownload.add(offlineMapModel.getLocation()); + + for (OfflineMapModel model : offlineMapModelList) { + if (!model.getDownloadAreaId().equals(offlineMapModel.getDownloadAreaId()) + && model.getOfflineMapStatus() == OfflineMapModel.OfflineMapStatus.SELECTED_FOR_DOWNLOAD) { + model.setOfflineMapStatus(OfflineMapModel.OfflineMapStatus.READY); + } + } + setOfflineMapModelList(offlineMapModelList); + } else { + operationalAreasToDownload.remove(offlineMapModel.getLocation()); + } + } + + @Override + public void setOfflineMapModelList(List offlineMapModelList) { + this.offlineMapModelList = offlineMapModelList; + super.setOfflineMapModelList(offlineMapModelList); + } + + @Override + public void initiateMapDownload() { + if (this.operationalAreasToDownload == null || this.operationalAreasToDownload.isEmpty()) { + displayToast(getString(R.string.select_offline_map_to_download)); + return; + } + + for (OfflineMapModel model : offlineMapModelList) { + if (model.getOfflineMapStatus() == OfflineMapModel.OfflineMapStatus.DOWNLOAD_STARTED) { + Timber.e("Error: A map download is already in progress"); + return; + } + } + + for (Location location : this.operationalAreasToDownload) { + disableCheckBox(location.getId()); + downloadLocation(location); + } + } } diff --git a/opensrp-eusm/src/main/java/org/smartregister/eusm/presenter/EUSMAvailableOfflineMapsPresenter.java b/opensrp-eusm/src/main/java/org/smartregister/eusm/presenter/EUSMAvailableOfflineMapsPresenter.java index 074825d..21928de 100644 --- a/opensrp-eusm/src/main/java/org/smartregister/eusm/presenter/EUSMAvailableOfflineMapsPresenter.java +++ b/opensrp-eusm/src/main/java/org/smartregister/eusm/presenter/EUSMAvailableOfflineMapsPresenter.java @@ -1,5 +1,6 @@ package org.smartregister.eusm.presenter; +import org.smartregister.domain.Location; import org.smartregister.eusm.application.EusmApplication; import org.smartregister.tasking.contract.AvailableOfflineMapsContract; import org.smartregister.tasking.presenter.AvailableOfflineMapsPresenter; @@ -16,9 +17,18 @@ public EUSMAvailableOfflineMapsPresenter(AvailableOfflineMapsContract.View view) @Override public void fetchAvailableOAsForMapDownLoad(List locationIds) { List regionIds = new ArrayList<>(); - for (String districtId : locationIds) { - regionIds.add(EusmApplication.getInstance().getAppLocationRepository().getRegionIdForDistrictId(districtId).getId()); + if (locationIds != null) { + for (String districtId : locationIds) { + Location region = EusmApplication.getInstance().getAppLocationRepository().getRegionIdForDistrictId(districtId); + if (region != null) + regionIds.add(region.getId()); + } } super.fetchAvailableOAsForMapDownLoad(regionIds); } + + @Override + public void onDownloadStarted(String operationalAreaId) { + // DO nothing + } } From 55edab37cfb978b9cf1cf34d2f1728cf1524ec97 Mon Sep 17 00:00:00 2001 From: Hamza Ahmed Khan Date: Tue, 14 Feb 2023 16:54:42 +0500 Subject: [PATCH 04/11] Fix failing test --- .../fragment/EusmAvailableOfflineMapsFragment.java | 12 +++++++++++- .../EusmAvailableOfflineMapsFragmentTest.java | 11 +++++++++-- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/opensrp-eusm/src/main/java/org/smartregister/eusm/fragment/EusmAvailableOfflineMapsFragment.java b/opensrp-eusm/src/main/java/org/smartregister/eusm/fragment/EusmAvailableOfflineMapsFragment.java index 2ab7346..148d6fd 100644 --- a/opensrp-eusm/src/main/java/org/smartregister/eusm/fragment/EusmAvailableOfflineMapsFragment.java +++ b/opensrp-eusm/src/main/java/org/smartregister/eusm/fragment/EusmAvailableOfflineMapsFragment.java @@ -17,6 +17,7 @@ import org.smartregister.eusm.R; import org.smartregister.eusm.application.EusmApplication; import org.smartregister.eusm.presenter.EUSMAvailableOfflineMapsPresenter; +import org.smartregister.eusm.repository.AppLocationRepository; import org.smartregister.eusm.repository.AppStructureRepository; import org.smartregister.tasking.fragment.AvailableOfflineMapsFragment; import org.smartregister.tasking.model.OfflineMapModel; @@ -35,6 +36,8 @@ public class EusmAvailableOfflineMapsFragment extends AvailableOfflineMapsFragme private AppStructureRepository appStructureRepository; + private AppLocationRepository appLocationRepository; + private AppExecutors appExecutors; private List offlineMapModelList = new ArrayList<>(); @@ -54,7 +57,7 @@ public static EusmAvailableOfflineMapsFragment newInstance(Bundle bundle, @NonNu @Override protected void downloadLocation(@NonNull Location location) { String locationId = location.getId(); - Set districts = EusmApplication.getInstance().getAppLocationRepository().getDistrictIdsForRegionId(locationId); + Set districts = getAppLocationRepository().getDistrictIdsForRegionId(locationId); for (Location district : districts) { downloadDistrictMap(district.getId()); } @@ -99,6 +102,13 @@ public AppStructureRepository getAppStructureRepository() { return appStructureRepository; } + public AppLocationRepository getAppLocationRepository() { + if (appLocationRepository == null) { + appLocationRepository = EusmApplication.getInstance().getAppLocationRepository(); + } + return appLocationRepository; + } + public AppExecutors getAppExecutors() { if (appExecutors == null) { appExecutors = EusmApplication.getInstance().getAppExecutors(); diff --git a/opensrp-eusm/src/test/java/org/smartregister/eusm/fragment/EusmAvailableOfflineMapsFragmentTest.java b/opensrp-eusm/src/test/java/org/smartregister/eusm/fragment/EusmAvailableOfflineMapsFragmentTest.java index 0c701db..af6efc5 100644 --- a/opensrp-eusm/src/test/java/org/smartregister/eusm/fragment/EusmAvailableOfflineMapsFragmentTest.java +++ b/opensrp-eusm/src/test/java/org/smartregister/eusm/fragment/EusmAvailableOfflineMapsFragmentTest.java @@ -9,6 +9,7 @@ import org.robolectric.annotation.LooperMode; import org.smartregister.domain.Location; import org.smartregister.eusm.BaseUnitTest; +import org.smartregister.eusm.repository.AppLocationRepository; import org.smartregister.eusm.repository.AppStructureRepository; import java.util.Collections; @@ -40,13 +41,19 @@ public void setUp() throws Exception { public void testDownloadLocationShouldStartOfflineMap() { fragmentScenario.onFragment(fragment -> { EusmAvailableOfflineMapsFragment fragmentSpy = spy(fragment); + Location district = new Location(); + district.setId("4322-23"); + district.setType("Feature"); Location location = new Location(); - location.setId("4322-23"); + location.setId("4322-78"); location.setType("Feature"); doNothing().when(fragmentSpy).downloadMap(any(FeatureCollection.class), anyString()); AppStructureRepository appStructureRepository = mock(AppStructureRepository.class); + AppLocationRepository appLocationRepository = mock(AppLocationRepository.class); doReturn(appStructureRepository).when(fragmentSpy).getAppStructureRepository(); - doReturn(Collections.singletonList(location)).when(appStructureRepository).getStructuresByDistrictId(anyString()); + doReturn(appLocationRepository).when(fragmentSpy).getAppLocationRepository(); + doReturn(Collections.singletonList(district)).when(appStructureRepository).getStructuresByDistrictId(anyString()); + doReturn(Collections.singleton(location)).when(appLocationRepository).getDistrictIdsForRegionId(anyString()); doNothing().when(fragmentSpy).showToast(anyInt()); fragmentSpy.downloadLocation(location); shadowOf(getMainLooper()).idle(); From 0b2d7f1b46d6c0d193f3c9318421028feb939866 Mon Sep 17 00:00:00 2001 From: Hamza Ahmed Khan Date: Thu, 16 Feb 2023 12:02:53 +0500 Subject: [PATCH 05/11] Modify download maps to use districts instead of regions --- .../activity/EusmOfflineMapsActivity.java | 7 ++ .../AppTaskingLibraryConfiguration.java | 16 +++- .../EusmAvailableOfflineMapsFragment.java | 83 +++++++++---------- .../EusmDownloadedOfflineMapsFragment.java | 32 +++++++ .../EUSMAvailableOfflineMapsPresenter.java | 34 -------- .../repository/AppLocationRepository.java | 23 ++--- opensrp-eusm/src/main/res/values/strings.xml | 2 + .../EusmAvailableOfflineMapsFragmentTest.java | 13 +-- 8 files changed, 107 insertions(+), 103 deletions(-) create mode 100644 opensrp-eusm/src/main/java/org/smartregister/eusm/fragment/EusmDownloadedOfflineMapsFragment.java delete mode 100644 opensrp-eusm/src/main/java/org/smartregister/eusm/presenter/EUSMAvailableOfflineMapsPresenter.java diff --git a/opensrp-eusm/src/main/java/org/smartregister/eusm/activity/EusmOfflineMapsActivity.java b/opensrp-eusm/src/main/java/org/smartregister/eusm/activity/EusmOfflineMapsActivity.java index 5cf0b9e..e601afc 100644 --- a/opensrp-eusm/src/main/java/org/smartregister/eusm/activity/EusmOfflineMapsActivity.java +++ b/opensrp-eusm/src/main/java/org/smartregister/eusm/activity/EusmOfflineMapsActivity.java @@ -4,8 +4,10 @@ import org.smartregister.eusm.R; import org.smartregister.eusm.fragment.EusmAvailableOfflineMapsFragment; +import org.smartregister.eusm.fragment.EusmDownloadedOfflineMapsFragment; import org.smartregister.tasking.activity.OfflineMapsActivity; import org.smartregister.tasking.fragment.AvailableOfflineMapsFragment; +import org.smartregister.tasking.fragment.DownloadedOfflineMapsFragment; public class EusmOfflineMapsActivity extends OfflineMapsActivity { @@ -19,4 +21,9 @@ public String getMapStyleAssetPath() { protected AvailableOfflineMapsFragment getAvailableOfflineMapsFragment() { return EusmAvailableOfflineMapsFragment.newInstance(this.getIntent().getExtras(), this.getMapStyleAssetPath()); } + + @Override + protected DownloadedOfflineMapsFragment getDownloadedOfflineMapsFragment() { + return EusmDownloadedOfflineMapsFragment.newInstance(this.getIntent().getExtras(), this); + } } diff --git a/opensrp-eusm/src/main/java/org/smartregister/eusm/config/AppTaskingLibraryConfiguration.java b/opensrp-eusm/src/main/java/org/smartregister/eusm/config/AppTaskingLibraryConfiguration.java index 9f1654e..c7f6402 100644 --- a/opensrp-eusm/src/main/java/org/smartregister/eusm/config/AppTaskingLibraryConfiguration.java +++ b/opensrp-eusm/src/main/java/org/smartregister/eusm/config/AppTaskingLibraryConfiguration.java @@ -34,6 +34,7 @@ import org.smartregister.eusm.helper.EusmTaskingMapHelper; import org.smartregister.eusm.job.LocationTaskServiceJob; import org.smartregister.eusm.layer.SatelliteStreetsLayer; +import org.smartregister.eusm.repository.AppLocationRepository; import org.smartregister.eusm.util.AppConstants; import org.smartregister.eusm.util.AppUtils; import org.smartregister.eusm.util.DefaultLocationUtils; @@ -69,6 +70,7 @@ import org.smartregister.tasking.util.TaskingMapHelper; import org.smartregister.util.AppExecutors; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; @@ -514,15 +516,25 @@ public List getLocationsIdsForDownload(List downloadedLocation .findPlanDefinitionSearchByPlanStatus(PlanDefinition.PlanStatus.ACTIVE) .stream().map(PlanDefinitionSearch::getJurisdictionId).collect(Collectors.toList()); + // List districts instead of regions + List districtIds = new ArrayList<>(); + AppLocationRepository appLocationRepository = EusmApplication.getInstance().getAppLocationRepository(); + for (String regionId : jurisdictionIds) { + Set districts = appLocationRepository.getDistrictIdsForRegionId(regionId); + for (Location district: districts) { + districtIds.add(district.getId()); + } + } + if (downloadedLocations != null) { - jurisdictionIds.removeAll(downloadedLocations); + districtIds.removeAll(downloadedLocations); } // List locationList = EusmApplication.getInstance().getStructureRepository().getLocationByDistrictIds(jurisdictionIds); // // if (downloadedLocations != null) { // locationList = locationList.stream().filter(location -> !downloadedLocations.contains(location.getId())).collect(Collectors.toList()); // } - return EusmApplication.getInstance().getLocationRepository().getLocationsByIds(jurisdictionIds); + return EusmApplication.getInstance().getLocationRepository().getLocationsByIds(districtIds); } @Override diff --git a/opensrp-eusm/src/main/java/org/smartregister/eusm/fragment/EusmAvailableOfflineMapsFragment.java b/opensrp-eusm/src/main/java/org/smartregister/eusm/fragment/EusmAvailableOfflineMapsFragment.java index 148d6fd..571828b 100644 --- a/opensrp-eusm/src/main/java/org/smartregister/eusm/fragment/EusmAvailableOfflineMapsFragment.java +++ b/opensrp-eusm/src/main/java/org/smartregister/eusm/fragment/EusmAvailableOfflineMapsFragment.java @@ -5,30 +5,26 @@ import android.widget.CheckBox; import androidx.annotation.NonNull; -import androidx.annotation.StringRes; +import com.google.android.material.snackbar.Snackbar; import com.mapbox.geojson.FeatureCollection; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import org.smartregister.domain.Location; -import org.smartregister.domain.LocationTag; import org.smartregister.eusm.R; import org.smartregister.eusm.application.EusmApplication; -import org.smartregister.eusm.presenter.EUSMAvailableOfflineMapsPresenter; -import org.smartregister.eusm.repository.AppLocationRepository; import org.smartregister.eusm.repository.AppStructureRepository; import org.smartregister.tasking.fragment.AvailableOfflineMapsFragment; import org.smartregister.tasking.model.OfflineMapModel; +import org.smartregister.tasking.presenter.AvailableOfflineMapsPresenter; import org.smartregister.tasking.util.OfflineMapHelper; import org.smartregister.tasking.util.TaskingConstants; import org.smartregister.util.AppExecutors; -import org.smartregister.util.Utils; import java.util.ArrayList; import java.util.List; -import java.util.Set; import timber.log.Timber; @@ -36,38 +32,41 @@ public class EusmAvailableOfflineMapsFragment extends AvailableOfflineMapsFragme private AppStructureRepository appStructureRepository; - private AppLocationRepository appLocationRepository; - private AppExecutors appExecutors; private List offlineMapModelList = new ArrayList<>(); private List operationalAreasToDownload = new ArrayList<>(); + private Snackbar displayBar = null; + public static EusmAvailableOfflineMapsFragment newInstance(Bundle bundle, @NonNull String mapStyleAssetPath) { EusmAvailableOfflineMapsFragment fragment = new EusmAvailableOfflineMapsFragment(); if (bundle != null) { fragment.setArguments(bundle); } - fragment.setPresenter(new EUSMAvailableOfflineMapsPresenter(fragment)); + fragment.setPresenter(new AvailableOfflineMapsPresenter(fragment)); fragment.setMapStyleAssetPath(mapStyleAssetPath); return fragment; } @Override protected void downloadLocation(@NonNull Location location) { - String locationId = location.getId(); - Set districts = getAppLocationRepository().getDistrictIdsForRegionId(locationId); - for (Location district : districts) { - downloadDistrictMap(district.getId()); - } + downloadDistrictMap(location.getId()); } protected void downloadDistrictMap(String districtId) { getAppExecutors().diskIO().execute(() -> { List locationList = getAppStructureRepository().getStructuresByDistrictId(districtId); if (locationList == null || locationList.isEmpty()) { - getAppExecutors().mainThread().execute(() -> showToast(R.string.location_has_no_structures)); + getAppExecutors().mainThread().execute(() -> displayToast(getString(R.string.location_has_no_structures))); + // Revert download map status + for (OfflineMapModel model : offlineMapModelList) { + if (model.getOfflineMapStatus() == OfflineMapModel.OfflineMapStatus.DOWNLOAD_STARTED) { + model.setOfflineMapStatus(OfflineMapModel.OfflineMapStatus.READY); + return; + } + } } else { JSONObject featureCollection = new JSONObject(); try { @@ -76,7 +75,7 @@ protected void downloadDistrictMap(String districtId) { getAppExecutors().mainThread().execute(new Runnable() { @Override public void run() { - showToast(R.string.download_starting); + displayToast(getString(R.string.download_starting)); downloadMap(FeatureCollection.fromJson(featureCollection.toString()), districtId); } }); @@ -87,10 +86,6 @@ public void run() { }); } - protected void showToast(@StringRes int stringRes) { - Utils.showToast(getContext(), getString(stringRes)); - } - protected void downloadMap(FeatureCollection operationalAreaFeature, String mapName) { OfflineMapHelper.downloadMap(operationalAreaFeature, mapName, getContext()); } @@ -102,13 +97,6 @@ public AppStructureRepository getAppStructureRepository() { return appStructureRepository; } - public AppLocationRepository getAppLocationRepository() { - if (appLocationRepository == null) { - appLocationRepository = EusmApplication.getInstance().getAppLocationRepository(); - } - return appLocationRepository; - } - public AppExecutors getAppExecutors() { if (appExecutors == null) { appExecutors = EusmApplication.getInstance().getAppExecutors(); @@ -118,11 +106,10 @@ public AppExecutors getAppExecutors() { @Override public void moveDownloadedOAToDownloadedList(String operationalAreaId) { - String regionId = EusmApplication.getInstance().getAppLocationRepository().getRegionIdForDistrictId(operationalAreaId).getId(); List toRemoveFromAvailableList = new ArrayList<>(); List toRemoveFromDownloadList = new ArrayList<>(); for (OfflineMapModel offlineMapModel : offlineMapModelList) { - if (offlineMapModel.getDownloadAreaId().equals(regionId)) { + if (offlineMapModel.getDownloadAreaId().equals(operationalAreaId)) { offlineMapModel.setOfflineMapStatus(OfflineMapModel.OfflineMapStatus.DOWNLOADED); callback.onMapDownloaded(offlineMapModel); toRemoveFromAvailableList.add(offlineMapModel); @@ -134,18 +121,6 @@ public void moveDownloadedOAToDownloadedList(String operationalAreaId) { operationalAreasToDownload.removeAll(toRemoveFromDownloadList); } - @Override - public void updateOperationalAreasToDownload(OfflineMapModel offlineMapModel) { - Set tags = offlineMapModel.getLocation().getLocationTags(); - for (LocationTag tag : tags) { - if (tag.getName().equalsIgnoreCase("district")) { - Location region = EusmApplication.getInstance().getAppLocationRepository().getRegionIdForDistrictId(offlineMapModel.getLocation().getId()); - offlineMapModel.setLocation(region); - } - } - super.updateOperationalAreasToDownload(offlineMapModel); - } - @Override public void updateOperationalAreasToDownload(View view) { CheckBox checkBox = (CheckBox) view; @@ -183,14 +158,38 @@ public void initiateMapDownload() { for (OfflineMapModel model : offlineMapModelList) { if (model.getOfflineMapStatus() == OfflineMapModel.OfflineMapStatus.DOWNLOAD_STARTED) { + displayToast(getString(R.string.another_map_in_download)); Timber.e("Error: A map download is already in progress"); return; } } for (Location location : this.operationalAreasToDownload) { - disableCheckBox(location.getId()); downloadLocation(location); } } + + @Override + public void displayToast(String message) { + if (displayBar == null) { + displayBar = Snackbar.make(requireView(), message, Snackbar.LENGTH_LONG); + displayBar.show(); + } else { + displayBar.setText(message); + displayBar.setDuration(Snackbar.LENGTH_LONG); + if (!displayBar.isShown()) + displayBar.show(); + } + } + + @Override + public void displayError(int title, String message) { + displayToast(message); + } + + @Override + protected void mapDeletedSuccessfully(String mapUniqueName) { + super.mapDeletedSuccessfully(mapUniqueName); + displayToast(getString(R.string.map_deleted, mapUniqueName)); + } } diff --git a/opensrp-eusm/src/main/java/org/smartregister/eusm/fragment/EusmDownloadedOfflineMapsFragment.java b/opensrp-eusm/src/main/java/org/smartregister/eusm/fragment/EusmDownloadedOfflineMapsFragment.java new file mode 100644 index 0000000..f042409 --- /dev/null +++ b/opensrp-eusm/src/main/java/org/smartregister/eusm/fragment/EusmDownloadedOfflineMapsFragment.java @@ -0,0 +1,32 @@ +package org.smartregister.eusm.fragment; + +import android.content.Context; +import android.os.Bundle; + +import androidx.annotation.NonNull; + +import org.smartregister.tasking.fragment.DownloadedOfflineMapsFragment; +import org.smartregister.tasking.presenter.DownloadedOfflineMapsPresenter; + +public class EusmDownloadedOfflineMapsFragment extends DownloadedOfflineMapsFragment { + + public static EusmDownloadedOfflineMapsFragment newInstance(Bundle bundle, @NonNull Context context) { + EusmDownloadedOfflineMapsFragment fragment = new EusmDownloadedOfflineMapsFragment(); + if (bundle != null) { + fragment.setArguments(bundle); + } + fragment.setPresenter(new DownloadedOfflineMapsPresenter(fragment, context)); + return fragment; + } + + @Override + public void displayToast(String message) { + // Do nothing + } + + @Override + public void displayError(int title, String message) { + // Do nothing + } + +} diff --git a/opensrp-eusm/src/main/java/org/smartregister/eusm/presenter/EUSMAvailableOfflineMapsPresenter.java b/opensrp-eusm/src/main/java/org/smartregister/eusm/presenter/EUSMAvailableOfflineMapsPresenter.java deleted file mode 100644 index 21928de..0000000 --- a/opensrp-eusm/src/main/java/org/smartregister/eusm/presenter/EUSMAvailableOfflineMapsPresenter.java +++ /dev/null @@ -1,34 +0,0 @@ -package org.smartregister.eusm.presenter; - -import org.smartregister.domain.Location; -import org.smartregister.eusm.application.EusmApplication; -import org.smartregister.tasking.contract.AvailableOfflineMapsContract; -import org.smartregister.tasking.presenter.AvailableOfflineMapsPresenter; - -import java.util.ArrayList; -import java.util.List; - -public class EUSMAvailableOfflineMapsPresenter extends AvailableOfflineMapsPresenter { - - public EUSMAvailableOfflineMapsPresenter(AvailableOfflineMapsContract.View view) { - super(view); - } - - @Override - public void fetchAvailableOAsForMapDownLoad(List locationIds) { - List regionIds = new ArrayList<>(); - if (locationIds != null) { - for (String districtId : locationIds) { - Location region = EusmApplication.getInstance().getAppLocationRepository().getRegionIdForDistrictId(districtId); - if (region != null) - regionIds.add(region.getId()); - } - } - super.fetchAvailableOAsForMapDownLoad(regionIds); - } - - @Override - public void onDownloadStarted(String operationalAreaId) { - // DO nothing - } -} diff --git a/opensrp-eusm/src/main/java/org/smartregister/eusm/repository/AppLocationRepository.java b/opensrp-eusm/src/main/java/org/smartregister/eusm/repository/AppLocationRepository.java index d3e6b19..bcfcfe4 100644 --- a/opensrp-eusm/src/main/java/org/smartregister/eusm/repository/AppLocationRepository.java +++ b/opensrp-eusm/src/main/java/org/smartregister/eusm/repository/AppLocationRepository.java @@ -84,30 +84,23 @@ public Set getLocationByNameAndGeoLevel(Set names, String leve } public Set getDistrictIdsForRegionId(String regionId) { + Cursor cursor = null; Set districts = new HashSet<>(); if (StringUtils.isBlank(regionId)) return districts; - try (Cursor cursor = getReadableDatabase().rawQuery("SELECT * FROM " + getLocationTableName() + - " WHERE " + PARENT_ID + " =? ", new String[]{regionId})) { - if (cursor.moveToFirst()) { + try { + cursor = getReadableDatabase().rawQuery("SELECT * FROM " + getLocationTableName() + + " WHERE " + PARENT_ID + " =? ", new String[]{regionId}); + while (cursor.moveToNext()) { districts.add(readCursor(cursor)); } + cursor.close(); } catch (SQLException e) { Timber.e(e); + } finally { + cursor.close(); } return districts; } - public Location getRegionIdForDistrictId(String districtId) { - try (Cursor cursor = getReadableDatabase().rawQuery("SELECT * FROM " + getLocationTableName() + - " WHERE " + ID + " IN (SELECT " + PARENT_ID + " FROM " + getLocationTableName() + " WHERE " + - ID + " =? )", new String[]{districtId})) { - if (cursor.moveToFirst()) { - return readCursor(cursor); - } - } catch (SQLException e) { - Timber.e(e); - } - return null; - } } diff --git a/opensrp-eusm/src/main/res/values/strings.xml b/opensrp-eusm/src/main/res/values/strings.xml index 0854fc0..7ff2692 100644 --- a/opensrp-eusm/src/main/res/values/strings.xml +++ b/opensrp-eusm/src/main/res/values/strings.xml @@ -156,5 +156,7 @@ Consult Beneficiaries Warehouse Check + Map Deleted: %1s + Another map is currently being downloaded. diff --git a/opensrp-eusm/src/test/java/org/smartregister/eusm/fragment/EusmAvailableOfflineMapsFragmentTest.java b/opensrp-eusm/src/test/java/org/smartregister/eusm/fragment/EusmAvailableOfflineMapsFragmentTest.java index af6efc5..819dc84 100644 --- a/opensrp-eusm/src/test/java/org/smartregister/eusm/fragment/EusmAvailableOfflineMapsFragmentTest.java +++ b/opensrp-eusm/src/test/java/org/smartregister/eusm/fragment/EusmAvailableOfflineMapsFragmentTest.java @@ -9,7 +9,6 @@ import org.robolectric.annotation.LooperMode; import org.smartregister.domain.Location; import org.smartregister.eusm.BaseUnitTest; -import org.smartregister.eusm.repository.AppLocationRepository; import org.smartregister.eusm.repository.AppStructureRepository; import java.util.Collections; @@ -41,20 +40,14 @@ public void setUp() throws Exception { public void testDownloadLocationShouldStartOfflineMap() { fragmentScenario.onFragment(fragment -> { EusmAvailableOfflineMapsFragment fragmentSpy = spy(fragment); - Location district = new Location(); - district.setId("4322-23"); - district.setType("Feature"); Location location = new Location(); - location.setId("4322-78"); + location.setId("4322-23"); location.setType("Feature"); doNothing().when(fragmentSpy).downloadMap(any(FeatureCollection.class), anyString()); AppStructureRepository appStructureRepository = mock(AppStructureRepository.class); - AppLocationRepository appLocationRepository = mock(AppLocationRepository.class); doReturn(appStructureRepository).when(fragmentSpy).getAppStructureRepository(); - doReturn(appLocationRepository).when(fragmentSpy).getAppLocationRepository(); - doReturn(Collections.singletonList(district)).when(appStructureRepository).getStructuresByDistrictId(anyString()); - doReturn(Collections.singleton(location)).when(appLocationRepository).getDistrictIdsForRegionId(anyString()); - doNothing().when(fragmentSpy).showToast(anyInt()); + doReturn(Collections.singletonList(location)).when(appStructureRepository).getStructuresByDistrictId(anyString()); + doNothing().when(fragmentSpy).displayToast(anyString()); fragmentSpy.downloadLocation(location); shadowOf(getMainLooper()).idle(); try { From 635729766b4718ae65aff9547bfaf2d89c52c2be Mon Sep 17 00:00:00 2001 From: Hamza Ahmed Khan Date: Thu, 16 Feb 2023 18:11:32 +0500 Subject: [PATCH 06/11] Eliminate UI bugs --- .../EUSMDownloadedOfflineMapAdapter.java | 52 +++++++ .../EusmAvailableOfflineMapsFragment.java | 9 +- .../EusmDownloadedOfflineMapsFragment.java | 137 +++++++++++++++++- .../repository/AppStructureRepository.java | 4 +- opensrp-eusm/src/main/res/values/strings.xml | 1 + 5 files changed, 195 insertions(+), 8 deletions(-) create mode 100644 opensrp-eusm/src/main/java/org/smartregister/eusm/adapter/EUSMDownloadedOfflineMapAdapter.java diff --git a/opensrp-eusm/src/main/java/org/smartregister/eusm/adapter/EUSMDownloadedOfflineMapAdapter.java b/opensrp-eusm/src/main/java/org/smartregister/eusm/adapter/EUSMDownloadedOfflineMapAdapter.java new file mode 100644 index 0000000..a0604b6 --- /dev/null +++ b/opensrp-eusm/src/main/java/org/smartregister/eusm/adapter/EUSMDownloadedOfflineMapAdapter.java @@ -0,0 +1,52 @@ +package org.smartregister.eusm.adapter; + +import android.content.Context; +import android.view.View; + +import androidx.annotation.NonNull; + +import org.smartregister.tasking.adapter.DownloadedOfflineMapAdapter; +import org.smartregister.tasking.model.OfflineMapModel; +import org.smartregister.tasking.viewholder.DownloadedOfflineMapViewHolder; + +import java.util.ArrayList; +import java.util.List; + +public class EUSMDownloadedOfflineMapAdapter extends DownloadedOfflineMapAdapter { + + private List offlineMapModels = new ArrayList<>(); + + public EUSMDownloadedOfflineMapAdapter(Context context, View.OnClickListener offlineMapClickHandler) { + super(context, offlineMapClickHandler); + } + + @Override + public void setOfflineMapModels(List offlineMapModels) { + this.offlineMapModels = offlineMapModels; + super.setOfflineMapModels(offlineMapModels); + } + + @Override + public void onBindViewHolder(@NonNull DownloadedOfflineMapViewHolder viewHolder, int position) { + super.onBindViewHolder(viewHolder, position); + OfflineMapModel offlineMapModel = offlineMapModels.get(position); + + switch (offlineMapModel.getOfflineMapStatus()) { + case READY: + case DOWNLOADED: + viewHolder.checkCheckBox(false); + viewHolder.enableCheckBox(true); + break; + case SELECTED_FOR_DOWNLOAD: + viewHolder.checkCheckBox(true); + break; + case DOWNLOAD_STARTED: + viewHolder.checkCheckBox(true); + viewHolder.enableCheckBox(false); + break; + default: + break; + + } + } +} diff --git a/opensrp-eusm/src/main/java/org/smartregister/eusm/fragment/EusmAvailableOfflineMapsFragment.java b/opensrp-eusm/src/main/java/org/smartregister/eusm/fragment/EusmAvailableOfflineMapsFragment.java index 571828b..1996498 100644 --- a/opensrp-eusm/src/main/java/org/smartregister/eusm/fragment/EusmAvailableOfflineMapsFragment.java +++ b/opensrp-eusm/src/main/java/org/smartregister/eusm/fragment/EusmAvailableOfflineMapsFragment.java @@ -36,7 +36,7 @@ public class EusmAvailableOfflineMapsFragment extends AvailableOfflineMapsFragme private List offlineMapModelList = new ArrayList<>(); - private List operationalAreasToDownload = new ArrayList<>(); + private final List operationalAreasToDownload = new ArrayList<>(); private Snackbar displayBar = null; @@ -110,7 +110,7 @@ public void moveDownloadedOAToDownloadedList(String operationalAreaId) { List toRemoveFromDownloadList = new ArrayList<>(); for (OfflineMapModel offlineMapModel : offlineMapModelList) { if (offlineMapModel.getDownloadAreaId().equals(operationalAreaId)) { - offlineMapModel.setOfflineMapStatus(OfflineMapModel.OfflineMapStatus.DOWNLOADED); + offlineMapModel.setOfflineMapStatus(OfflineMapModel.OfflineMapStatus.READY); callback.onMapDownloaded(offlineMapModel); toRemoveFromAvailableList.add(offlineMapModel); toRemoveFromDownloadList.add(offlineMapModel.getLocation()); @@ -151,7 +151,7 @@ public void setOfflineMapModelList(List offlineMapModelList) { @Override public void initiateMapDownload() { - if (this.operationalAreasToDownload == null || this.operationalAreasToDownload.isEmpty()) { + if (this.operationalAreasToDownload.isEmpty()) { displayToast(getString(R.string.select_offline_map_to_download)); return; } @@ -177,8 +177,7 @@ public void displayToast(String message) { } else { displayBar.setText(message); displayBar.setDuration(Snackbar.LENGTH_LONG); - if (!displayBar.isShown()) - displayBar.show(); + displayBar.show(); } } diff --git a/opensrp-eusm/src/main/java/org/smartregister/eusm/fragment/EusmDownloadedOfflineMapsFragment.java b/opensrp-eusm/src/main/java/org/smartregister/eusm/fragment/EusmDownloadedOfflineMapsFragment.java index f042409..5767834 100644 --- a/opensrp-eusm/src/main/java/org/smartregister/eusm/fragment/EusmDownloadedOfflineMapsFragment.java +++ b/opensrp-eusm/src/main/java/org/smartregister/eusm/fragment/EusmDownloadedOfflineMapsFragment.java @@ -2,23 +2,51 @@ import android.content.Context; import android.os.Bundle; +import android.view.View; +import android.widget.Button; +import android.widget.CheckBox; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.core.content.ContextCompat; +import androidx.recyclerview.widget.RecyclerView; +import com.google.android.material.snackbar.Snackbar; + +import org.smartregister.eusm.R; +import org.smartregister.eusm.adapter.EUSMDownloadedOfflineMapAdapter; +import org.smartregister.tasking.TaskingLibrary; +import org.smartregister.tasking.contract.OfflineMapDownloadCallback; import org.smartregister.tasking.fragment.DownloadedOfflineMapsFragment; +import org.smartregister.tasking.model.OfflineMapModel; import org.smartregister.tasking.presenter.DownloadedOfflineMapsPresenter; +import java.util.ArrayList; +import java.util.List; + +import io.ona.kujaku.helpers.OfflineServiceHelper; + public class EusmDownloadedOfflineMapsFragment extends DownloadedOfflineMapsFragment { + + private EUSMDownloadedOfflineMapAdapter adapter; + + private List downloadedOfflineMapModelList = new ArrayList<>(); + + private static DownloadedOfflineMapsPresenter fragmentPresenter = null; + + private OfflineMapDownloadCallback callback; + public static EusmDownloadedOfflineMapsFragment newInstance(Bundle bundle, @NonNull Context context) { EusmDownloadedOfflineMapsFragment fragment = new EusmDownloadedOfflineMapsFragment(); if (bundle != null) { fragment.setArguments(bundle); } - fragment.setPresenter(new DownloadedOfflineMapsPresenter(fragment, context)); + fragmentPresenter = new DownloadedOfflineMapsPresenter(fragment, context); + fragment.setPresenter(fragmentPresenter); return fragment; } - + @Override public void displayToast(String message) { // Do nothing @@ -29,4 +57,109 @@ public void displayError(int title, String message) { // Do nothing } + @Override + public void setDownloadedOfflineMapModelList(List downloadedOfflineMapModelList) { + if (adapter == null) { + this.downloadedOfflineMapModelList = downloadedOfflineMapModelList; + } else { + adapter.setOfflineMapModels(downloadedOfflineMapModelList); + this.downloadedOfflineMapModelList = downloadedOfflineMapModelList; + } + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + RecyclerView downloadedMapsRecyclerView = view.findViewById(R.id.offline_map_recyclerView); + initAdapter(downloadedMapsRecyclerView); + + Button btnDeleteMap = view.findViewById(R.id.download_map); + btnDeleteMap.setText(getString(R.string.delete).toUpperCase()); + btnDeleteMap.setBackground(ContextCompat.getDrawable(requireContext(), R.drawable.delete_map_bg)); + + btnDeleteMap.setOnClickListener(v -> { + List mapsToDownload = new ArrayList<>(); + for (OfflineMapModel offlineMapModel : downloadedOfflineMapModelList) { + if (offlineMapModel.getOfflineMapStatus().equals(OfflineMapModel.OfflineMapStatus.SELECTED_FOR_DOWNLOAD)) { + mapsToDownload.add(offlineMapModel); + } + } + + if (mapsToDownload.isEmpty()) { + Snackbar.make(requireView(), getString(R.string.select_offline_map_to_delete), Snackbar.LENGTH_LONG).show(); + return; + } + fragmentPresenter.onDeleteDownloadMap(mapsToDownload); + }); + } + + private void initAdapter(RecyclerView downloadedMapsRecyclerView) { + adapter = new EUSMDownloadedOfflineMapAdapter(this.getContext(), this); + downloadedMapsRecyclerView.setAdapter(adapter); + if (downloadedOfflineMapModelList != null) { + setDownloadedOfflineMapModelList(downloadedOfflineMapModelList); + } + } + + @Override + public void updateOfflineMapsTodelete(View view) { + CheckBox checkBox = (CheckBox) view; + OfflineMapModel offlineMapModel = (OfflineMapModel) view.getTag(R.id.offline_map_checkbox); + + if (checkBox.isChecked()) { + for (OfflineMapModel model : downloadedOfflineMapModelList) { + if (model.getDownloadAreaId().equals(offlineMapModel.getDownloadAreaId())) { + model.setOfflineMapStatus(OfflineMapModel.OfflineMapStatus.SELECTED_FOR_DOWNLOAD); + } + } + } else { + for (OfflineMapModel model : downloadedOfflineMapModelList) { + if (model.getDownloadAreaId().equals(offlineMapModel.getDownloadAreaId())) { + model.setOfflineMapStatus(OfflineMapModel.OfflineMapStatus.READY); + } + } + } + + setDownloadedOfflineMapModelList(downloadedOfflineMapModelList); + } + + @Override + public void onDestroy() { + super.onDestroy(); + fragmentPresenter = null; + } + + @Override + public void deleteDownloadedOfflineMaps() { + Snackbar.make(requireView(), getString(R.string.deleting_map), Snackbar.LENGTH_LONG).show(); + + for (OfflineMapModel offlineMapModel : downloadedOfflineMapModelList) { + if (offlineMapModel.getOfflineMapStatus().equals(OfflineMapModel.OfflineMapStatus.SELECTED_FOR_DOWNLOAD)) { + offlineMapModel.setOfflineMapStatus(OfflineMapModel.OfflineMapStatus.DOWNLOAD_STARTED); + OfflineServiceHelper.deleteOfflineMap(requireActivity(), + offlineMapModel.getDownloadAreaId(), + TaskingLibrary.getInstance().getMapboxAccessToken()); + } + } + setDownloadedOfflineMapModelList(downloadedOfflineMapModelList); + } + + @Override + public void setOfflineMapDownloadCallback(OfflineMapDownloadCallback callBack) { + this.callback = callBack; + } + + @Override + protected void mapDeletedSuccessfully(String deletedMapName) { + List toRemove = new ArrayList<>(); + for (OfflineMapModel offlineMapModel : downloadedOfflineMapModelList) { + if (offlineMapModel.getDownloadAreaId().equals(deletedMapName)) { + toRemove.add(offlineMapModel); + offlineMapModel.setOfflineMapStatus(OfflineMapModel.OfflineMapStatus.READY); + callback.onOfflineMapDeleted(offlineMapModel); + } + } + downloadedOfflineMapModelList.removeAll(toRemove); + setDownloadedOfflineMapModelList(downloadedOfflineMapModelList); + } } diff --git a/opensrp-eusm/src/main/java/org/smartregister/eusm/repository/AppStructureRepository.java b/opensrp-eusm/src/main/java/org/smartregister/eusm/repository/AppStructureRepository.java index 436b1cd..5eb1b9f 100644 --- a/opensrp-eusm/src/main/java/org/smartregister/eusm/repository/AppStructureRepository.java +++ b/opensrp-eusm/src/main/java/org/smartregister/eusm/repository/AppStructureRepository.java @@ -272,7 +272,9 @@ public List getStructuresByDistrictId(String }; String query = "SELECT " + StringUtils.join(columns, ",") + " from " + StructureRepository.STRUCTURE_TABLE - + " join location on location._id = " + StructureRepository.STRUCTURE_TABLE + ".parent_id "; + + " join location on location._id = " + StructureRepository.STRUCTURE_TABLE + ".parent_id" + + " AND " + StructureRepository.STRUCTURE_TABLE + "." + LATITUDE + " IS NOT NULL " + + " AND " + StructureRepository.STRUCTURE_TABLE + "." + LONGITUDE + " IS NOT NULL"; String[] args = new String[]{districtId}; diff --git a/opensrp-eusm/src/main/res/values/strings.xml b/opensrp-eusm/src/main/res/values/strings.xml index 7ff2692..95c8a7c 100644 --- a/opensrp-eusm/src/main/res/values/strings.xml +++ b/opensrp-eusm/src/main/res/values/strings.xml @@ -158,5 +158,6 @@ Warehouse Check Map Deleted: %1s Another map is currently being downloaded. + Deleting map From fc43da7209025dce3d06acb080c1bbdf5c5827fb Mon Sep 17 00:00:00 2001 From: Hamza Ahmed Khan Date: Mon, 20 Feb 2023 13:26:00 +0500 Subject: [PATCH 07/11] Code Cleanup + Test Coverage --- .../EusmDownloadedOfflineMapsFragment.java | 49 +++-- .../EusmAvailableOfflineMapsFragmentTest.java | 178 +++++++++++++++- ...EusmDownloadedOfflineMapsFragmentTest.java | 191 ++++++++++++++++++ 3 files changed, 396 insertions(+), 22 deletions(-) create mode 100644 opensrp-eusm/src/test/java/org/smartregister/eusm/fragment/EusmDownloadedOfflineMapsFragmentTest.java diff --git a/opensrp-eusm/src/main/java/org/smartregister/eusm/fragment/EusmDownloadedOfflineMapsFragment.java b/opensrp-eusm/src/main/java/org/smartregister/eusm/fragment/EusmDownloadedOfflineMapsFragment.java index 5767834..faae93d 100644 --- a/opensrp-eusm/src/main/java/org/smartregister/eusm/fragment/EusmDownloadedOfflineMapsFragment.java +++ b/opensrp-eusm/src/main/java/org/smartregister/eusm/fragment/EusmDownloadedOfflineMapsFragment.java @@ -70,6 +70,10 @@ public void setDownloadedOfflineMapModelList(List downloadedOff @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); + setUpViews(view); + } + + protected void setUpViews(View view) { RecyclerView downloadedMapsRecyclerView = view.findViewById(R.id.offline_map_recyclerView); initAdapter(downloadedMapsRecyclerView); @@ -77,20 +81,22 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat btnDeleteMap.setText(getString(R.string.delete).toUpperCase()); btnDeleteMap.setBackground(ContextCompat.getDrawable(requireContext(), R.drawable.delete_map_bg)); - btnDeleteMap.setOnClickListener(v -> { - List mapsToDownload = new ArrayList<>(); - for (OfflineMapModel offlineMapModel : downloadedOfflineMapModelList) { - if (offlineMapModel.getOfflineMapStatus().equals(OfflineMapModel.OfflineMapStatus.SELECTED_FOR_DOWNLOAD)) { - mapsToDownload.add(offlineMapModel); - } - } + btnDeleteMap.setOnClickListener(v -> startDeleteProcess()); + } - if (mapsToDownload.isEmpty()) { - Snackbar.make(requireView(), getString(R.string.select_offline_map_to_delete), Snackbar.LENGTH_LONG).show(); - return; + protected void startDeleteProcess() { + List mapsToDownload = new ArrayList<>(); + for (OfflineMapModel offlineMapModel : downloadedOfflineMapModelList) { + if (offlineMapModel.getOfflineMapStatus().equals(OfflineMapModel.OfflineMapStatus.SELECTED_FOR_DOWNLOAD)) { + mapsToDownload.add(offlineMapModel); } - fragmentPresenter.onDeleteDownloadMap(mapsToDownload); - }); + } + + if (mapsToDownload.isEmpty()) { + displaySnackBar(getString(R.string.select_offline_map_to_delete)); + return; + } + fragmentPresenter.onDeleteDownloadMap(mapsToDownload); } private void initAdapter(RecyclerView downloadedMapsRecyclerView) { @@ -106,15 +112,11 @@ public void updateOfflineMapsTodelete(View view) { CheckBox checkBox = (CheckBox) view; OfflineMapModel offlineMapModel = (OfflineMapModel) view.getTag(R.id.offline_map_checkbox); - if (checkBox.isChecked()) { - for (OfflineMapModel model : downloadedOfflineMapModelList) { - if (model.getDownloadAreaId().equals(offlineMapModel.getDownloadAreaId())) { + for (OfflineMapModel model : downloadedOfflineMapModelList) { + if (model.getDownloadAreaId().equals(offlineMapModel.getDownloadAreaId())) { + if (checkBox.isChecked()) { model.setOfflineMapStatus(OfflineMapModel.OfflineMapStatus.SELECTED_FOR_DOWNLOAD); - } - } - } else { - for (OfflineMapModel model : downloadedOfflineMapModelList) { - if (model.getDownloadAreaId().equals(offlineMapModel.getDownloadAreaId())) { + } else { model.setOfflineMapStatus(OfflineMapModel.OfflineMapStatus.READY); } } @@ -131,7 +133,7 @@ public void onDestroy() { @Override public void deleteDownloadedOfflineMaps() { - Snackbar.make(requireView(), getString(R.string.deleting_map), Snackbar.LENGTH_LONG).show(); + displaySnackBar(getString(R.string.deleting_map)); for (OfflineMapModel offlineMapModel : downloadedOfflineMapModelList) { if (offlineMapModel.getOfflineMapStatus().equals(OfflineMapModel.OfflineMapStatus.SELECTED_FOR_DOWNLOAD)) { @@ -162,4 +164,9 @@ protected void mapDeletedSuccessfully(String deletedMapName) { downloadedOfflineMapModelList.removeAll(toRemove); setDownloadedOfflineMapModelList(downloadedOfflineMapModelList); } + + protected void displaySnackBar(String message) { + Snackbar.make(requireView(), message, Snackbar.LENGTH_LONG).show(); + } + } diff --git a/opensrp-eusm/src/test/java/org/smartregister/eusm/fragment/EusmAvailableOfflineMapsFragmentTest.java b/opensrp-eusm/src/test/java/org/smartregister/eusm/fragment/EusmAvailableOfflineMapsFragmentTest.java index 819dc84..5560949 100644 --- a/opensrp-eusm/src/test/java/org/smartregister/eusm/fragment/EusmAvailableOfflineMapsFragmentTest.java +++ b/opensrp-eusm/src/test/java/org/smartregister/eusm/fragment/EusmAvailableOfflineMapsFragmentTest.java @@ -4,28 +4,38 @@ import com.mapbox.geojson.FeatureCollection; +import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.robolectric.annotation.LooperMode; +import org.robolectric.util.ReflectionHelpers; import org.smartregister.domain.Location; import org.smartregister.eusm.BaseUnitTest; +import org.smartregister.eusm.R; import org.smartregister.eusm.repository.AppStructureRepository; +import org.smartregister.tasking.contract.OfflineMapDownloadCallback; +import org.smartregister.tasking.model.OfflineMapModel; +import org.smartregister.util.AppExecutors; +import java.util.ArrayList; import java.util.Collections; +import java.util.List; import static android.os.Looper.getMainLooper; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.robolectric.Shadows.shadowOf; import static org.robolectric.annotation.LooperMode.Mode.PAUSED; +import android.widget.CheckBox; + @LooperMode(PAUSED) public class EusmAvailableOfflineMapsFragmentTest extends BaseUnitTest { @@ -36,8 +46,27 @@ public void setUp() throws Exception { fragmentScenario = FragmentScenario.launch(EusmAvailableOfflineMapsFragment.class); } + @Test + public void testGetAppStructureRepositoryNotNull() { + Assert.assertNotNull(fragmentScenario); // To remove codacy error for assertion + fragmentScenario.onFragment(fragment -> { + AppStructureRepository repository = fragment.getAppStructureRepository(); + Assert.assertNotNull(repository); + }); + } + + @Test + public void testGetAppExecutors() { + Assert.assertNotNull(fragmentScenario); // To remove codacy error for assertion + fragmentScenario.onFragment(fragment -> { + AppExecutors appExecutors = fragment.getAppExecutors(); + Assert.assertNotNull(appExecutors); + }); + } + @Test public void testDownloadLocationShouldStartOfflineMap() { + Assert.assertNotNull(fragmentScenario); // To remove codacy error for assertion fragmentScenario.onFragment(fragment -> { EusmAvailableOfflineMapsFragment fragmentSpy = spy(fragment); Location location = new Location(); @@ -60,4 +89,151 @@ public void testDownloadLocationShouldStartOfflineMap() { }); } + @Test + public void testDownloadLocationShouldReturnWhenNoStructuresForLocation() { + Assert.assertNotNull(fragmentScenario); // To remove codacy error for assertion + fragmentScenario.onFragment(fragment -> { + EusmAvailableOfflineMapsFragment fragmentSpy = spy(fragment); + doNothing().when(fragmentSpy).downloadMap(any(FeatureCollection.class), anyString()); + AppStructureRepository appStructureRepository = mock(AppStructureRepository.class); + doReturn(appStructureRepository).when(fragmentSpy).getAppStructureRepository(); + doReturn(Collections.singletonList(new ArrayList())).when(appStructureRepository).getStructuresByDistrictId(anyString()); + doNothing().when(fragmentSpy).displayToast(anyString()); + + OfflineMapModel offlineMapModel = new OfflineMapModel(); + offlineMapModel.setOfflineMapStatus(OfflineMapModel.OfflineMapStatus.DOWNLOAD_STARTED); + List offlineMapModelList = new ArrayList<>(); + offlineMapModelList.add(offlineMapModel); + ReflectionHelpers.setField(fragmentSpy, "offlineMapModelList", offlineMapModelList); + + fragmentSpy.downloadLocation(new Location()); + + shadowOf(getMainLooper()).idle(); + try { + Thread.sleep(ASYNC_TIMEOUT); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + List offlineMapModelListProcessed = ReflectionHelpers.getField(fragmentSpy, "offlineMapModelList"); + Assert.assertEquals(OfflineMapModel.OfflineMapStatus.READY, offlineMapModelListProcessed.get(0).getOfflineMapStatus()); + }); + } + + @Test + public void testMoveDownloadedOAToDownloadedListRemovesItMapFromList() { + Assert.assertNotNull(fragmentScenario); // To remove codacy error for assertion + fragmentScenario.onFragment(fragment -> { + EusmAvailableOfflineMapsFragment fragmentSpy = spy(fragment); + + Location location = new Location(); + location.setId("4322-23"); + location.setType("Feature"); + List operationalAreasToDownload = new ArrayList<>(); + operationalAreasToDownload.add(location); + ReflectionHelpers.setField(fragmentSpy, "operationalAreasToDownload", operationalAreasToDownload); + + OfflineMapModel offlineMapModel = new OfflineMapModel(); + offlineMapModel.setOfflineMapStatus(OfflineMapModel.OfflineMapStatus.DOWNLOAD_STARTED); + offlineMapModel.setLocation(location); + List offlineMapModelList = new ArrayList<>(); + offlineMapModelList.add(offlineMapModel); + ReflectionHelpers.setField(fragmentSpy, "offlineMapModelList", offlineMapModelList); + + OfflineMapDownloadCallback callback = mock(OfflineMapDownloadCallback.class); + doNothing().when(callback).onMapDownloaded(any()); + ReflectionHelpers.setField(fragmentSpy, "callback", callback); + + fragmentSpy.moveDownloadedOAToDownloadedList("4322-23"); + + List offlineMapModelListProcessed = ReflectionHelpers.getField(fragmentSpy, "offlineMapModelList"); + Assert.assertEquals(OfflineMapModel.OfflineMapStatus.READY, offlineMapModelListProcessed.get(0).getOfflineMapStatus()); + List operationalAreasToDownloadProcessed = ReflectionHelpers.getField(fragmentSpy, "operationalAreasToDownload"); + Assert.assertEquals(0, operationalAreasToDownloadProcessed.size()); + }); + } + + @Test + public void testUpdateOperationalAreasToDownloadShouldSelectSingleMapAtOneTIme() { + Assert.assertNotNull(fragmentScenario); // To remove codacy error for assertion + fragmentScenario.onFragment(fragment -> { + EusmAvailableOfflineMapsFragment fragmentSpy = spy(fragment); + + Location location1 = new Location(); + location1.setId("4322-23"); + location1.setType("Feature"); + Location location2 = new Location(); + location2.setId("4322-24"); + location2.setType("Feature"); + + List operationalAreasToDownload = new ArrayList<>(); + operationalAreasToDownload.add(location1); + operationalAreasToDownload.add(location2); + ReflectionHelpers.setField(fragmentSpy, "operationalAreasToDownload", operationalAreasToDownload); + + OfflineMapModel offlineMapModel = new OfflineMapModel(); + offlineMapModel.setOfflineMapStatus(OfflineMapModel.OfflineMapStatus.READY); + offlineMapModel.setLocation(location1); + OfflineMapModel offlineMapModel2 = new OfflineMapModel(); + offlineMapModel2.setOfflineMapStatus(OfflineMapModel.OfflineMapStatus.SELECTED_FOR_DOWNLOAD); + offlineMapModel2.setLocation(location2); + + CheckBox checkBox = mock(CheckBox.class); + doReturn(true).when(checkBox).isChecked(); + doReturn(offlineMapModel).when(checkBox).getTag(eq(R.id.offline_map_checkbox)); + + List offlineMapModelList = new ArrayList<>(); + offlineMapModelList.add(offlineMapModel); + offlineMapModelList.add(offlineMapModel2); + ReflectionHelpers.setField(fragmentSpy, "offlineMapModelList", offlineMapModelList); + + fragmentSpy.updateOperationalAreasToDownload(checkBox); + + List offlineMapModelListProcessed = ReflectionHelpers.getField(fragmentSpy, "offlineMapModelList"); + for (OfflineMapModel model : offlineMapModelListProcessed) { + if (model.getDownloadAreaId().equals(offlineMapModel.getDownloadAreaId())){ + Assert.assertEquals(OfflineMapModel.OfflineMapStatus.SELECTED_FOR_DOWNLOAD, model.getOfflineMapStatus()); + } else if (model.getDownloadAreaId().equals(offlineMapModel2.getDownloadAreaId())){ + Assert.assertEquals(OfflineMapModel.OfflineMapStatus.READY, model.getOfflineMapStatus()); + } + } + + doReturn(false).when(checkBox).isChecked(); + operationalAreasToDownload.clear(); + operationalAreasToDownload.add(location1); + operationalAreasToDownload.add(location2); + ReflectionHelpers.setField(fragmentSpy, "operationalAreasToDownload", operationalAreasToDownload); + fragmentSpy.updateOperationalAreasToDownload(checkBox); + + List operationalAreasToDownloadProcessed = ReflectionHelpers.getField(fragmentSpy, "operationalAreasToDownload"); + Assert.assertEquals(1, operationalAreasToDownloadProcessed.size()); + }); + } + + @Test + public void testInitiateMapDownloadShouldNotDownloadIfAnotherMapInProgress() { + Assert.assertNotNull(fragmentScenario); // To remove codacy error for assertion + fragmentScenario.onFragment(fragment -> { + EusmAvailableOfflineMapsFragment fragmentSpy = spy(fragment); + doNothing().when(fragmentSpy).displayToast(anyString()); + + Location location = new Location(); + location.setId("4322-23"); + location.setType("Feature"); + List operationalAreasToDownload = new ArrayList<>(); + operationalAreasToDownload.add(location); + ReflectionHelpers.setField(fragmentSpy, "operationalAreasToDownload", operationalAreasToDownload); + + OfflineMapModel offlineMapModel = new OfflineMapModel(); + offlineMapModel.setOfflineMapStatus(OfflineMapModel.OfflineMapStatus.DOWNLOAD_STARTED); + offlineMapModel.setLocation(location); + List offlineMapModelList = new ArrayList<>(); + offlineMapModelList.add(offlineMapModel); + ReflectionHelpers.setField(fragmentSpy, "offlineMapModelList", offlineMapModelList); + + fragmentSpy.initiateMapDownload(); + verify(fragmentSpy, times(1)).displayToast(anyString()); + }); + } + } \ No newline at end of file diff --git a/opensrp-eusm/src/test/java/org/smartregister/eusm/fragment/EusmDownloadedOfflineMapsFragmentTest.java b/opensrp-eusm/src/test/java/org/smartregister/eusm/fragment/EusmDownloadedOfflineMapsFragmentTest.java new file mode 100644 index 0000000..d84aefd --- /dev/null +++ b/opensrp-eusm/src/test/java/org/smartregister/eusm/fragment/EusmDownloadedOfflineMapsFragmentTest.java @@ -0,0 +1,191 @@ +package org.smartregister.eusm.fragment; + +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; +import static org.robolectric.annotation.LooperMode.Mode.PAUSED; + +import android.content.Context; +import android.view.View; +import android.widget.Button; +import android.widget.CheckBox; + +import androidx.fragment.app.FragmentActivity; +import androidx.recyclerview.widget.RecyclerView; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.robolectric.annotation.LooperMode; +import org.robolectric.util.ReflectionHelpers; +import org.smartregister.domain.Location; +import org.smartregister.eusm.BaseUnitTest; +import org.smartregister.eusm.R; +import org.smartregister.tasking.contract.OfflineMapDownloadCallback; +import org.smartregister.tasking.model.OfflineMapModel; +import org.smartregister.tasking.presenter.DownloadedOfflineMapsPresenter; + +import java.util.ArrayList; +import java.util.List; + +@LooperMode(PAUSED) +public class EusmDownloadedOfflineMapsFragmentTest extends BaseUnitTest { + + private EusmDownloadedOfflineMapsFragment fragment; + + @Before + public void setUp() { + fragment = new EusmDownloadedOfflineMapsFragment(); + } + + @Test + public void testSetUpViewsShouldInitAdapter() { + EusmDownloadedOfflineMapsFragment fragmentSpy = spy(fragment); + doReturn(mock(Context.class)).when(fragmentSpy).requireContext(); + + View view = mock(View.class); + + RecyclerView recyclerView = mock(RecyclerView.class); + doReturn(recyclerView).when(view).findViewById(eq(R.id.offline_map_recyclerView)); + + Button btnDeleteMap = mock(Button.class); + doReturn(btnDeleteMap).when(view).findViewById(eq(R.id.download_map)); + doReturn("").when(fragmentSpy).getString(anyInt()); + fragmentSpy.setUpViews(view); + + Assert.assertNotNull(ReflectionHelpers.getField(fragmentSpy, "adapter")); + } + + @Test + public void testStartDeleteProcessShouldStartDeletingSelectedMaps() { + EusmDownloadedOfflineMapsFragment fragmentSpy = spy(fragment); + DownloadedOfflineMapsPresenter presenter = mock(DownloadedOfflineMapsPresenter.class); + ReflectionHelpers.setField(fragmentSpy, "fragmentPresenter", presenter); + + List downloadedOfflineMapModelList = new ArrayList<>(); + OfflineMapModel offlineMapModel1 = new OfflineMapModel(); + offlineMapModel1.setOfflineMapStatus(OfflineMapModel.OfflineMapStatus.SELECTED_FOR_DOWNLOAD); + OfflineMapModel offlineMapModel2 = new OfflineMapModel(); + offlineMapModel2.setOfflineMapStatus(OfflineMapModel.OfflineMapStatus.READY); + ReflectionHelpers.setField(fragmentSpy, "downloadedOfflineMapModelList", downloadedOfflineMapModelList); + doReturn("").when(fragmentSpy).getString(anyInt()); + doNothing().when(fragmentSpy).displaySnackBar(anyString()); + fragmentSpy.startDeleteProcess(); + verifyNoInteractions(presenter); + + downloadedOfflineMapModelList.add(offlineMapModel2); + downloadedOfflineMapModelList.add(offlineMapModel1); + ReflectionHelpers.setField(fragmentSpy, "downloadedOfflineMapModelList", downloadedOfflineMapModelList); + fragmentSpy.startDeleteProcess(); + + List mapsToDownload = new ArrayList<>(); + mapsToDownload.add(offlineMapModel1); + verify(presenter, times(1)).onDeleteDownloadMap(eq(mapsToDownload)); + } + + @Test + public void testUpdateOfflineMapsTodeleteShouldMarkSelectedForDownloadWHenChecked() { + EusmDownloadedOfflineMapsFragment fragmentSpy = spy(fragment); + + Location location = new Location(); + location.setId("4322-23"); + location.setType("Feature"); + + OfflineMapModel offlineMapModel = new OfflineMapModel(); + offlineMapModel.setOfflineMapStatus(OfflineMapModel.OfflineMapStatus.READY); + offlineMapModel.setLocation(location); + + List downloadedOfflineMapModelList = new ArrayList<>(); + downloadedOfflineMapModelList.add(offlineMapModel); + ReflectionHelpers.setField(fragmentSpy, "downloadedOfflineMapModelList", downloadedOfflineMapModelList); + + CheckBox checkBox = mock(CheckBox.class); + doReturn(true).when(checkBox).isChecked(); + doReturn(offlineMapModel).when(checkBox).getTag(eq(R.id.offline_map_checkbox)); + + fragmentSpy.updateOfflineMapsTodelete(checkBox); + List downloadedOfflineMapModelListProcessed = ReflectionHelpers.getField(fragmentSpy, "downloadedOfflineMapModelList"); + Assert.assertEquals(OfflineMapModel.OfflineMapStatus.SELECTED_FOR_DOWNLOAD, downloadedOfflineMapModelListProcessed.get(0).getOfflineMapStatus()); + } + + @Test + public void testUpdateOfflineMapsTodeleteShouldMarkSReadyWHenUnChecked() { + EusmDownloadedOfflineMapsFragment fragmentSpy = spy(fragment); + + Location location = new Location(); + location.setId("4322-23"); + location.setType("Feature"); + + OfflineMapModel offlineMapModel = new OfflineMapModel(); + offlineMapModel.setOfflineMapStatus(OfflineMapModel.OfflineMapStatus.SELECTED_FOR_DOWNLOAD); + offlineMapModel.setLocation(location); + + List downloadedOfflineMapModelList = new ArrayList<>(); + downloadedOfflineMapModelList.add(offlineMapModel); + ReflectionHelpers.setField(fragmentSpy, "downloadedOfflineMapModelList", downloadedOfflineMapModelList); + + CheckBox checkBox = mock(CheckBox.class); + doReturn(false).when(checkBox).isChecked(); + doReturn(offlineMapModel).when(checkBox).getTag(eq(R.id.offline_map_checkbox)); + + fragmentSpy.updateOfflineMapsTodelete(checkBox); + List downloadedOfflineMapModelListProcessed = ReflectionHelpers.getField(fragmentSpy, "downloadedOfflineMapModelList"); + Assert.assertEquals(OfflineMapModel.OfflineMapStatus.READY, downloadedOfflineMapModelListProcessed.get(0).getOfflineMapStatus()); + } + + @Test + public void testDeleteDownloadedOfflineMapsShouldMarkSelectedForDownloadAsDownloadStarted() { + EusmDownloadedOfflineMapsFragment fragmentSpy = spy(fragment); + Location location = new Location(); + location.setId("4322-23"); + location.setType("Feature"); + + OfflineMapModel offlineMapModel = new OfflineMapModel(); + offlineMapModel.setOfflineMapStatus(OfflineMapModel.OfflineMapStatus.SELECTED_FOR_DOWNLOAD); + offlineMapModel.setLocation(location); + + List downloadedOfflineMapModelList = new ArrayList<>(); + downloadedOfflineMapModelList.add(offlineMapModel); + ReflectionHelpers.setField(fragmentSpy, "downloadedOfflineMapModelList", downloadedOfflineMapModelList); + + doReturn("").when(fragmentSpy).getString(anyInt()); + doReturn(mock(FragmentActivity.class)).when(fragmentSpy).requireActivity(); + doNothing().when(fragmentSpy).displaySnackBar(anyString()); + + fragmentSpy.deleteDownloadedOfflineMaps(); + List downloadedOfflineMapModelListProcessed = ReflectionHelpers.getField(fragmentSpy, "downloadedOfflineMapModelList"); + Assert.assertEquals(OfflineMapModel.OfflineMapStatus.DOWNLOAD_STARTED, downloadedOfflineMapModelListProcessed.get(0).getOfflineMapStatus()); + } + + @Test + public void testMapDeletedSuccessfullyShouldRemoveOfflineMapFromList() { + EusmDownloadedOfflineMapsFragment fragmentSpy = spy(fragment); + Location location = new Location(); + location.setId("4322-23"); + location.setType("Feature"); + + OfflineMapModel offlineMapModel = new OfflineMapModel(); + offlineMapModel.setOfflineMapStatus(OfflineMapModel.OfflineMapStatus.DOWNLOAD_STARTED); + offlineMapModel.setLocation(location); + + List downloadedOfflineMapModelList = new ArrayList<>(); + downloadedOfflineMapModelList.add(offlineMapModel); + ReflectionHelpers.setField(fragmentSpy, "downloadedOfflineMapModelList", downloadedOfflineMapModelList); + + OfflineMapDownloadCallback callback = mock(OfflineMapDownloadCallback.class); + fragmentSpy.setOfflineMapDownloadCallback(callback); + + fragmentSpy.mapDeletedSuccessfully("4322-23"); + List downloadedOfflineMapModelListProcessed = ReflectionHelpers.getField(fragmentSpy, "downloadedOfflineMapModelList"); + Assert.assertTrue(downloadedOfflineMapModelListProcessed.isEmpty()); + + } + +} \ No newline at end of file From cb7b94a3d288abfc3ffd733a33d264b942268e9e Mon Sep 17 00:00:00 2001 From: Hamza Ahmed Khan Date: Mon, 20 Feb 2023 14:23:14 +0500 Subject: [PATCH 08/11] Add tests 2 --- .../org/smartregister/eusm/BaseUnitTest.java | 3 +- .../activity/EusmOfflineMapsActivityTest.java | 6 ++++ ...EusmDownloadedOfflineMapsFragmentTest.java | 6 ++++ .../repository/AppLocationRepositoryTest.java | 30 +++++++++++++++++++ .../eusm/shadow/RealmDatabaseShadow.java | 18 +++++++++++ 5 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 opensrp-eusm/src/test/java/org/smartregister/eusm/shadow/RealmDatabaseShadow.java diff --git a/opensrp-eusm/src/test/java/org/smartregister/eusm/BaseUnitTest.java b/opensrp-eusm/src/test/java/org/smartregister/eusm/BaseUnitTest.java index 9239ac3..50ec28e 100644 --- a/opensrp-eusm/src/test/java/org/smartregister/eusm/BaseUnitTest.java +++ b/opensrp-eusm/src/test/java/org/smartregister/eusm/BaseUnitTest.java @@ -23,6 +23,7 @@ import org.smartregister.eusm.shadow.MapViewShadow; import org.smartregister.eusm.shadow.RasterLayerShadow; import org.smartregister.eusm.shadow.RasterSourceShadow; +import org.smartregister.eusm.shadow.RealmDatabaseShadow; import org.smartregister.eusm.shadow.SQLiteDatabaseShadow; import org.smartregister.eusm.shadow.SymbolLayerShadow; import org.smartregister.eusm.shadow.TaskingMapViewShadow; @@ -35,7 +36,7 @@ @Config(application = TestEusmApplication.class, shadows = {SymbolLayerShadow.class, LayerShadow.class, TaskingMapViewShadow.class, KujakuMapViewShadow.class, MapViewShadow.class, SQLiteDatabaseShadow.class, CustomFontTextViewShadow.class, VectorSourceShadow.class, BackgroundLayerShadow.class, - RasterLayerShadow.class, LineLayerShadow.class, RasterSourceShadow.class}, sdk = Build.VERSION_CODES.P) + RasterLayerShadow.class, LineLayerShadow.class, RasterSourceShadow.class, RealmDatabaseShadow.class}, sdk = Build.VERSION_CODES.P) @PowerMockIgnore({"org.mockito.*", "org.robolectric.*", "android.*"}) public abstract class BaseUnitTest { diff --git a/opensrp-eusm/src/test/java/org/smartregister/eusm/activity/EusmOfflineMapsActivityTest.java b/opensrp-eusm/src/test/java/org/smartregister/eusm/activity/EusmOfflineMapsActivityTest.java index 3c4d051..c5cb058 100644 --- a/opensrp-eusm/src/test/java/org/smartregister/eusm/activity/EusmOfflineMapsActivityTest.java +++ b/opensrp-eusm/src/test/java/org/smartregister/eusm/activity/EusmOfflineMapsActivityTest.java @@ -34,6 +34,12 @@ public void testGetAvailableOfflineMapsFragmentShouldNotBeNull() { assertNotNull(eusmOfflineMapsActivity.getAvailableOfflineMapsFragment()); } + @Test + public void testGetDownloadedOfflineMapsFragmentShouldNotBeNull() { + assertNotNull(eusmOfflineMapsActivity.getDownloadedOfflineMapsFragment()); + } + + @Override protected Activity getActivity() { return eusmOfflineMapsActivity; diff --git a/opensrp-eusm/src/test/java/org/smartregister/eusm/fragment/EusmDownloadedOfflineMapsFragmentTest.java b/opensrp-eusm/src/test/java/org/smartregister/eusm/fragment/EusmDownloadedOfflineMapsFragmentTest.java index d84aefd..a923cc0 100644 --- a/opensrp-eusm/src/test/java/org/smartregister/eusm/fragment/EusmDownloadedOfflineMapsFragmentTest.java +++ b/opensrp-eusm/src/test/java/org/smartregister/eusm/fragment/EusmDownloadedOfflineMapsFragmentTest.java @@ -13,6 +13,7 @@ import static org.robolectric.annotation.LooperMode.Mode.PAUSED; import android.content.Context; +import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.CheckBox; @@ -46,6 +47,11 @@ public void setUp() { } @Test + public void testGetInstanceMethodNotNull() { + Assert.assertNotNull(EusmDownloadedOfflineMapsFragment.newInstance(new Bundle(), mock(Context.class))); + } + + @Test public void testSetUpViewsShouldInitAdapter() { EusmDownloadedOfflineMapsFragment fragmentSpy = spy(fragment); doReturn(mock(Context.class)).when(fragmentSpy).requireContext(); diff --git a/opensrp-eusm/src/test/java/org/smartregister/eusm/repository/AppLocationRepositoryTest.java b/opensrp-eusm/src/test/java/org/smartregister/eusm/repository/AppLocationRepositoryTest.java index 96c785a..1f9e770 100644 --- a/opensrp-eusm/src/test/java/org/smartregister/eusm/repository/AppLocationRepositoryTest.java +++ b/opensrp-eusm/src/test/java/org/smartregister/eusm/repository/AppLocationRepositoryTest.java @@ -2,22 +2,30 @@ import android.content.ContentValues; +import net.sqlcipher.Cursor; import net.sqlcipher.database.SQLiteDatabase; import org.junit.Before; import org.junit.Test; import org.mockito.Mock; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; import org.smartregister.domain.Location; import org.smartregister.domain.LocationProperty; import org.smartregister.eusm.BaseUnitTest; import org.smartregister.repository.BaseRepository; +import java.util.Set; import java.util.UUID; +import static org.junit.Assert.assertEquals; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.isNull; +import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; @@ -65,4 +73,26 @@ public void testAddOrUpdateShouldInvokeAddLocationIfIdPresent() { verify(sqLiteDatabase).replace(eq("location"), isNull(), any(ContentValues.class)); } + + @Test + public void testGetDistrictIdsForRegionId() { + doReturn(sqLiteDatabase).when(appLocationRepository).getReadableDatabase(); + Cursor cursor = mock(Cursor.class); + doReturn(cursor).when(sqLiteDatabase) + .rawQuery(anyString(), any(String[].class)); + + doAnswer(new Answer() { + int count = -1; + + @Override + public Object answer(InvocationOnMock invocation) throws Throwable { + count++; + return count == 0; + } + }).when(cursor).moveToNext(); + + Set districts = appLocationRepository.getDistrictIdsForRegionId("23-3"); + assertEquals(1, districts.size()); + } + } \ No newline at end of file diff --git a/opensrp-eusm/src/test/java/org/smartregister/eusm/shadow/RealmDatabaseShadow.java b/opensrp-eusm/src/test/java/org/smartregister/eusm/shadow/RealmDatabaseShadow.java new file mode 100644 index 0000000..580794e --- /dev/null +++ b/opensrp-eusm/src/test/java/org/smartregister/eusm/shadow/RealmDatabaseShadow.java @@ -0,0 +1,18 @@ +package org.smartregister.eusm.shadow; + +import android.content.Context; + + +import org.robolectric.annotation.Implementation; +import org.robolectric.annotation.Implements; + +import io.ona.kujaku.data.realm.RealmDatabase; + +@Implements(RealmDatabase.class) +public class RealmDatabaseShadow { + + @Implementation + public static synchronized void init(Context context) { + //do nothing + } +} From 13367efcc0fb0a9e0f3877e33208695d0cf1d355 Mon Sep 17 00:00:00 2001 From: Hamza Ahmed Khan Date: Tue, 28 Feb 2023 13:42:52 +0500 Subject: [PATCH 09/11] PR feedback changes --- .../AppTaskingLibraryConfiguration.java | 7 +-- .../EusmAvailableOfflineMapsFragment.java | 54 +++++++++---------- .../EusmDownloadedOfflineMapsFragment.java | 22 ++++---- .../repository/AppLocationRepositoryTest.java | 1 + 4 files changed, 37 insertions(+), 47 deletions(-) diff --git a/opensrp-eusm/src/main/java/org/smartregister/eusm/config/AppTaskingLibraryConfiguration.java b/opensrp-eusm/src/main/java/org/smartregister/eusm/config/AppTaskingLibraryConfiguration.java index c7f6402..1be1d10 100644 --- a/opensrp-eusm/src/main/java/org/smartregister/eusm/config/AppTaskingLibraryConfiguration.java +++ b/opensrp-eusm/src/main/java/org/smartregister/eusm/config/AppTaskingLibraryConfiguration.java @@ -433,7 +433,7 @@ public String getProvinceFromTreeDialogValue(List arrayList) { @Override public String getDistrictFromTreeDialogValue(List arrayList) { try { - return arrayList.get(1); + return arrayList.get(Integer.parseInt(AppConstants.LocationGeographicLevel.REGION)); } catch (IndexOutOfBoundsException e) { Timber.e(e); } @@ -529,11 +529,6 @@ public List getLocationsIdsForDownload(List downloadedLocation if (downloadedLocations != null) { districtIds.removeAll(downloadedLocations); } -// List locationList = EusmApplication.getInstance().getStructureRepository().getLocationByDistrictIds(jurisdictionIds); -// -// if (downloadedLocations != null) { -// locationList = locationList.stream().filter(location -> !downloadedLocations.contains(location.getId())).collect(Collectors.toList()); -// } return EusmApplication.getInstance().getLocationRepository().getLocationsByIds(districtIds); } diff --git a/opensrp-eusm/src/main/java/org/smartregister/eusm/fragment/EusmAvailableOfflineMapsFragment.java b/opensrp-eusm/src/main/java/org/smartregister/eusm/fragment/EusmAvailableOfflineMapsFragment.java index 1996498..910f860 100644 --- a/opensrp-eusm/src/main/java/org/smartregister/eusm/fragment/EusmAvailableOfflineMapsFragment.java +++ b/opensrp-eusm/src/main/java/org/smartregister/eusm/fragment/EusmAvailableOfflineMapsFragment.java @@ -52,38 +52,34 @@ public static EusmAvailableOfflineMapsFragment newInstance(Bundle bundle, @NonNu @Override protected void downloadLocation(@NonNull Location location) { - downloadDistrictMap(location.getId()); + getAppExecutors().diskIO().execute(() -> downloadDistrictMap(location.getId())); + } protected void downloadDistrictMap(String districtId) { - getAppExecutors().diskIO().execute(() -> { - List locationList = getAppStructureRepository().getStructuresByDistrictId(districtId); - if (locationList == null || locationList.isEmpty()) { - getAppExecutors().mainThread().execute(() -> displayToast(getString(R.string.location_has_no_structures))); - // Revert download map status - for (OfflineMapModel model : offlineMapModelList) { - if (model.getOfflineMapStatus() == OfflineMapModel.OfflineMapStatus.DOWNLOAD_STARTED) { - model.setOfflineMapStatus(OfflineMapModel.OfflineMapStatus.READY); - return; - } - } - } else { - JSONObject featureCollection = new JSONObject(); - try { - featureCollection.put(TaskingConstants.GeoJSON.TYPE, TaskingConstants.GeoJSON.FEATURE_COLLECTION); - featureCollection.put(TaskingConstants.GeoJSON.FEATURES, new JSONArray(gson.toJson(locationList))); - getAppExecutors().mainThread().execute(new Runnable() { - @Override - public void run() { - displayToast(getString(R.string.download_starting)); - downloadMap(FeatureCollection.fromJson(featureCollection.toString()), districtId); - } - }); - } catch (JSONException e) { - Timber.e(e); + List locationList = getAppStructureRepository().getStructuresByDistrictId(districtId); + if (locationList == null || locationList.isEmpty()) { + getAppExecutors().mainThread().execute(() -> displayToast(getString(R.string.location_has_no_structures))); + // Revert download map status + for (OfflineMapModel model : offlineMapModelList) { + if (model.getOfflineMapStatus() == OfflineMapModel.OfflineMapStatus.DOWNLOAD_STARTED) { + model.setOfflineMapStatus(OfflineMapModel.OfflineMapStatus.READY); + return; } } - }); + } else { + JSONObject featureCollection = new JSONObject(); + try { + featureCollection.put(TaskingConstants.GeoJSON.TYPE, TaskingConstants.GeoJSON.FEATURE_COLLECTION); + featureCollection.put(TaskingConstants.GeoJSON.FEATURES, new JSONArray(gson.toJson(locationList))); + getAppExecutors().mainThread().execute(() -> { + displayToast(getString(R.string.download_starting)); + downloadMap(FeatureCollection.fromJson(featureCollection.toString()), districtId); + }); + } catch (JSONException e) { + Timber.e(e); + } + } } protected void downloadMap(FeatureCollection operationalAreaFeature, String mapName) { @@ -106,13 +102,11 @@ public AppExecutors getAppExecutors() { @Override public void moveDownloadedOAToDownloadedList(String operationalAreaId) { - List toRemoveFromAvailableList = new ArrayList<>(); List toRemoveFromDownloadList = new ArrayList<>(); for (OfflineMapModel offlineMapModel : offlineMapModelList) { - if (offlineMapModel.getDownloadAreaId().equals(operationalAreaId)) { + if (operationalAreaId.equals(offlineMapModel.getDownloadAreaId())) { offlineMapModel.setOfflineMapStatus(OfflineMapModel.OfflineMapStatus.READY); callback.onMapDownloaded(offlineMapModel); - toRemoveFromAvailableList.add(offlineMapModel); toRemoveFromDownloadList.add(offlineMapModel.getLocation()); setOfflineMapModelList(offlineMapModelList); break; diff --git a/opensrp-eusm/src/main/java/org/smartregister/eusm/fragment/EusmDownloadedOfflineMapsFragment.java b/opensrp-eusm/src/main/java/org/smartregister/eusm/fragment/EusmDownloadedOfflineMapsFragment.java index faae93d..d402cd8 100644 --- a/opensrp-eusm/src/main/java/org/smartregister/eusm/fragment/EusmDownloadedOfflineMapsFragment.java +++ b/opensrp-eusm/src/main/java/org/smartregister/eusm/fragment/EusmDownloadedOfflineMapsFragment.java @@ -59,12 +59,10 @@ public void displayError(int title, String message) { @Override public void setDownloadedOfflineMapModelList(List downloadedOfflineMapModelList) { - if (adapter == null) { - this.downloadedOfflineMapModelList = downloadedOfflineMapModelList; - } else { + if (adapter != null) { adapter.setOfflineMapModels(downloadedOfflineMapModelList); - this.downloadedOfflineMapModelList = downloadedOfflineMapModelList; } + this.downloadedOfflineMapModelList = downloadedOfflineMapModelList; } @Override @@ -87,7 +85,7 @@ protected void setUpViews(View view) { protected void startDeleteProcess() { List mapsToDownload = new ArrayList<>(); for (OfflineMapModel offlineMapModel : downloadedOfflineMapModelList) { - if (offlineMapModel.getOfflineMapStatus().equals(OfflineMapModel.OfflineMapStatus.SELECTED_FOR_DOWNLOAD)) { + if (OfflineMapModel.OfflineMapStatus.SELECTED_FOR_DOWNLOAD.equals(offlineMapModel.getOfflineMapStatus())) { mapsToDownload.add(offlineMapModel); } } @@ -112,12 +110,14 @@ public void updateOfflineMapsTodelete(View view) { CheckBox checkBox = (CheckBox) view; OfflineMapModel offlineMapModel = (OfflineMapModel) view.getTag(R.id.offline_map_checkbox); - for (OfflineMapModel model : downloadedOfflineMapModelList) { - if (model.getDownloadAreaId().equals(offlineMapModel.getDownloadAreaId())) { - if (checkBox.isChecked()) { - model.setOfflineMapStatus(OfflineMapModel.OfflineMapStatus.SELECTED_FOR_DOWNLOAD); - } else { - model.setOfflineMapStatus(OfflineMapModel.OfflineMapStatus.READY); + if (offlineMapModel != null) { + for (OfflineMapModel model : downloadedOfflineMapModelList) { + if (model != null && model.getDownloadAreaId().equals(offlineMapModel.getDownloadAreaId())) { + if (checkBox.isChecked()) { + model.setOfflineMapStatus(OfflineMapModel.OfflineMapStatus.SELECTED_FOR_DOWNLOAD); + } else { + model.setOfflineMapStatus(OfflineMapModel.OfflineMapStatus.READY); + } } } } diff --git a/opensrp-eusm/src/test/java/org/smartregister/eusm/repository/AppLocationRepositoryTest.java b/opensrp-eusm/src/test/java/org/smartregister/eusm/repository/AppLocationRepositoryTest.java index 1f9e770..4c08e3e 100644 --- a/opensrp-eusm/src/test/java/org/smartregister/eusm/repository/AppLocationRepositoryTest.java +++ b/opensrp-eusm/src/test/java/org/smartregister/eusm/repository/AppLocationRepositoryTest.java @@ -92,6 +92,7 @@ public Object answer(InvocationOnMock invocation) throws Throwable { }).when(cursor).moveToNext(); Set districts = appLocationRepository.getDistrictIdsForRegionId("23-3"); + verify(appLocationRepository).getDistrictIdsForRegionId("23-3"); assertEquals(1, districts.size()); } From 10c269457298c460bb21428008739e2417a24ca6 Mon Sep 17 00:00:00 2001 From: Hamza Ahmed Khan Date: Wed, 1 Mar 2023 14:04:34 +0500 Subject: [PATCH 10/11] Revert getDistrictFromTreeDialogValue --- .../eusm/config/AppTaskingLibraryConfiguration.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opensrp-eusm/src/main/java/org/smartregister/eusm/config/AppTaskingLibraryConfiguration.java b/opensrp-eusm/src/main/java/org/smartregister/eusm/config/AppTaskingLibraryConfiguration.java index 1be1d10..6706a0c 100644 --- a/opensrp-eusm/src/main/java/org/smartregister/eusm/config/AppTaskingLibraryConfiguration.java +++ b/opensrp-eusm/src/main/java/org/smartregister/eusm/config/AppTaskingLibraryConfiguration.java @@ -433,7 +433,7 @@ public String getProvinceFromTreeDialogValue(List arrayList) { @Override public String getDistrictFromTreeDialogValue(List arrayList) { try { - return arrayList.get(Integer.parseInt(AppConstants.LocationGeographicLevel.REGION)); + return arrayList.get(Integer.parseInt(AppConstants.LocationGeographicLevel.DISTRICT)); } catch (IndexOutOfBoundsException e) { Timber.e(e); } From 7c3718e3cc3fcb94d833c814d3cf804ddb335df5 Mon Sep 17 00:00:00 2001 From: Hamza Ahmed Khan Date: Tue, 7 Mar 2023 18:35:39 +0500 Subject: [PATCH 11/11] PR feedback 2 --- .../EusmDownloadedOfflineMapsFragment.java | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/opensrp-eusm/src/main/java/org/smartregister/eusm/fragment/EusmDownloadedOfflineMapsFragment.java b/opensrp-eusm/src/main/java/org/smartregister/eusm/fragment/EusmDownloadedOfflineMapsFragment.java index d402cd8..0d94e38 100644 --- a/opensrp-eusm/src/main/java/org/smartregister/eusm/fragment/EusmDownloadedOfflineMapsFragment.java +++ b/opensrp-eusm/src/main/java/org/smartregister/eusm/fragment/EusmDownloadedOfflineMapsFragment.java @@ -136,7 +136,7 @@ public void deleteDownloadedOfflineMaps() { displaySnackBar(getString(R.string.deleting_map)); for (OfflineMapModel offlineMapModel : downloadedOfflineMapModelList) { - if (offlineMapModel.getOfflineMapStatus().equals(OfflineMapModel.OfflineMapStatus.SELECTED_FOR_DOWNLOAD)) { + if (OfflineMapModel.OfflineMapStatus.SELECTED_FOR_DOWNLOAD.equals(offlineMapModel.getOfflineMapStatus())) { offlineMapModel.setOfflineMapStatus(OfflineMapModel.OfflineMapStatus.DOWNLOAD_STARTED); OfflineServiceHelper.deleteOfflineMap(requireActivity(), offlineMapModel.getDownloadAreaId(), @@ -153,16 +153,18 @@ public void setOfflineMapDownloadCallback(OfflineMapDownloadCallback callBack) { @Override protected void mapDeletedSuccessfully(String deletedMapName) { - List toRemove = new ArrayList<>(); - for (OfflineMapModel offlineMapModel : downloadedOfflineMapModelList) { - if (offlineMapModel.getDownloadAreaId().equals(deletedMapName)) { - toRemove.add(offlineMapModel); - offlineMapModel.setOfflineMapStatus(OfflineMapModel.OfflineMapStatus.READY); - callback.onOfflineMapDeleted(offlineMapModel); + if (deletedMapName != null) { + List toRemove = new ArrayList<>(); + for (OfflineMapModel offlineMapModel : downloadedOfflineMapModelList) { + if (deletedMapName.equals(offlineMapModel.getDownloadAreaId())) { + toRemove.add(offlineMapModel); + offlineMapModel.setOfflineMapStatus(OfflineMapModel.OfflineMapStatus.READY); + callback.onOfflineMapDeleted(offlineMapModel); + } } + downloadedOfflineMapModelList.removeAll(toRemove); + setDownloadedOfflineMapModelList(downloadedOfflineMapModelList); } - downloadedOfflineMapModelList.removeAll(toRemove); - setDownloadedOfflineMapModelList(downloadedOfflineMapModelList); } protected void displaySnackBar(String message) {