Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/add filter by text value feature #1

Merged
merged 11 commits into from
Jul 17, 2020
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ class ProgramPresenter internal constructor(
private val programQueries = PublishProcessor.create<Pair<List<DatePeriod>, List<String>>>()

fun init() {
FilterManager.getInstance().clearTextValues()

val loadingProcessor = PublishProcessor.create<Boolean>()

disposable.add(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
import org.hisp.dhis.android.core.category.CategoryCombo;
import org.hisp.dhis.android.core.category.CategoryOptionCombo;
import org.hisp.dhis.android.core.common.FeatureType;
import org.hisp.dhis.android.core.dataelement.DataElement;
import org.hisp.dhis.android.core.program.Program;

import java.lang.reflect.Field;
Expand Down Expand Up @@ -136,6 +137,7 @@ public void onCreate(@Nullable Bundle savedInstanceState) {

filtersAdapter = new FiltersAdapter();
filtersAdapter.addEventStatus();

try {
binding.filterLayout.setAdapter(filtersAdapter);

Expand Down Expand Up @@ -303,6 +305,11 @@ public void setCatOptionComboFilter(Pair<CategoryCombo, List<CategoryOptionCombo
filtersAdapter.addCatOptCombFilter(categoryOptionCombos);
}

@Override
public void setTextTypeDataElementsFilter(List<DataElement> textTypeDataElementsFilter) {
filtersAdapter.addTextValueFilter(textTypeDataElementsFilter);
}

@Override
public void showPeriodRequest(FilterManager.PeriodRequest periodRequest) {
if (periodRequest == FilterManager.PeriodRequest.FROM_TO) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
package org.dhis2.usescases.programEventDetail;

import androidx.lifecycle.LiveData;
import androidx.paging.PagedList;

import com.mapbox.geojson.BoundingBox;
import com.mapbox.geojson.FeatureCollection;
import com.mapbox.mapboxsdk.geometry.LatLng;
Expand All @@ -13,11 +10,13 @@
import org.hisp.dhis.android.core.category.CategoryCombo;
import org.hisp.dhis.android.core.category.CategoryOptionCombo;
import org.hisp.dhis.android.core.common.FeatureType;
import org.hisp.dhis.android.core.period.DatePeriod;
import org.hisp.dhis.android.core.dataelement.DataElement;
import org.hisp.dhis.android.core.program.Program;

import java.util.List;

import androidx.lifecycle.LiveData;
import androidx.paging.PagedList;
import io.reactivex.functions.Consumer;

/**
Expand All @@ -44,6 +43,8 @@ public interface View extends AbstractActivityContracts.View {

void setCatOptionComboFilter(Pair<CategoryCombo, List<CategoryOptionCombo>> categoryOptionCombos);

void setTextTypeDataElementsFilter(List<DataElement> textTypeDataElementsFilter);

void openOrgUnitTreeSelector();

Consumer<kotlin.Pair<FeatureCollection, BoundingBox>> setMap();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,15 @@ public void init(ProgramEventDetailContract.View view) {
)
);

compositeDisposable.add(
eventRepository.textTypeDataElements()
.subscribeOn(schedulerProvider.io())
.observeOn(schedulerProvider.ui())
.subscribe(view::setTextTypeDataElementsFilter,
Timber::e
)
);

compositeDisposable.add(
FilterManager.getInstance().asFlowable()
.startWith(FilterManager.getInstance())
Expand All @@ -109,7 +118,8 @@ public void init(ProgramEventDetailContract.View view) {
filterManager.getOrgUnitUidsFilters(),
filterManager.getCatOptComboFilters(),
filterManager.getEventStatusFilters(),
filterManager.getStateFilters()
filterManager.getStateFilters(),
filterManager.getTexValueFilter()
))
.subscribeOn(schedulerProvider.computation())
.observeOn(schedulerProvider.ui())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import org.hisp.dhis.android.core.category.CategoryOptionCombo;
import org.hisp.dhis.android.core.common.FeatureType;
import org.hisp.dhis.android.core.common.State;
import org.hisp.dhis.android.core.dataelement.DataElement;
import org.hisp.dhis.android.core.event.EventStatus;
import org.hisp.dhis.android.core.period.DatePeriod;
import org.hisp.dhis.android.core.program.Program;
Expand All @@ -29,7 +30,7 @@
public interface ProgramEventDetailRepository {

@NonNull
LiveData<PagedList<ProgramEventViewModel>> filteredProgramEvents(List<DatePeriod> dateFilter, List<String> orgUnitFilter, List<CategoryOptionCombo> catOptionComboUid, List<EventStatus> eventStatus, List<State> states);
LiveData<PagedList<ProgramEventViewModel>> filteredProgramEvents(List<DatePeriod> dateFilter, List<String> orgUnitFilter, List<CategoryOptionCombo> catOptionComboUid, List<EventStatus> eventStatus, List<State> states, Pair<String, String> valueFilter);

@NonNull
Flowable<kotlin.Pair<FeatureCollection, BoundingBox>> filteredEventsForMap(List<DatePeriod> dateFilter, List<String> orgUnitFilter, List<CategoryOptionCombo> catOptionComboUid, List<EventStatus> eventStatus, List<State> states);
Expand All @@ -41,6 +42,9 @@ public interface ProgramEventDetailRepository {

Single<Pair<CategoryCombo, List<CategoryOptionCombo>>> catOptionCombos();

@NonNull
Observable<List<DataElement>> textTypeDataElements();

Single<Boolean> hasAccessToAllCatOptions();

Flowable<ProgramEventViewModel> getInfoForEvent(String eventUid);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@

import static android.text.TextUtils.isEmpty;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import android.database.Cursor;

import com.mapbox.geojson.BoundingBox;
import com.mapbox.geojson.FeatureCollection;
import com.squareup.sqlbrite2.BriteDatabase;

import org.dhis2.data.tuples.Pair;
import org.dhis2.utils.DateUtils;
Expand All @@ -29,20 +31,21 @@
import org.hisp.dhis.android.core.program.Program;
import org.hisp.dhis.android.core.program.ProgramStageDataElement;
import org.hisp.dhis.android.core.trackedentity.TrackedEntityDataValue;
import org.jetbrains.annotations.NotNull;

import com.mapbox.geojson.BoundingBox;
import com.mapbox.geojson.FeatureCollection;
import com.squareup.sqlbrite2.BriteDatabase;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import androidx.annotation.NonNull;
import androidx.lifecycle.LiveData;
import androidx.paging.DataSource;
import androidx.paging.LivePagedListBuilder;
import androidx.paging.PagedList;

import io.reactivex.Flowable;
import io.reactivex.Observable;
import io.reactivex.Single;
import timber.log.Timber;

/**
* QUADRAM. Created by ppajuelo on 02/11/2017.
Expand All @@ -63,8 +66,9 @@ public class ProgramEventDetailRepositoryImpl implements ProgramEventDetailRepos
@NonNull
@Override
public LiveData<PagedList<ProgramEventViewModel>> filteredProgramEvents(List<DatePeriod> dateFilter, List<String> orgUnitFilter, List<CategoryOptionCombo> catOptCombList,
List<EventStatus> eventStatus, List<State> states) {
List<EventStatus> eventStatus, List<State> states, Pair<String, String> valueFilter) {
EventCollectionRepository eventRepo = d2.eventModule().events().byProgramUid().eq(programUid);

if (!dateFilter.isEmpty())
eventRepo = eventRepo.byEventDate().inDatePeriods(dateFilter);
if (!orgUnitFilter.isEmpty())
Expand All @@ -75,6 +79,11 @@ public LiveData<PagedList<ProgramEventViewModel>> filteredProgramEvents(List<Dat
eventRepo = eventRepo.byStatus().in(eventStatus);
if (!states.isEmpty())
eventRepo = eventRepo.byState().in(states);
if (valueFilter != null && !valueFilter.val0().isEmpty() && !valueFilter.val1().isEmpty()) {
List<String> uIds = getEventUIdsFilteredByValue(valueFilter);
eventRepo = eventRepo.byUid().in(uIds);
}

DataSource dataSource = eventRepo.orderByEventDate(RepositoryScope.OrderByDirection.DESC).withTrackedEntityDataValues().getDataSource().map(event -> transformToProgramEventModel(event));

return new LivePagedListBuilder(new DataSource.Factory() {
Expand All @@ -85,6 +94,33 @@ public DataSource create() {
}, 20).build();
}

@NotNull
private List<String> getEventUIdsFilteredByValue(
Pair<String, String> valueFilter) {

List<String> uids = new ArrayList<>();

String QUERY = "SELECT Event.uid FROM Event " +
"LEFT OUTER JOIN TrackedEntityDataValue AS Value ON Value.event = Event.uid " +
"WHERE Value.dataElement = '" + valueFilter.val0() + "' AND Value.value like '%" +
valueFilter.val1()+ "%'";

try (Cursor uIdsCursor = briteDatabase.query(QUERY)) {
if (uIdsCursor != null) {
uIdsCursor.moveToFirst();
for (int i = 0; i < uIdsCursor.getCount(); i++) {
uids.add(uIdsCursor.getString(0));
uIdsCursor.moveToNext();
}
}
} catch (Exception e) {
Timber.e(e);
}

return uids;
}


@NonNull
@Override
public Flowable<kotlin.Pair<FeatureCollection, BoundingBox>> filteredEventsForMap(List<DatePeriod> dateFilter, List<String> orgUnitFilter, List<CategoryOptionCombo> catOptCombList,
Expand Down Expand Up @@ -246,6 +282,34 @@ public Single<Pair<CategoryCombo, List<CategoryOptionCombo>>> catOptionCombos()
));
}

@NonNull
@Override
public Observable<List<DataElement>> textTypeDataElements() {
List<String> programStageUIds =
d2.programModule().programs().uid(programUid).get()
.flatMap(program -> d2.programModule().programStages().byProgramUid()
.eq(program.uid()).get())
.toObservable().flatMap(programStages ->
Observable.fromIterable(programStages)
.map(item -> item.uid())
.toList().toObservable()).blockingFirst();

List<String> programStagesDataElementsUIds =
d2.programModule().programStageDataElements().byProgramStage().in(programStageUIds).get()
.toObservable().flatMap(programStageDataElements ->
Observable.fromIterable(programStageDataElements)
.map(item -> item.dataElement().uid())
.toList().toObservable()).blockingFirst();


return d2.dataElementModule().dataElements()
.byValueType().eq(ValueType.TEXT)
.byUid().in(programStagesDataElementsUIds)
.byOptionSetUid().isNull()
.orderByDisplayName(RepositoryScope.OrderByDirection.ASC)
.get().toObservable();
}

@Override
public Single<Boolean> hasAccessToAllCatOptions() {
return d2.programModule().programs().uid(programUid).get()
Expand Down
61 changes: 61 additions & 0 deletions app/src/main/java/org/dhis2/utils/DataElementsAdapter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package org.dhis2.utils;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;

import org.dhis2.databinding.SpinnerDataelementLayoutBinding;
import org.hisp.dhis.android.core.dataelement.DataElement;

import java.util.List;

import androidx.annotation.ColorRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;

public class DataElementsAdapter extends ArrayAdapter<DataElement> {

private final List<DataElement> dataElements;
private @ColorRes
int textColor;

public DataElementsAdapter(@NonNull Context context, int resource, int textViewResourceId,
@NonNull List<DataElement> objects, @ColorRes int textColor) {
super(context, resource, textViewResourceId, objects);
this.dataElements = objects;
this.textColor = textColor;
}

@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {

LayoutInflater inflater = LayoutInflater.from(parent.getContext());
SpinnerDataelementLayoutBinding binding = SpinnerDataelementLayoutBinding.inflate(inflater,
parent, false);
binding.setDataElement(dataElements.get(position));
binding.spinnerText.setTextColor(
ContextCompat.getColor(binding.spinnerText.getContext(), textColor));
return binding.getRoot();

}

@Override
public View getDropDownView(int position, @Nullable View convertView,
@NonNull ViewGroup parent) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
SpinnerDataelementLayoutBinding binding = SpinnerDataelementLayoutBinding.inflate(inflater,
parent, false);
binding.setDataElement(dataElements.get(position));

return binding.getRoot();
}

@Override
public int getCount() {
return super.getCount();
}
}
Loading