diff --git a/.gitignore b/.gitignore
index 23ee352e..ff7f2830 100644
--- a/.gitignore
+++ b/.gitignore
@@ -23,3 +23,6 @@ build
#Windows
*.db
+
+# Last commit file
+app/src/main/res/raw/lastcommit.txt
\ No newline at end of file
diff --git a/api/build.gradle b/api/build.gradle
index 14b5bbb3..4c76294e 100755
--- a/api/build.gradle
+++ b/api/build.gradle
@@ -1,5 +1,6 @@
apply plugin: 'com.android.library'
apply plugin: 'com.neenbedankt.android-apt'
+apply plugin: 'jacoco-android'
android {
compileSdkVersion 25
@@ -17,8 +18,20 @@ android {
targetCompatibility JavaVersion.VERSION_1_7
}
+ packagingOptions {
+ exclude 'META-INF/LICENSE'
+ exclude 'META-INF/NOTICE'
+ }
+
lintOptions {
- disable 'RtlSymmetry', 'RtlHardcoded'
+ disable 'RtlSymmetry', 'RtlHardcoded', 'RestrictedApi'
+ abortOnError false
+ }
+
+ buildTypes {
+ debug {
+ testCoverageEnabled true
+ }
}
}
@@ -47,4 +60,7 @@ dependencies {
// Other
compile 'joda-time:joda-time:2.9.2'
+
+ // Java test dependencies
+ testCompile "junit:junit:4.12"
}
diff --git a/api/src/main/AndroidManifest.xml b/api/src/main/AndroidManifest.xml
index 2dbf51c3..b04cd600 100755
--- a/api/src/main/AndroidManifest.xml
+++ b/api/src/main/AndroidManifest.xml
@@ -3,6 +3,7 @@
package="org.hisp.dhis.android.dashboard.api">
+
diff --git a/api/src/main/java/org/hisp/dhis/android/dashboard/api/controllers/DashboardController.java b/api/src/main/java/org/hisp/dhis/android/dashboard/api/controllers/DashboardController.java
index a27634b4..76819c47 100755
--- a/api/src/main/java/org/hisp/dhis/android/dashboard/api/controllers/DashboardController.java
+++ b/api/src/main/java/org/hisp/dhis/android/dashboard/api/controllers/DashboardController.java
@@ -28,6 +28,13 @@
package org.hisp.dhis.android.dashboard.api.controllers;
+import static org.hisp.dhis.android.dashboard.api.models.BaseIdentifiableObject.merge;
+import static org.hisp.dhis.android.dashboard.api.models.BaseIdentifiableObject.toListIds;
+import static org.hisp.dhis.android.dashboard.api.models.BaseIdentifiableObject.toMap;
+import static org.hisp.dhis.android.dashboard.api.utils.NetworkUtils.findLocationHeader;
+import static org.hisp.dhis.android.dashboard.api.utils.NetworkUtils.handleApiException;
+import static org.hisp.dhis.android.dashboard.api.utils.NetworkUtils.unwrapResponse;
+
import android.net.Uri;
import com.raizlabs.android.dbflow.sql.builder.Condition;
@@ -61,13 +68,6 @@
import retrofit.client.Header;
import retrofit.client.Response;
-import static org.hisp.dhis.android.dashboard.api.models.BaseIdentifiableObject.merge;
-import static org.hisp.dhis.android.dashboard.api.models.BaseIdentifiableObject.toListIds;
-import static org.hisp.dhis.android.dashboard.api.models.BaseIdentifiableObject.toMap;
-import static org.hisp.dhis.android.dashboard.api.utils.NetworkUtils.findLocationHeader;
-import static org.hisp.dhis.android.dashboard.api.utils.NetworkUtils.handleApiException;
-import static org.hisp.dhis.android.dashboard.api.utils.NetworkUtils.unwrapResponse;
-
final class DashboardController {
final DhisApi mDhisApi;
@@ -96,6 +96,11 @@ private static List queryDashboards() {
.queryList();
}
+ public static List queryAllDashboardElement() {
+ return new Select().from(DashboardElement.class)
+ .queryList();
+ }
+
private static List queryDashboardItems(Dashboard dashboard) {
Where where = new Select().from(DashboardItem.class)
.where(Condition.column(DashboardItem$Table
@@ -164,7 +169,8 @@ private List updateDashboards(DateTime lastUpdated) throws APIExcepti
"]");
if (lastUpdated != null) {
- QUERY_MAP_FULL.put("filter", "lastUpdated:gt:" + lastUpdated.toString());
+ QUERY_MAP_FULL.put("filter",
+ "lastUpdated:gt:" + lastUpdated.toLocalDateTime().toString());
}
// List of dashboards with UUIDs (without content). This list is used
@@ -183,8 +189,11 @@ private List updateDashboards(DateTime lastUpdated) throws APIExcepti
continue;
}
+ int i=0;
for (DashboardItem item : dashboard.getDashboardItems()) {
item.setDashboard(dashboard);
+ item.setOrderPosition(i);
+ i++;
}
}
}
@@ -213,7 +222,7 @@ private List updateDashboardItems(List dashboards, Dat
QUERY_MAP_BASIC.put("fields", "id,created,lastUpdated,shape");
if (lastUpdated != null) {
- QUERY_MAP_BASIC.put("filter", "lastUpdated:gt:" + lastUpdated.toString());
+ QUERY_MAP_BASIC.put("filter", "lastUpdated:gt:" + lastUpdated.toLocalDateTime().toString());
}
// List of actual dashboard items.
@@ -628,6 +637,8 @@ private List updateApiResources(DateTime lastUpdated) thro
DashboardItemContent.TYPE_REPORTS, lastUpdated));
dashboardItemContent.addAll(updateApiResourceByType(
DashboardItemContent.TYPE_RESOURCES, lastUpdated));
+ dashboardItemContent.addAll(updateApiResourceByType(
+ DashboardItemContent.TYPE_MESSAGES, lastUpdated));
return dashboardItemContent;
}
@@ -682,6 +693,8 @@ private List getApiResourceByType(String type, Map createOperations(List oldModels
continue;
}
- if (newModel.getLastUpdated().isAfter(oldModel.getLastUpdated())) {
+ if (DateTime.parse(newModel.getLastUpdated()).isAfter(DateTime.parse(oldModel.getLastUpdated()))) {
newModel.setId(oldModel.getId());
ops.add(DbOperation.update(newModel));
}
@@ -573,6 +573,11 @@ private static List queryInterpretations() {
.queryList();
}
+ public static List queryAllInterpretationElements() {
+ return new Select().from(InterpretationElement.class)
+ .queryList();
+ }
+
private static List queryInterpretationUsers() {
return new Select().from(User.class).queryList();
}
diff --git a/api/src/main/java/org/hisp/dhis/android/dashboard/api/controllers/PullImageController.java b/api/src/main/java/org/hisp/dhis/android/dashboard/api/controllers/PullImageController.java
new file mode 100644
index 00000000..319c2ef8
--- /dev/null
+++ b/api/src/main/java/org/hisp/dhis/android/dashboard/api/controllers/PullImageController.java
@@ -0,0 +1,101 @@
+package org.hisp.dhis.android.dashboard.api.controllers;
+
+import android.content.Context;
+
+import com.squareup.picasso.MemoryPolicy;
+import com.squareup.picasso.NetworkPolicy;
+
+import org.hisp.dhis.android.dashboard.api.models.DashboardElement;
+import org.hisp.dhis.android.dashboard.api.models.DashboardItemContent;
+import org.hisp.dhis.android.dashboard.api.models.Interpretation;
+import org.hisp.dhis.android.dashboard.api.models.InterpretationElement;
+import org.hisp.dhis.android.dashboard.api.network.APIException;
+import org.hisp.dhis.android.dashboard.api.utils.PicassoProvider;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+final class PullImageController {
+
+ static Context mContext;
+
+ public PullImageController(Context context) {
+ mContext = context;
+ }
+
+ public void pullDashboardImages(DhisController.ImageNetworkPolicy imageNetworkPolicy) throws APIException {
+ List requestList = new ArrayList<>();
+ requestList = downloadDashboardImages(requestList);
+ downloadImages(imageNetworkPolicy, requestList, mContext);
+ }
+
+ public void pullInterpretationImages(DhisController.ImageNetworkPolicy imageNetworkPolicy) throws APIException {
+ List requestList = new ArrayList<>();
+ requestList = downloadInterpretationImages(requestList);
+ downloadImages(imageNetworkPolicy, requestList, mContext);
+ }
+
+ public static List downloadInterpretationImages(List requestList) {
+ for (InterpretationElement interpretationElement : InterpretationController
+ .queryAllInterpretationElements()) {
+ if (interpretationElement == null || interpretationElement.getType() == null) {
+ continue;
+ }
+ if (Interpretation.TYPE_CHART.equals(interpretationElement.getType())) {
+ requestList.add(
+ DhisController.buildImageUrl("charts", interpretationElement.getUId(),
+ mContext));
+ } else if (Interpretation.TYPE_MAP.equals(interpretationElement.getType())) {
+ requestList.add(DhisController.buildImageUrl("maps", interpretationElement.getUId(),
+ mContext));
+ }
+ }
+ return requestList;
+ }
+
+ public static List downloadDashboardImages(List requestList) {
+ for (DashboardElement element : DashboardController.queryAllDashboardElement()) {
+ if (element.getDashboardItem() == null
+ || element.getDashboardItem().getType() == null) {
+ continue;
+ }
+
+ switch (element.getDashboardItem().getType()) {
+ case DashboardItemContent.TYPE_CHART: {
+ requestList.add(
+ DhisController.buildImageUrl("charts", element.getUId(), mContext));
+ break;
+ }
+ case DashboardItemContent.TYPE_EVENT_CHART: {
+ requestList.add(DhisController.buildImageUrl("eventCharts", element.getUId(),
+ mContext));
+ break;
+ }
+ case DashboardItemContent.TYPE_MAP: {
+ requestList.add(
+ DhisController.buildImageUrl("maps", element.getUId(), mContext));
+ break;
+ }
+ }
+ }
+ return requestList;
+ }
+
+ private static void downloadImages(DhisController.ImageNetworkPolicy imageNetworkPolicy,
+ final List requestUrlList, final Context context) {
+
+ for (int i = 0; i < requestUrlList.size(); i++) {
+ final String request = requestUrlList.get(i);
+
+ if (imageNetworkPolicy == DhisController.ImageNetworkPolicy.NO_CACHE) {
+ PicassoProvider.getInstance(context, false)
+ .load(request).networkPolicy(NetworkPolicy.NO_CACHE)
+ .memoryPolicy(MemoryPolicy.NO_CACHE).fetch();
+ } else {
+ PicassoProvider.getInstance(context, false)
+ .load(request).fetch();
+ }
+ }
+ }
+}
diff --git a/api/src/main/java/org/hisp/dhis/android/dashboard/api/models/Access.java b/api/src/main/java/org/hisp/dhis/android/dashboard/api/models/Access.java
index bc2c182f..8fc263f9 100755
--- a/api/src/main/java/org/hisp/dhis/android/dashboard/api/models/Access.java
+++ b/api/src/main/java/org/hisp/dhis/android/dashboard/api/models/Access.java
@@ -58,7 +58,7 @@ public final class Access {
*
* @return new Access object.
*/
- static Access provideDefaultAccess() {
+ public static Access provideDefaultAccess() {
Access access = new Access();
access.setManage(true);
access.setExternalize(true);
diff --git a/api/src/main/java/org/hisp/dhis/android/dashboard/api/models/AttributeDimension.java b/api/src/main/java/org/hisp/dhis/android/dashboard/api/models/AttributeDimension.java
new file mode 100644
index 00000000..0a9570cc
--- /dev/null
+++ b/api/src/main/java/org/hisp/dhis/android/dashboard/api/models/AttributeDimension.java
@@ -0,0 +1,26 @@
+package org.hisp.dhis.android.dashboard.api.models;
+
+import com.raizlabs.android.dbflow.annotation.Column;
+import com.raizlabs.android.dbflow.annotation.PrimaryKey;
+import com.raizlabs.android.dbflow.annotation.Table;
+import com.raizlabs.android.dbflow.structure.BaseModel;
+
+import org.hisp.dhis.android.dashboard.api.models.meta.DbDhis;
+
+@Table(databaseName = DbDhis.NAME)
+public class AttributeDimension extends BaseModel {
+
+ @Column(name = "id")
+ @PrimaryKey(autoincrement = true)
+ long id;
+
+ UIDObject attribute;
+
+ public UIDObject getAttribute() {
+ return attribute;
+ }
+
+ public void setAttribute(UIDObject attribute) {
+ this.attribute = attribute;
+ }
+}
diff --git a/api/src/main/java/org/hisp/dhis/android/dashboard/api/models/BaseIdentifiableObject.java b/api/src/main/java/org/hisp/dhis/android/dashboard/api/models/BaseIdentifiableObject.java
index f2dcd5ef..be4bd076 100755
--- a/api/src/main/java/org/hisp/dhis/android/dashboard/api/models/BaseIdentifiableObject.java
+++ b/api/src/main/java/org/hisp/dhis/android/dashboard/api/models/BaseIdentifiableObject.java
@@ -36,6 +36,7 @@
import org.hisp.dhis.android.dashboard.api.utils.StringUtils;
import org.joda.time.DateTime;
+import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
@@ -45,6 +46,10 @@
@JsonIgnoreProperties(ignoreUnknown = true)
public class BaseIdentifiableObject extends BaseModel implements IdentifiableObject {
+ public static final String TIMESTAMP_PATTERN = "yyyy-MM-dd'T'HH:mm:ss";
+
+ public static final SimpleDateFormat LONG_DATE_FORMAT = new SimpleDateFormat(TIMESTAMP_PATTERN);
+
@JsonIgnore
@Column(name = "id")
@PrimaryKey(autoincrement = true)
@@ -64,11 +69,11 @@ public class BaseIdentifiableObject extends BaseModel implements IdentifiableObj
@JsonProperty("created")
@Column(name = "created")
- DateTime created;
+ String created;
@JsonProperty("lastUpdated")
@Column(name = "lastUpdated")
- DateTime lastUpdated;
+ String lastUpdated;
@JsonProperty("access")
@Column(name = "access")
@@ -115,22 +120,22 @@ public void setDisplayName(String displayName) {
}
@Override
- public DateTime getCreated() {
+ public String getCreated() {
return created;
}
@Override
- public void setCreated(DateTime created) {
+ public void setCreated(String created) {
this.created = created;
}
@Override
- public DateTime getLastUpdated() {
+ public String getLastUpdated() {
return lastUpdated;
}
@Override
- public void setLastUpdated(DateTime lastUpdated) {
+ public void setLastUpdated(String lastUpdated) {
this.lastUpdated = lastUpdated;
}
diff --git a/api/src/main/java/org/hisp/dhis/android/dashboard/api/models/Dashboard.java b/api/src/main/java/org/hisp/dhis/android/dashboard/api/models/Dashboard.java
index 28dc6679..5bb92432 100755
--- a/api/src/main/java/org/hisp/dhis/android/dashboard/api/models/Dashboard.java
+++ b/api/src/main/java/org/hisp/dhis/android/dashboard/api/models/Dashboard.java
@@ -86,8 +86,8 @@ public static Dashboard createDashboard(String name) {
dashboard.setState(State.TO_POST);
dashboard.setName(name);
dashboard.setDisplayName(name);
- dashboard.setCreated(lastUpdatedDateTime);
- dashboard.setLastUpdated(lastUpdatedDateTime);
+ dashboard.setCreated(LONG_DATE_FORMAT.format(lastUpdatedDateTime.toDate()));
+ dashboard.setLastUpdated(LONG_DATE_FORMAT.format(lastUpdatedDateTime.toDate()));
dashboard.setAccess(Access.provideDefaultAccess());
return dashboard;
@@ -231,7 +231,8 @@ private boolean isItemContentTypeEmbedded(DashboardItemContent content) {
}
case DashboardItemContent.TYPE_USERS:
case DashboardItemContent.TYPE_REPORTS:
- case DashboardItemContent.TYPE_RESOURCES: {
+ case DashboardItemContent.TYPE_RESOURCES:
+ case DashboardItemContent.TYPE_MESSAGES: {
return false;
}
}
@@ -274,4 +275,14 @@ public int getDashboardItemCount() {
= queryRelatedDashboardItems();
return items == null ? 0 : items.size();
}
+
+ @Override
+ public void setCreated(String created) {
+ this.created=created;
+ }
+
+ @Override
+ public void setLastUpdated(String lastUpdated) {
+ this.lastUpdated = lastUpdated;
+ }
}
\ No newline at end of file
diff --git a/api/src/main/java/org/hisp/dhis/android/dashboard/api/models/DashboardItem.java b/api/src/main/java/org/hisp/dhis/android/dashboard/api/models/DashboardItem.java
index 8749f701..a1198960 100755
--- a/api/src/main/java/org/hisp/dhis/android/dashboard/api/models/DashboardItem.java
+++ b/api/src/main/java/org/hisp/dhis/android/dashboard/api/models/DashboardItem.java
@@ -108,6 +108,10 @@ public final class DashboardItem extends BaseIdentifiableObject {
@JsonProperty("messages")
boolean messages;
+ @JsonIgnore
+ @Column
+ int orderPosition;
+
public DashboardItem() {
state = State.SYNCED;
shape = SHAPE_NORMAL;
@@ -127,8 +131,8 @@ public static DashboardItem createDashboardItem(Dashboard dashboard,
.getLastUpdated(ResourceType.DASHBOARDS);
DashboardItem item = new DashboardItem();
- item.setCreated(lastUpdatedDateTime);
- item.setLastUpdated(lastUpdatedDateTime);
+ item.setCreated(LONG_DATE_FORMAT.format(lastUpdatedDateTime.toDate()));
+ item.setLastUpdated(LONG_DATE_FORMAT.format(lastUpdatedDateTime.toDate()));
item.setState(State.TO_POST);
item.setDashboard(dashboard);
item.setAccess(Access.provideDefaultAccess());
@@ -425,4 +429,12 @@ public State getState() {
public void setState(State state) {
this.state = state;
}
+
+ public int getOrderPosition() {
+ return orderPosition;
+ }
+
+ public void setOrderPosition(int orderPosition) {
+ this.orderPosition = orderPosition;
+ }
}
\ No newline at end of file
diff --git a/api/src/main/java/org/hisp/dhis/android/dashboard/api/models/DataElementDimension.java b/api/src/main/java/org/hisp/dhis/android/dashboard/api/models/DataElementDimension.java
new file mode 100644
index 00000000..14da5b36
--- /dev/null
+++ b/api/src/main/java/org/hisp/dhis/android/dashboard/api/models/DataElementDimension.java
@@ -0,0 +1,54 @@
+package org.hisp.dhis.android.dashboard.api.models;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.raizlabs.android.dbflow.annotation.Column;
+import com.raizlabs.android.dbflow.annotation.PrimaryKey;
+import com.raizlabs.android.dbflow.annotation.Table;
+import com.raizlabs.android.dbflow.structure.BaseModel;
+
+import org.hisp.dhis.android.dashboard.api.models.meta.DbDhis;
+
+@Table(databaseName = DbDhis.NAME)
+public class DataElementDimension extends BaseModel {
+ @JsonIgnore
+ @Column
+ @PrimaryKey(autoincrement = true)
+ long id;
+
+ String filter;
+
+ UIDObject dataElement;
+
+ UIDObject legendSet;
+
+ public DataElementDimension() {
+ }
+
+ public DataElementDimension(UIDObject dataElement) {
+ this.dataElement = dataElement;
+ }
+
+ public UIDObject getDataElement() {
+ return dataElement;
+ }
+
+ public void setDataElement(UIDObject dataElement) {
+ this.dataElement = dataElement;
+ }
+
+ public String getFilter() {
+ return filter;
+ }
+
+ public void setFilter(String filter) {
+ this.filter = filter;
+ }
+
+ public UIDObject getLegendSet() {
+ return legendSet;
+ }
+
+ public void setLegendSet(UIDObject legendSet) {
+ this.legendSet = legendSet;
+ }
+}
diff --git a/api/src/main/java/org/hisp/dhis/android/dashboard/api/models/EventReport.java b/api/src/main/java/org/hisp/dhis/android/dashboard/api/models/EventReport.java
new file mode 100644
index 00000000..961042a3
--- /dev/null
+++ b/api/src/main/java/org/hisp/dhis/android/dashboard/api/models/EventReport.java
@@ -0,0 +1,194 @@
+package org.hisp.dhis.android.dashboard.api.models;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.raizlabs.android.dbflow.annotation.Table;
+
+import org.hisp.dhis.android.dashboard.api.models.meta.DbDhis;
+
+import java.util.List;
+
+@Table(databaseName = DbDhis.NAME)
+public final class EventReport extends BaseIdentifiableObject {
+ @JsonIgnore
+ static final String AGGREGATED_VALUES_TYPE = "AGGREGATED_VALUES";
+ @JsonIgnore
+ static final String EVENTS_TYPE = "EVENTS";
+ @JsonIgnore
+ static final String OU_KEY = "ou";
+ @JsonIgnore
+ static final String PE_KEY = "pe";
+ @JsonIgnore
+ static final String AGGREGATE_KEY = "aggregate";
+ @JsonIgnore
+ static final String QUERY_KEY = "query";
+
+
+ UIDObject program;
+ UIDObject programStage;
+ List organisationUnits;
+ RelativePeriod relativePeriods;
+ List dataElementDimensions;
+ UIDObject dataElementValueDimension;
+ String aggregationType;
+ String outputType;
+ String dataType;
+ List attributeDimensions;
+ List filters;
+ List columns;
+
+ public UIDObject getProgram() {
+ return program;
+ }
+
+ public void setProgram(UIDObject program) {
+ this.program = program;
+ }
+
+ public UIDObject getProgramStage() {
+ return programStage;
+ }
+
+ public void setProgramStage(UIDObject programStage) {
+ this.programStage = programStage;
+ }
+
+ public List getOrganisationUnits() {
+ return organisationUnits;
+ }
+
+ public void setOrganisationUnits(
+ List organisationUnits) {
+ this.organisationUnits = organisationUnits;
+ }
+
+ public RelativePeriod getRelativePeriods() {
+ return relativePeriods;
+ }
+
+ public void setRelativePeriods(RelativePeriod relativePeriods) {
+ this.relativePeriods = relativePeriods;
+ }
+
+ public List getDataElementDimensions() {
+ return dataElementDimensions;
+ }
+
+ public void setDataElementDimensions(
+ List dataElementDimensions) {
+ this.dataElementDimensions = dataElementDimensions;
+ }
+
+ public UIDObject getDataElementValueDimension() {
+ return dataElementValueDimension;
+ }
+
+ public void setDataElementValueDimension(
+ UIDObject dataElementValueDimension) {
+ this.dataElementValueDimension = dataElementValueDimension;
+ }
+
+ public String getAggregationType() {
+ return aggregationType;
+ }
+
+ public void setAggregationType(String aggregationType) {
+ this.aggregationType = aggregationType;
+ }
+
+ public String getOutputType() {
+ return outputType;
+ }
+
+ public void setOutputType(String outputType) {
+ this.outputType = outputType;
+ }
+
+ public String getDataType() {
+ return dataType;
+ }
+
+ public void setDataType(String dataType) {
+ this.dataType = dataType;
+ }
+
+ public List getAttributeDimensions() {
+ return attributeDimensions;
+ }
+
+ public void setAttributeDimensions(
+ List attributeDimensions) {
+ this.attributeDimensions = attributeDimensions;
+ }
+
+ public List getFilters() {
+ return filters;
+ }
+
+ public void setFilters(List filters) {
+ this.filters = filters;
+ }
+
+ public List getColumns() {
+ return columns;
+ }
+
+ public void setColumns(List columns) {
+ this.columns = columns;
+ }
+
+ public String getOUDimensionFilter() {
+ String ouDimensions = "ou:";
+ boolean firstOu = true;
+ for (UIDObject organizationUnit : organisationUnits) {
+ ouDimensions +=
+ firstOu ? organizationUnit.getuId() : ";" + organizationUnit.getuId();
+ firstOu = false;
+ }
+ return ouDimensions;
+ }
+
+ public String getDimensionFilter(DataElementDimension dimension) {
+ String dimensionUID = "";
+ dimensionUID += dimension.getDataElement().getuId();
+ if (dimension.getLegendSet() != null) {
+ dimensionUID += "-" + dimension.getLegendSet().getuId();
+ }
+ if (dimension.getFilter() != null && !dimension.getFilter().isEmpty()) {
+ dimensionUID += ":" + dimension.getFilter();
+ }
+ return dimensionUID;
+ }
+
+ public boolean isOUInFilters() {
+ return isInFilters(OU_KEY);
+ }
+
+ public boolean isPEInFilters() {
+ return isInFilters(PE_KEY);
+ }
+
+ public boolean isInFilters(String key){
+ for (UIDObject filter : filters) {
+ if (filter.getuId().equals(key)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public String getDataTypeString() {
+ return (dataType.equals(AGGREGATED_VALUES_TYPE)) ? AGGREGATE_KEY : QUERY_KEY;
+ }
+
+ public boolean isValidColumn(UIDObject column) {
+ if (column.getuId().equals(PE_KEY) || column.getuId().equals(OU_KEY)) {
+ return false;
+ }
+ for (DataElementDimension dimension : dataElementDimensions) {
+ if (dimension.getDataElement().getuId().equals(column.getuId())) {
+ return false;
+ }
+ }
+ return true;
+ }
+}
diff --git a/api/src/main/java/org/hisp/dhis/android/dashboard/api/models/IdentifiableObject.java b/api/src/main/java/org/hisp/dhis/android/dashboard/api/models/IdentifiableObject.java
index e5a2986a..26e1fd2d 100755
--- a/api/src/main/java/org/hisp/dhis/android/dashboard/api/models/IdentifiableObject.java
+++ b/api/src/main/java/org/hisp/dhis/android/dashboard/api/models/IdentifiableObject.java
@@ -51,13 +51,13 @@ public interface IdentifiableObject {
void setDisplayName(String displayName);
- DateTime getCreated();
+ String getCreated();
- void setCreated(DateTime created);
+ void setCreated(String created);
- DateTime getLastUpdated();
+ String getLastUpdated();
- void setLastUpdated(DateTime lastUpdated);
+ void setLastUpdated(String lastUpdated);
Access getAccess();
@@ -80,13 +80,21 @@ class CreatedComparator implements Comparator {
@Override
public int compare(IdentifiableObject first, IdentifiableObject second) {
- if (first != null && first.getCreated() != null
- && second != null && second.getCreated() != null) {
- if (first.getCreated().isAfter(second.getCreated())) {
+ DateTime firstDate = null;
+ if(first!=null && first.getCreated()!=null) {
+ firstDate=DateTime.parse(first.getCreated());
+ }
+ DateTime secondDate = null;
+ if(second!=null && second.getCreated()!=null) {
+ secondDate=DateTime.parse(second.getCreated());
+ }
+ if (first != null && firstDate != null
+ && second != null && secondDate != null) {
+ if (firstDate.isAfter(secondDate)) {
return 1;
}
- if (second.getCreated().isAfter(first.getCreated())) {
+ if (secondDate.isAfter(firstDate)) {
return -1;
}
}
diff --git a/api/src/main/java/org/hisp/dhis/android/dashboard/api/models/Interpretation.java b/api/src/main/java/org/hisp/dhis/android/dashboard/api/models/Interpretation.java
index 938d83b4..856d15c7 100755
--- a/api/src/main/java/org/hisp/dhis/android/dashboard/api/models/Interpretation.java
+++ b/api/src/main/java/org/hisp/dhis/android/dashboard/api/models/Interpretation.java
@@ -119,8 +119,8 @@ public static InterpretationComment addComment(Interpretation interpretation, Us
.getLastUpdated(ResourceType.INTERPRETATIONS);
InterpretationComment comment = new InterpretationComment();
- comment.setCreated(lastUpdated);
- comment.setLastUpdated(lastUpdated);
+ comment.setCreated(LONG_DATE_FORMAT.format(lastUpdated.toDate()));
+ comment.setLastUpdated(LONG_DATE_FORMAT.format(lastUpdated.toDate()));
comment.setAccess(Access.provideDefaultAccess());
comment.setText(text);
comment.setState(State.TO_POST);
@@ -146,8 +146,8 @@ public static Interpretation createInterpretation(DashboardItem item, User user,
.getLastUpdated(ResourceType.INTERPRETATIONS);
Interpretation interpretation = new Interpretation();
- interpretation.setCreated(lastUpdated);
- interpretation.setLastUpdated(lastUpdated);
+ interpretation.setCreated(LONG_DATE_FORMAT.format(lastUpdated.toDate()));
+ interpretation.setLastUpdated(LONG_DATE_FORMAT.format(lastUpdated.toDate()));
interpretation.setAccess(Access.provideDefaultAccess());
interpretation.setText(text);
interpretation.setState(State.TO_POST);
diff --git a/api/src/main/java/org/hisp/dhis/android/dashboard/api/models/RelativePeriod.java b/api/src/main/java/org/hisp/dhis/android/dashboard/api/models/RelativePeriod.java
new file mode 100644
index 00000000..c329b883
--- /dev/null
+++ b/api/src/main/java/org/hisp/dhis/android/dashboard/api/models/RelativePeriod.java
@@ -0,0 +1,399 @@
+package org.hisp.dhis.android.dashboard.api.models;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.raizlabs.android.dbflow.annotation.Column;
+import com.raizlabs.android.dbflow.annotation.PrimaryKey;
+import com.raizlabs.android.dbflow.annotation.Table;
+import com.raizlabs.android.dbflow.structure.BaseModel;
+
+import org.hisp.dhis.android.dashboard.api.models.meta.DbDhis;
+
+@Table(databaseName = DbDhis.NAME)
+public final class RelativePeriod extends BaseModel {
+
+ @JsonIgnore
+ private static final String[] periodsStrings =
+ {"THIS_YEAR", "QUARTERS_LAST_YEAR", "LAST_52_WEEKS", "THIS_WEEK", "LAST_MONTH",
+ "LAST_14_DAYS", "MONTHS_THIS_YEAR", "LAST_2_SIXMONTHS", "YESTERDAY",
+ "THIS_QUARTER", "LAST_12_MONTHS", "LAST_5_FINANCIAL_YEARS", "THIS_SIX_MONTH",
+ "LAST_QUARTER", "THIS_FINANCIAL_YEAR", "LAST_4_WEEKS", "LAST_3_MONTHS",
+ "THIS_DAY", "THIS_MONTH", "LAST_5_YEARS", "LAST_6_BIMONTHS",
+ "LAST_FINANCIAL_YEAR", "LAST_6_MONTHS", "LAST_3_DAYS", "QUARTERS_THIS_YEAR",
+ "MONTHS_LAST_YEAR", "LAST_WEEK", "LAST_7_DAYS", "THIS_BIMONTH", "LAST_BIMONTH",
+ "LAST_SIX_MONTH", "LAST_YEAR", "LAST_12_WEEKS", "LAST_4_QUARTERS",
+ "BIMONTHS_THIS_YEAR", "WEEKS_THIS_YEAR"};
+
+ @JsonIgnore
+ @Column(name = "id")
+ @PrimaryKey(autoincrement = true)
+ long id;
+
+ boolean thisYear;
+ boolean quartersLastYear;
+ boolean last52Weeks;
+ boolean thisWeek;
+ boolean lastMonth;
+ boolean last14Days;
+ boolean monthsThisYear;
+ boolean last2SixMonths;
+ boolean yesterday;
+ boolean thisQuarter;
+ boolean last12Months;
+ boolean last5FinancialYears;
+ boolean thisSixMonth;
+ boolean lastQuarter;
+ boolean thisFinancialYear;
+ boolean last4Weeks;
+ boolean last3Months;
+ boolean thisDay;
+ boolean thisMonth;
+ boolean last5Years;
+ boolean last6BiMonths;
+ boolean lastFinancialYear;
+ boolean last6Months;
+ boolean last3Days;
+ boolean quartersThisYear;
+ boolean monthsLastYear;
+ boolean lastWeek;
+ boolean last7Days;
+ boolean thisBimonth;
+ boolean lastBimonth;
+ boolean lastSixMonth;
+ boolean lastYear;
+ boolean last12Weeks;
+ boolean last4Quarters;
+ boolean biMonthsThisYear;
+ boolean weeksThisYear;
+
+ @JsonIgnore
+ private boolean[] periodsList;
+
+
+ public RelativePeriod() {
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(long id) {
+ this.id = id;
+ }
+
+ public boolean[] getPeriodsList() {
+ return periodsList;
+ }
+
+ public void setPeriodsList(boolean[] periodsList) {
+ this.periodsList = periodsList;
+ }
+
+ public String getRelativePeriodString() {
+ String result = "pe:";
+ periodsList = new boolean[]{thisYear, quartersLastYear, last52Weeks, thisWeek, lastMonth,
+ last14Days, monthsThisYear, last2SixMonths, yesterday, thisQuarter, last12Months,
+ last5FinancialYears, thisSixMonth, lastQuarter, thisFinancialYear, last4Weeks,
+ last3Months, thisDay, thisMonth, last5Years, last6BiMonths, lastFinancialYear,
+ last6Months, last3Days, quartersThisYear, monthsLastYear, lastWeek, last7Days,
+ thisBimonth, lastBimonth, lastSixMonth, lastYear, last12Weeks, last4Quarters,
+ biMonthsThisYear, weeksThisYear};
+ for (int i = 0; i < periodsList.length; i++) {
+ if (periodsList[i]) {
+ if (i == 0) {
+ result += periodsStrings[i];
+ } else {
+ result += ";" + periodsStrings[i];
+ }
+ }
+ }
+ return result;
+ }
+
+ public boolean isThisYear() {
+ return thisYear;
+ }
+
+ public void setThisYear(boolean thisYear) {
+ this.thisYear = thisYear;
+ }
+
+ public boolean isQuartersLastYear() {
+ return quartersLastYear;
+ }
+
+ public void setQuartersLastYear(boolean quartersLastYear) {
+ this.quartersLastYear = quartersLastYear;
+ }
+
+ public boolean isLast52Weeks() {
+ return last52Weeks;
+ }
+
+ public void setLast52Weeks(boolean last52Weeks) {
+ this.last52Weeks = last52Weeks;
+ }
+
+ public boolean isThisWeek() {
+ return thisWeek;
+ }
+
+ public void setThisWeek(boolean thisWeek) {
+ this.thisWeek = thisWeek;
+ }
+
+ public boolean isLastMonth() {
+ return lastMonth;
+ }
+
+ public void setLastMonth(boolean lastMonth) {
+ this.lastMonth = lastMonth;
+ }
+
+ public boolean isLast14Days() {
+ return last14Days;
+ }
+
+ public void setLast14Days(boolean last14Days) {
+ this.last14Days = last14Days;
+ }
+
+ public boolean isMonthsThisYear() {
+ return monthsThisYear;
+ }
+
+ public void setMonthsThisYear(boolean monthsThisYear) {
+ this.monthsThisYear = monthsThisYear;
+ }
+
+ public boolean isLast2SixMonths() {
+ return last2SixMonths;
+ }
+
+ public void setLast2SixMonths(boolean last2SixMonths) {
+ this.last2SixMonths = last2SixMonths;
+ }
+
+ public boolean isYesterday() {
+ return yesterday;
+ }
+
+ public void setYesterday(boolean yesterday) {
+ this.yesterday = yesterday;
+ }
+
+ public boolean isThisQuarter() {
+ return thisQuarter;
+ }
+
+ public void setThisQuarter(boolean thisQuarter) {
+ this.thisQuarter = thisQuarter;
+ }
+
+ public boolean isLast12Months() {
+ return last12Months;
+ }
+
+ public void setLast12Months(boolean last12Months) {
+ this.last12Months = last12Months;
+ }
+
+ public boolean isLast5FinancialYears() {
+ return last5FinancialYears;
+ }
+
+ public void setLast5FinancialYears(boolean last5FinancialYears) {
+ this.last5FinancialYears = last5FinancialYears;
+ }
+
+ public boolean isThisSixMonth() {
+ return thisSixMonth;
+ }
+
+ public void setThisSixMonth(boolean thisSixMonth) {
+ this.thisSixMonth = thisSixMonth;
+ }
+
+ public boolean isLastQuarter() {
+ return lastQuarter;
+ }
+
+ public void setLastQuarter(boolean lastQuarter) {
+ this.lastQuarter = lastQuarter;
+ }
+
+ public boolean isThisFinancialYear() {
+ return thisFinancialYear;
+ }
+
+ public void setThisFinancialYear(boolean thisFinancialYear) {
+ this.thisFinancialYear = thisFinancialYear;
+ }
+
+ public boolean isLast4Weeks() {
+ return last4Weeks;
+ }
+
+ public void setLast4Weeks(boolean last4Weeks) {
+ this.last4Weeks = last4Weeks;
+ }
+
+ public boolean isLast3Months() {
+ return last3Months;
+ }
+
+ public void setLast3Months(boolean last3Months) {
+ this.last3Months = last3Months;
+ }
+
+ public boolean isThisDay() {
+ return thisDay;
+ }
+
+ public void setThisDay(boolean thisDay) {
+ this.thisDay = thisDay;
+ }
+
+ public boolean isThisMonth() {
+ return thisMonth;
+ }
+
+ public void setThisMonth(boolean thisMonth) {
+ this.thisMonth = thisMonth;
+ }
+
+ public boolean isLast5Years() {
+ return last5Years;
+ }
+
+ public void setLast5Years(boolean last5Years) {
+ this.last5Years = last5Years;
+ }
+
+ public boolean isLast6BiMonths() {
+ return last6BiMonths;
+ }
+
+ public void setLast6BiMonths(boolean last6BiMonths) {
+ this.last6BiMonths = last6BiMonths;
+ }
+
+ public boolean isLastFinancialYear() {
+ return lastFinancialYear;
+ }
+
+ public void setLastFinancialYear(boolean lastFinancialYear) {
+ this.lastFinancialYear = lastFinancialYear;
+ }
+
+ public boolean isLast6Months() {
+ return last6Months;
+ }
+
+ public void setLast6Months(boolean last6Months) {
+ this.last6Months = last6Months;
+ }
+
+ public boolean isLast3Days() {
+ return last3Days;
+ }
+
+ public void setLast3Days(boolean last3Days) {
+ this.last3Days = last3Days;
+ }
+
+ public boolean isQuartersThisYear() {
+ return quartersThisYear;
+ }
+
+ public void setQuartersThisYear(boolean quartersThisYear) {
+ this.quartersThisYear = quartersThisYear;
+ }
+
+ public boolean isMonthsLastYear() {
+ return monthsLastYear;
+ }
+
+ public void setMonthsLastYear(boolean monthsLastYear) {
+ this.monthsLastYear = monthsLastYear;
+ }
+
+ public boolean isLastWeek() {
+ return lastWeek;
+ }
+
+ public void setLastWeek(boolean lastWeek) {
+ this.lastWeek = lastWeek;
+ }
+
+ public boolean isLast7Days() {
+ return last7Days;
+ }
+
+ public void setLast7Days(boolean last7Days) {
+ this.last7Days = last7Days;
+ }
+
+ public boolean isThisBimonth() {
+ return thisBimonth;
+ }
+
+ public void setThisBimonth(boolean thisBimonth) {
+ this.thisBimonth = thisBimonth;
+ }
+
+ public boolean isLastBimonth() {
+ return lastBimonth;
+ }
+
+ public void setLastBimonth(boolean lastBimonth) {
+ this.lastBimonth = lastBimonth;
+ }
+
+ public boolean isLastSixMonth() {
+ return lastSixMonth;
+ }
+
+ public void setLastSixMonth(boolean lastSixMonth) {
+ this.lastSixMonth = lastSixMonth;
+ }
+
+ public boolean isLastYear() {
+ return lastYear;
+ }
+
+ public void setLastYear(boolean lastYear) {
+ this.lastYear = lastYear;
+ }
+
+ public boolean isLast12Weeks() {
+ return last12Weeks;
+ }
+
+ public void setLast12Weeks(boolean last12Weeks) {
+ this.last12Weeks = last12Weeks;
+ }
+
+ public boolean isLast4Quarters() {
+ return last4Quarters;
+ }
+
+ public void setLast4Quarters(boolean last4Quarters) {
+ this.last4Quarters = last4Quarters;
+ }
+
+ public boolean isBiMonthsThisYear() {
+ return biMonthsThisYear;
+ }
+
+ public void setBiMonthsThisYear(boolean biMonthsThisYear) {
+ this.biMonthsThisYear = biMonthsThisYear;
+ }
+
+ public boolean isWeeksThisYear() {
+ return weeksThisYear;
+ }
+
+ public void setWeeksThisYear(boolean weeksThisYear) {
+ this.weeksThisYear = weeksThisYear;
+ }
+}
diff --git a/api/src/main/java/org/hisp/dhis/android/dashboard/api/models/UIDObject.java b/api/src/main/java/org/hisp/dhis/android/dashboard/api/models/UIDObject.java
new file mode 100644
index 00000000..d4cfc892
--- /dev/null
+++ b/api/src/main/java/org/hisp/dhis/android/dashboard/api/models/UIDObject.java
@@ -0,0 +1,46 @@
+package org.hisp.dhis.android.dashboard.api.models;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.raizlabs.android.dbflow.annotation.Column;
+import com.raizlabs.android.dbflow.annotation.PrimaryKey;
+import com.raizlabs.android.dbflow.annotation.Table;
+import com.raizlabs.android.dbflow.structure.BaseModel;
+
+import org.hisp.dhis.android.dashboard.api.models.meta.DbDhis;
+
+@Table(databaseName = DbDhis.NAME)
+public class UIDObject extends BaseModel {
+ @JsonIgnore
+ @Column(name = "id")
+ @PrimaryKey(autoincrement = true)
+ long id;
+
+ @JsonProperty("id")
+ @Column(name = "uId")
+ String uId;
+
+ public UIDObject() {
+ }
+
+ public UIDObject(String uId) {
+ this.uId = uId;
+ }
+
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(long id) {
+ this.id = id;
+ }
+
+ public String getuId() {
+ return uId;
+ }
+
+ public void setuId(String uId) {
+ this.uId = uId;
+ }
+}
diff --git a/api/src/main/java/org/hisp/dhis/android/dashboard/api/models/UserAccount.java b/api/src/main/java/org/hisp/dhis/android/dashboard/api/models/UserAccount.java
index 182185cf..e65db0e9 100755
--- a/api/src/main/java/org/hisp/dhis/android/dashboard/api/models/UserAccount.java
+++ b/api/src/main/java/org/hisp/dhis/android/dashboard/api/models/UserAccount.java
@@ -68,11 +68,11 @@ public final class UserAccount extends BaseModel implements IdentifiableObject {
@JsonProperty("created")
@Column(name = "created")
- DateTime created;
+ String created;
@JsonProperty("lastUpdated")
@Column(name = "lastUpdated")
- DateTime lastUpdated;
+ String lastUpdated;
@JsonProperty("access")
@Column(name = "access")
@@ -151,7 +151,7 @@ public static User toUser(UserAccount userAccount) {
User user = new User();
user.setUId(userAccount.getUId());
user.setAccess(userAccount.getAccess());
- user.setCreated(user.getCreated());
+ user.setCreated(userAccount.getCreated());
user.setLastUpdated(userAccount.getLastUpdated());
user.setName(userAccount.getName());
user.setDisplayName(userAccount.getDisplayName());
@@ -208,25 +208,25 @@ public void setDisplayName(String displayName) {
@JsonIgnore
@Override
- public DateTime getCreated() {
+ public String getCreated() {
return created;
}
@JsonIgnore
@Override
- public void setCreated(DateTime created) {
+ public void setCreated(String created) {
this.created = created;
}
@JsonIgnore
@Override
- public DateTime getLastUpdated() {
+ public String getLastUpdated() {
return lastUpdated;
}
@JsonIgnore
@Override
- public void setLastUpdated(DateTime lastUpdated) {
+ public void setLastUpdated(String lastUpdated) {
this.lastUpdated = lastUpdated;
}
diff --git a/api/src/main/java/org/hisp/dhis/android/dashboard/api/models/meta/DbDhis.java b/api/src/main/java/org/hisp/dhis/android/dashboard/api/models/meta/DbDhis.java
index 0d8492e9..bfc838c6 100755
--- a/api/src/main/java/org/hisp/dhis/android/dashboard/api/models/meta/DbDhis.java
+++ b/api/src/main/java/org/hisp/dhis/android/dashboard/api/models/meta/DbDhis.java
@@ -34,5 +34,5 @@
@Database(name = DbDhis.NAME, version = DbDhis.VERSION)
public final class DbDhis {
public static final String NAME = "dhis";
- public static final int VERSION = 3;
+ public static final int VERSION = 4;
}
diff --git a/api/src/main/java/org/hisp/dhis/android/dashboard/api/models/meta/migrations/MigrationAddOrderPosToDashboardItem.java b/api/src/main/java/org/hisp/dhis/android/dashboard/api/models/meta/migrations/MigrationAddOrderPosToDashboardItem.java
new file mode 100644
index 00000000..ba34e06c
--- /dev/null
+++ b/api/src/main/java/org/hisp/dhis/android/dashboard/api/models/meta/migrations/MigrationAddOrderPosToDashboardItem.java
@@ -0,0 +1,21 @@
+package org.hisp.dhis.android.dashboard.api.models.meta.migrations;
+
+import com.raizlabs.android.dbflow.annotation.Migration;
+import com.raizlabs.android.dbflow.sql.migration.AlterTableMigration;
+
+import org.hisp.dhis.android.dashboard.api.models.DashboardItem;
+import org.hisp.dhis.android.dashboard.api.models.meta.DbDhis;
+
+@Migration(version = 4, databaseName = DbDhis.NAME)
+public class MigrationAddOrderPosToDashboardItem extends AlterTableMigration {
+
+
+ public MigrationAddOrderPosToDashboardItem() {
+ super(DashboardItem.class);
+ }
+
+ @Override
+ public void onPreMigrate() {
+ addColumn(Integer.class, "orderPosition");
+ }
+}
diff --git a/api/src/main/java/org/hisp/dhis/android/dashboard/api/network/DhisApi.java b/api/src/main/java/org/hisp/dhis/android/dashboard/api/network/DhisApi.java
index c7a77540..a5901953 100755
--- a/api/src/main/java/org/hisp/dhis/android/dashboard/api/network/DhisApi.java
+++ b/api/src/main/java/org/hisp/dhis/android/dashboard/api/network/DhisApi.java
@@ -31,6 +31,7 @@
import org.hisp.dhis.android.dashboard.api.models.Dashboard;
import org.hisp.dhis.android.dashboard.api.models.DashboardItem;
import org.hisp.dhis.android.dashboard.api.models.DashboardItemContent;
+import org.hisp.dhis.android.dashboard.api.models.EventReport;
import org.hisp.dhis.android.dashboard.api.models.Interpretation;
import org.hisp.dhis.android.dashboard.api.models.SystemInfo;
import org.hisp.dhis.android.dashboard.api.models.UserAccount;
@@ -141,6 +142,22 @@ Response deleteDashboardItemContent(@Path("dashboardUid") String dashboardUid,
@GET("/reportTables/{id}/data.html")
Response getReportTableData(@Path("id") String id);
+ @Headers("Accept: application/json")
+ @GET("/eventReports/{id}")
+ EventReport getEventReport(@Path("id") String id);
+
+ @Headers("Accept: application/text")
+ @GET("/analytics/events/{dataType}/{program}"
+ + ".html+css?displayProperty=NAME")
+ Response getEventReportTableData(@Path("program") String program,
+ @Query("stage") String programStage,
+ @Query("dimension") List dimensions,
+ @Query("outputType") String outputType,
+ @Query("aggregationType") String aggregationType,
+ @Query("value") String value,
+ @Path("dataType") String dataType,
+ @Query("filter") List filter);
+
@GET("/eventReports?paging=false")
@Headers("Accept: application/json")
Map> getEventReports(@QueryMap Map queryParams);
@@ -207,4 +224,5 @@ Response putInterpretationComment(@Path("interpretationUid") String interpretati
@DELETE("/interpretations/{interpretationUid}/comments/{commentUid}")
Response deleteInterpretationComment(@Path("interpretationUid") String interpretationUid,
@Path("commentUid") String commentUid);
+
}
\ No newline at end of file
diff --git a/api/src/main/java/org/hisp/dhis/android/dashboard/api/network/RepoManager.java b/api/src/main/java/org/hisp/dhis/android/dashboard/api/network/RepoManager.java
index 17cf63af..c06a851c 100755
--- a/api/src/main/java/org/hisp/dhis/android/dashboard/api/network/RepoManager.java
+++ b/api/src/main/java/org/hisp/dhis/android/dashboard/api/network/RepoManager.java
@@ -28,6 +28,13 @@
package org.hisp.dhis.android.dashboard.api.network;
+import static com.squareup.okhttp.Credentials.basic;
+
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+
+import com.squareup.okhttp.Cache;
import com.squareup.okhttp.HttpUrl;
import com.squareup.okhttp.Interceptor;
import com.squareup.okhttp.OkHttpClient;
@@ -38,19 +45,19 @@
import org.hisp.dhis.android.dashboard.api.models.meta.Credentials;
import org.hisp.dhis.android.dashboard.api.utils.ObjectMapperProvider;
+import java.io.File;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.util.concurrent.TimeUnit;
import retrofit.ErrorHandler;
+import retrofit.RequestInterceptor;
import retrofit.RestAdapter;
import retrofit.RetrofitError;
import retrofit.client.OkClient;
import retrofit.converter.Converter;
import retrofit.converter.JacksonConverter;
-import static com.squareup.okhttp.Credentials.basic;
-
public final class RepoManager {
static final int DEFAULT_CONNECT_TIMEOUT_MILLIS = 15 * 1000; // 15s
@@ -61,13 +68,15 @@ private RepoManager() {
// no instances
}
- public static DhisApi createService(HttpUrl serverUrl, Credentials credentials) {
+ public static DhisApi createService(HttpUrl serverUrl, Credentials credentials,
+ final Context context) {
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint(provideServerUrl(serverUrl))
.setConverter(provideJacksonConverter())
- .setClient(provideOkClient(credentials))
+ .setClient(provideOkClient(credentials, context))
.setErrorHandler(new RetrofitErrorHandler())
.setLogLevel(RestAdapter.LogLevel.BASIC)
+ .setRequestInterceptor(new ConnectionInterceptor(context))
.build();
return restAdapter.create(DhisApi.class);
}
@@ -82,19 +91,28 @@ private static Converter provideJacksonConverter() {
return new JacksonConverter(ObjectMapperProvider.getInstance());
}
- private static OkClient provideOkClient(Credentials credentials) {
- return new OkClient(provideOkHttpClient(credentials));
+ private static OkClient provideOkClient(Credentials credentials, Context context) {
+ return new OkClient(provideOkHttpClient(credentials, context));
}
- public static OkHttpClient provideOkHttpClient(Credentials credentials) {
+ public static OkHttpClient provideOkHttpClient(Credentials credentials, Context context) {
+
OkHttpClient client = new OkHttpClient();
client.interceptors().add(provideInterceptor(credentials));
client.setConnectTimeout(DEFAULT_CONNECT_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
client.setReadTimeout(DEFAULT_READ_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
client.setWriteTimeout(DEFAULT_WRITE_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
+ client.setCache(provideCache(context));
return client;
}
+ private static Cache provideCache(Context context) {
+ File httpCacheDirectory = new File(context.getCacheDir(), "responses");
+ Cache cache = null;
+ cache = new Cache(httpCacheDirectory, 10 * 1024 * 1024);
+ return cache;
+ }
+
private static Interceptor provideInterceptor(Credentials credentials) {
return new AuthInterceptor(credentials.getUsername(), credentials.getPassword());
}
@@ -132,4 +150,33 @@ public Throwable handleError(RetrofitError cause) {
return APIException.fromRetrofitError(cause);
}
}
+
+ private static boolean isOnline(Context context) {
+ ConnectivityManager cm =
+ (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+ NetworkInfo netInfo = cm.getActiveNetworkInfo();
+ return netInfo != null && netInfo.isConnectedOrConnecting();
+ }
+
+ private static class ConnectionInterceptor implements RequestInterceptor {
+ private Context mContext;
+
+ public ConnectionInterceptor(Context context) {
+ mContext = context;
+ }
+
+ @Override
+ public void intercept(RequestFacade request) {
+ request.addHeader("Accept", "application/json;versions=1");
+ if (isOnline(mContext)) {
+ int maxAge = 0; // no read cache if there is internet
+ request.addHeader("Cache-Control", "public, max-age=" + maxAge);
+ } else {
+ int maxStale = 60 * 60 * 24 * 365; // tolerate 1 year state
+ request.addHeader("Cache-Control",
+ "public, only-if-cached, max-stale=" + maxStale);
+ }
+ }
+ }
+
}
diff --git a/api/src/main/java/org/hisp/dhis/android/dashboard/api/persistence/preferences/ResourceType.java b/api/src/main/java/org/hisp/dhis/android/dashboard/api/persistence/preferences/ResourceType.java
index 943a094a..aefdc8d4 100755
--- a/api/src/main/java/org/hisp/dhis/android/dashboard/api/persistence/preferences/ResourceType.java
+++ b/api/src/main/java/org/hisp/dhis/android/dashboard/api/persistence/preferences/ResourceType.java
@@ -4,5 +4,5 @@
* @author Araz Abishov .
*/
public enum ResourceType {
- DASHBOARDS_CONTENT, DASHBOARDS, INTERPRETATIONS, USERS,
+ DASHBOARDS_CONTENT, DASHBOARDS, INTERPRETATIONS, USERS, INTERPRETATION_IMAGES, DASHBOARD_IMAGES
}
diff --git a/api/src/main/java/org/hisp/dhis/android/dashboard/api/persistence/preferences/SettingsManager.java b/api/src/main/java/org/hisp/dhis/android/dashboard/api/persistence/preferences/SettingsManager.java
new file mode 100644
index 00000000..55c78041
--- /dev/null
+++ b/api/src/main/java/org/hisp/dhis/android/dashboard/api/persistence/preferences/SettingsManager.java
@@ -0,0 +1,38 @@
+package org.hisp.dhis.android.dashboard.api.persistence.preferences;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+
+public class SettingsManager {
+ public static final String CHART_WIDTH = "key:chart_width";
+ public static final String CHART_HEIGHT = "key:chart_height";
+ public static final String MINIMUM_WIDTH = "480";
+ public static final String MINIMUM_HEIGHT = "320";
+ private static final String PREFERENCES = "preferences:settings";
+ public static final String MAXIMUM_WIDTH = "1920";
+ public static final String MAXIMUM_HEIGHT = "1080";
+ private static SettingsManager mSettingsManager = null;
+ private SharedPreferences mPrefs;
+
+ public SettingsManager(Context context) {
+ mPrefs = context.getSharedPreferences(SettingsManager.PREFERENCES,
+ Context.MODE_PRIVATE);
+ }
+
+ public static SettingsManager getInstance(Context context) {
+ if (mSettingsManager == null) {
+ mSettingsManager = new SettingsManager(context);
+ }
+ return mSettingsManager;
+ }
+
+ public void setPreference(String key, String value) {
+ mPrefs.edit().putString(key, value).commit();
+ }
+
+ public String getPreference(String key, String defaultValue) {
+ return mPrefs.getString(key, defaultValue);
+ }
+
+
+}
diff --git a/api/src/main/java/org/hisp/dhis/android/dashboard/api/utils/DbUtils.java b/api/src/main/java/org/hisp/dhis/android/dashboard/api/utils/DbUtils.java
index 6d830bd2..6235b397 100755
--- a/api/src/main/java/org/hisp/dhis/android/dashboard/api/utils/DbUtils.java
+++ b/api/src/main/java/org/hisp/dhis/android/dashboard/api/utils/DbUtils.java
@@ -94,14 +94,11 @@ public static List createOperati
continue;
}
- // if the last updated field in up to date model is after the same
- // field in persisted model, it means we need to update it.
- if (newModel.getLastUpdated().isAfter(oldModel.getLastUpdated())) {
+ //always updating to save changes not from the server
// note, we need to pass database primary id to updated model
// in order to avoid creation of new object.
newModel.setId(oldModel.getId());
ops.add(DbOperation.update(newModel));
- }
// as we have processed given old (persisted) model,
// we can remove it from map of new models.
diff --git a/api/src/main/java/org/hisp/dhis/android/dashboard/api/utils/NetworkUtils.java b/api/src/main/java/org/hisp/dhis/android/dashboard/api/utils/NetworkUtils.java
index 0316a38a..a1802d71 100755
--- a/api/src/main/java/org/hisp/dhis/android/dashboard/api/utils/NetworkUtils.java
+++ b/api/src/main/java/org/hisp/dhis/android/dashboard/api/utils/NetworkUtils.java
@@ -67,6 +67,7 @@ public static Header findLocationHeader(List headers) {
}
public static void handleApiException(APIException apiException) throws APIException {
+ apiException.printStackTrace();
handleApiException(apiException, null);
}
diff --git a/api/src/main/java/org/hisp/dhis/android/dashboard/api/utils/PicassoProvider.java b/api/src/main/java/org/hisp/dhis/android/dashboard/api/utils/PicassoProvider.java
index 03fb8567..f5d868a3 100755
--- a/api/src/main/java/org/hisp/dhis/android/dashboard/api/utils/PicassoProvider.java
+++ b/api/src/main/java/org/hisp/dhis/android/dashboard/api/utils/PicassoProvider.java
@@ -44,14 +44,15 @@ public final class PicassoProvider {
private PicassoProvider() {
}
- public static Picasso getInstance(Context context) {
- if (mPicasso == null) {
+ public static Picasso getInstance(Context context, boolean changeCredentials) {
+ if (mPicasso == null || changeCredentials) {
OkHttpClient client = RepoManager.provideOkHttpClient(
- DhisController.getInstance().getUserCredentials());
-
+ DhisController.getInstance().getUserCredentials(), context);
mPicasso = new Picasso.Builder(context)
.downloader(new OkHttpDownloader(client))
.build();
+ mPicasso.setIndicatorsEnabled(false);
+ mPicasso.setLoggingEnabled(false);
}
return mPicasso;
diff --git a/api/src/test/java/org/hisp/dhis/android/dashboard/api/PreconditionsTests.java b/api/src/test/java/org/hisp/dhis/android/dashboard/api/PreconditionsTests.java
new file mode 100644
index 00000000..deaf35cc
--- /dev/null
+++ b/api/src/test/java/org/hisp/dhis/android/dashboard/api/PreconditionsTests.java
@@ -0,0 +1,18 @@
+package org.hisp.dhis.android.dashboard.api;
+
+import org.hisp.dhis.android.dashboard.api.utils.Preconditions;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+public class PreconditionsTests {
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ @Test
+ public void precondition_null_exception() {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("test_message");
+ Preconditions.isNull(null, "test_message");
+ }
+}
diff --git a/api/src/test/java/org/hisp/dhis/android/dashboard/api/commons/DateTestUtils.java b/api/src/test/java/org/hisp/dhis/android/dashboard/api/commons/DateTestUtils.java
new file mode 100644
index 00000000..d69740ca
--- /dev/null
+++ b/api/src/test/java/org/hisp/dhis/android/dashboard/api/commons/DateTestUtils.java
@@ -0,0 +1,27 @@
+package org.hisp.dhis.android.dashboard.api.commons;
+
+import org.joda.time.DateTime;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.TimeZone;
+
+public class DateTestUtils {
+ public final static String DHIS2_GMT_NEW_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSS";
+
+ private static Date parseDate(String date, String format) {
+ try {
+ SimpleDateFormat sdf = new SimpleDateFormat(format);
+ sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
+ return sdf.parse(date);
+ } catch (ParseException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ public static boolean compareParsedDateWithStringDate(DateTime date, String isDate) {
+ return date.toDate().getTime() == (parseDate(isDate, DHIS2_GMT_NEW_DATE_FORMAT).getTime());
+ }
+}
diff --git a/api/src/test/java/org/hisp/dhis/android/dashboard/api/commons/FileReader.java b/api/src/test/java/org/hisp/dhis/android/dashboard/api/commons/FileReader.java
new file mode 100644
index 00000000..90dc5bcc
--- /dev/null
+++ b/api/src/test/java/org/hisp/dhis/android/dashboard/api/commons/FileReader.java
@@ -0,0 +1,28 @@
+package org.hisp.dhis.android.dashboard.api.commons;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.URL;
+
+public class FileReader {
+ private File getFile(String filename) {
+ ClassLoader classLoader = getClass().getClassLoader();
+ URL resource = classLoader.getResource(filename);
+ return new File(resource.getPath());
+ }
+
+ public String getStringFromFile(String filename) throws IOException {
+ FileInputStream inputStream = new FileInputStream(getFile(filename));
+ InputStreamReader isr = new InputStreamReader(inputStream);
+ BufferedReader bufferedReader = new BufferedReader(isr);
+ StringBuilder sb = new StringBuilder();
+ String line;
+ while ((line = bufferedReader.readLine()) != null) {
+ sb.append(line);
+ }
+ return sb.toString();
+ }
+}
diff --git a/api/src/test/java/org/hisp/dhis/android/dashboard/api/commons/JsonParser.java b/api/src/test/java/org/hisp/dhis/android/dashboard/api/commons/JsonParser.java
new file mode 100644
index 00000000..3512c207
--- /dev/null
+++ b/api/src/test/java/org/hisp/dhis/android/dashboard/api/commons/JsonParser.java
@@ -0,0 +1,15 @@
+package org.hisp.dhis.android.dashboard.api.commons;
+
+import org.hisp.dhis.android.dashboard.api.utils.ObjectMapperProvider;
+
+import java.io.IOException;
+
+public class JsonParser {
+
+
+ public static Object getModelFromJson(Class modelClass, String json) throws IOException {
+ return ObjectMapperProvider.getInstance()
+ .readValue(json, modelClass);
+ }
+
+}
\ No newline at end of file
diff --git a/api/src/test/java/org/hisp/dhis/android/dashboard/api/converters/AccessConverterTests.java b/api/src/test/java/org/hisp/dhis/android/dashboard/api/converters/AccessConverterTests.java
new file mode 100644
index 00000000..b64e79d4
--- /dev/null
+++ b/api/src/test/java/org/hisp/dhis/android/dashboard/api/converters/AccessConverterTests.java
@@ -0,0 +1,48 @@
+package org.hisp.dhis.android.dashboard.api.converters;
+
+import static junit.framework.Assert.assertTrue;
+
+import org.hisp.dhis.android.dashboard.api.commons.FileReader;
+import org.hisp.dhis.android.dashboard.api.models.Access;
+import org.hisp.dhis.android.dashboard.api.persistence.converters.AccessConverter;
+import org.junit.Test;
+
+import java.io.IOException;
+
+public class AccessConverterTests {
+ public static final String ACCESS_ALL_FALSE_STRING_TXT = "access_all_false_string.json";
+ public static final String ACCESS_ALL_TRUE_STRING_TXT = "access_all_true_string.json";
+ AccessConverter accessConverter = new AccessConverter();
+
+ @Test
+ public void convert_access_object_to_database_string() throws Exception {
+ String access = getAccessFromJson(ACCESS_ALL_TRUE_STRING_TXT);
+ assertTrue(accessConverter.getDBValue(Access.provideDefaultAccess()).equals(access));
+ }
+
+ @Test
+ public void convert_access_all_true_database_string_to_model() throws IOException {
+ Access access = accessConverter.getModelValue(
+ getAccessFromJson(ACCESS_ALL_TRUE_STRING_TXT));
+ assertTrue(access.isDelete());
+ assertTrue(access.isRead());
+ assertTrue(access.isWrite());
+ assertTrue(access.isManage());
+ assertTrue(access.isExternalize());
+ }
+
+ @Test
+ public void convert_access_all_false_database_string_to_model() throws IOException {
+ Access access = accessConverter.getModelValue(
+ getAccessFromJson(ACCESS_ALL_FALSE_STRING_TXT));
+ assertTrue(!access.isDelete());
+ assertTrue(!access.isRead());
+ assertTrue(!access.isWrite());
+ assertTrue(!access.isManage());
+ assertTrue(!access.isExternalize());
+ }
+
+ private String getAccessFromJson(String json) throws IOException {
+ return new FileReader().getStringFromFile(json).replaceAll(" ", "").replace("\t", "");
+ }
+}
diff --git a/api/src/test/java/org/hisp/dhis/android/dashboard/api/converters/DateTimeConverterTests.java b/api/src/test/java/org/hisp/dhis/android/dashboard/api/converters/DateTimeConverterTests.java
new file mode 100644
index 00000000..4820d504
--- /dev/null
+++ b/api/src/test/java/org/hisp/dhis/android/dashboard/api/converters/DateTimeConverterTests.java
@@ -0,0 +1,46 @@
+package org.hisp.dhis.android.dashboard.api.converters;
+
+import static junit.framework.Assert.assertTrue;
+
+import org.hisp.dhis.android.dashboard.api.commons.DateTestUtils;
+import org.hisp.dhis.android.dashboard.api.persistence.converters.DateTimeConverter;
+import org.joda.time.DateTime;
+import org.junit.Test;
+
+import java.util.Calendar;
+import java.util.TimeZone;
+
+public class DateTimeConverterTests {
+
+ public static final String DATETIME_AS_STRING = "2016-04-21T15:37:07.740Z";
+
+ DateTimeConverter dateTimeConverter = new DateTimeConverter();
+
+ @Test
+ public void convert_datetime_string_to_object() throws Exception {
+ DateTime convertedDate = dateTimeConverter.getModelValue(DATETIME_AS_STRING);
+
+ assertTrue(DateTestUtils.compareParsedDateWithStringDate(convertedDate, DATETIME_AS_STRING));
+ }
+
+ @Test
+ public void convert_datetime_object_to_string() throws Exception {
+ String converterDate = dateTimeConverter.getDBValue(createStubDateTime());
+
+ assertTrue(DateTestUtils.compareParsedDateWithStringDate(createStubDateTime(), converterDate));
+ }
+
+
+ private DateTime createStubDateTime(){
+ Calendar calendar = Calendar.getInstance();
+ calendar.setTimeZone(TimeZone.getTimeZone("UTC"));
+ calendar.set(Calendar.YEAR, 2016);
+ calendar.set(Calendar.MONTH, 04);
+ calendar.set(Calendar.DAY_OF_MONTH, 21);
+ calendar.set(Calendar.HOUR_OF_DAY, 15);
+ calendar.set(Calendar.MINUTE, 37);
+ calendar.set(Calendar.SECOND, 07);
+ calendar.set(Calendar.MILLISECOND, 740);
+ return new DateTime(calendar);
+ }
+}
diff --git a/api/src/test/java/org/hisp/dhis/android/dashboard/api/converters/StateConverterTests.java b/api/src/test/java/org/hisp/dhis/android/dashboard/api/converters/StateConverterTests.java
new file mode 100644
index 00000000..fbe2fa59
--- /dev/null
+++ b/api/src/test/java/org/hisp/dhis/android/dashboard/api/converters/StateConverterTests.java
@@ -0,0 +1,56 @@
+package org.hisp.dhis.android.dashboard.api.converters;
+
+import static junit.framework.Assert.assertTrue;
+
+import org.hisp.dhis.android.dashboard.api.models.meta.State;
+import org.hisp.dhis.android.dashboard.api.persistence.converters.StateConverter;
+import org.junit.Test;
+
+public class StateConverterTests {
+ public static final String STATE_SYNCED = "SYNCED";
+ public static final String STATE_TO_POST = "TO_POST";
+ public static final String STATE_TO_UPDATE = "TO_UPDATE";
+ public static final String STATE_TO_DELETE = "TO_DELETE";
+
+ StateConverter stateConverter = new StateConverter();
+
+ @Test
+ public void convert_state_to_post_string_to_object() throws Exception {
+ assertTrue(stateConverter.getModelValue(STATE_TO_POST).equals(State.TO_POST));
+ }
+
+ @Test
+ public void convert_state_to_post_object_to_string() throws Exception {
+ assertTrue(stateConverter.getDBValue(State.TO_POST).equals(STATE_TO_POST));
+ }
+
+ @Test
+ public void convert_state_to_delete_string_to_object() throws Exception {
+ assertTrue(stateConverter.getModelValue(STATE_TO_DELETE).equals(State.TO_DELETE));
+ }
+
+ @Test
+ public void convert_state_to_delete_object_to_string() throws Exception {
+ assertTrue(stateConverter.getDBValue(State.TO_DELETE).equals(STATE_TO_DELETE));
+ }
+
+ @Test
+ public void convert_state_to_update_string_to_object() throws Exception {
+ assertTrue(stateConverter.getModelValue(STATE_TO_UPDATE).equals(State.TO_UPDATE));
+ }
+
+ @Test
+ public void convert_state_to_update_object_to_string() throws Exception {
+ assertTrue(stateConverter.getDBValue(State.TO_UPDATE).equals(STATE_TO_UPDATE));
+ }
+
+ @Test
+ public void convert_state_synced_string_to_object() throws Exception {
+ assertTrue(stateConverter.getModelValue(STATE_SYNCED).equals(State.SYNCED));
+ }
+
+ @Test
+ public void convert_state_synced_object_to_string() throws Exception {
+ assertTrue(stateConverter.getDBValue(State.SYNCED).equals(STATE_SYNCED));
+ }
+}
diff --git a/api/src/test/java/org/hisp/dhis/android/dashboard/api/meta/CredentialsTests.java b/api/src/test/java/org/hisp/dhis/android/dashboard/api/meta/CredentialsTests.java
new file mode 100644
index 00000000..f35115eb
--- /dev/null
+++ b/api/src/test/java/org/hisp/dhis/android/dashboard/api/meta/CredentialsTests.java
@@ -0,0 +1,27 @@
+package org.hisp.dhis.android.dashboard.api.meta;
+
+import org.hisp.dhis.android.dashboard.api.models.meta.Credentials;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+public class CredentialsTests {
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ @Test
+ public void throw_exception_if_username_is_not_provided() throws Exception {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("Username must not be null");
+
+ new Credentials(null, "pwd");
+ }
+
+ @Test
+ public void throw_exception_if_password_is_not_provided() throws Exception {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("Password must not be null");
+
+ new Credentials("user", null);
+ }
+}
diff --git a/api/src/test/java/org/hisp/dhis/android/dashboard/api/network/ApiExceptionTests.java b/api/src/test/java/org/hisp/dhis/android/dashboard/api/network/ApiExceptionTests.java
new file mode 100644
index 00000000..7451f712
--- /dev/null
+++ b/api/src/test/java/org/hisp/dhis/android/dashboard/api/network/ApiExceptionTests.java
@@ -0,0 +1,74 @@
+package org.hisp.dhis.android.dashboard.api.network;
+
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import retrofit.RetrofitError;
+import retrofit.client.Header;
+import retrofit.client.Response;
+import retrofit.converter.ConversionException;
+import retrofit.converter.Converter;
+
+public class ApiExceptionTests {
+
+ Response response;
+ Converter converter;
+ java.lang.reflect.Type type;
+
+ @Test
+ public void retrofit_network_exception_map_to_api_exception() {
+ APIException apiException = getNetworkExceptionFromRetrofit();
+ assertTrue(apiException.getKind().equals(APIException.Kind.NETWORK));
+ assertTrue(apiException.getUrl().equals("test_message"));
+ }
+
+ @Test
+ public void retrofit_conversion_exception_map_to_api_exception() {
+ APIException apiException = getConversionExceptionFromRetrofit();
+ assertTrue(apiException.getKind().equals(APIException.Kind.CONVERSION));
+ assertTrue(apiException.getUrl().equals("test_message"));
+ }
+
+ @Test
+ public void retrofit_unexpected_exception_map_to_api_exception() {
+ APIException apiException = getUnexpectedExceptionFromRetrofit();
+ assertTrue(apiException.getKind().equals(APIException.Kind.UNEXPECTED));
+ assertTrue(apiException.getUrl().equals("test_message"));
+ }
+
+ @Test
+ public void retrofit_http_error_exception_map_to_api_exception() {
+ APIException apiException = getHttpErrorExceptionFromRetrofit();
+ assertTrue(apiException.getKind().equals(APIException.Kind.HTTP));
+ assertTrue(apiException.getUrl().equals("test_message"));
+ }
+
+
+ private APIException getNetworkExceptionFromRetrofit() {
+ return APIException.fromRetrofitError(
+ RetrofitError.networkError("test_message", new IOException()));
+ }
+
+ private APIException getConversionExceptionFromRetrofit() {
+ return APIException.fromRetrofitError(
+ RetrofitError.conversionError("test_message", response, converter,
+ type, new ConversionException("test_message")));
+ }
+
+ private APIException getUnexpectedExceptionFromRetrofit() {
+ return APIException.fromRetrofitError(
+ RetrofitError.unexpectedError("test_message", new IOException()));
+ }
+
+ private APIException getHttpErrorExceptionFromRetrofit() {
+ List headerList = new ArrayList<>();
+ Response response = new Response("test_url", 404, "Not found", headerList, null);
+ return APIException.fromRetrofitError(
+ RetrofitError.httpError("test_message", response, converter, type));
+ }
+}
\ No newline at end of file
diff --git a/api/src/test/java/org/hisp/dhis/android/dashboard/api/user/UserTests.java b/api/src/test/java/org/hisp/dhis/android/dashboard/api/user/UserTests.java
new file mode 100644
index 00000000..a4ff8ad8
--- /dev/null
+++ b/api/src/test/java/org/hisp/dhis/android/dashboard/api/user/UserTests.java
@@ -0,0 +1,39 @@
+package org.hisp.dhis.android.dashboard.api.user;
+
+import static org.junit.Assert.assertTrue;
+
+import org.hisp.dhis.android.dashboard.api.commons.DateTestUtils;
+import org.hisp.dhis.android.dashboard.api.commons.FileReader;
+import org.hisp.dhis.android.dashboard.api.commons.JsonParser;
+import org.hisp.dhis.android.dashboard.api.models.User;
+import org.hisp.dhis.android.dashboard.api.models.UserAccount;
+import org.joda.time.DateTime;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import java.io.IOException;
+
+public class UserTests {
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ @Test
+ public void userAccount_conversion_to_user() throws IOException {
+ UserAccount userAccount = getUserAccountFromJson();
+ User user = UserAccount.toUser(userAccount);
+ assertTrue(user.getUId().equals("xE7jOejl9FI"));
+ assertTrue(user.getName().equals("John Traore"));
+ assertTrue(user.getDisplayName().equals("John Traore"));
+ assertTrue(DateTestUtils.compareParsedDateWithStringDate(DateTime.parse(user.getCreated()),
+ "2013-04-18T17:15:08.407"));
+ assertTrue(DateTestUtils.compareParsedDateWithStringDate(DateTime.parse(user.getLastUpdated()),
+ "2017-05-02T17:02:37.817"));
+ assertTrue(user.getAccess() == null);
+ }
+
+ private UserAccount getUserAccountFromJson() throws IOException {
+ return (UserAccount) JsonParser.getModelFromJson(UserAccount.class, new FileReader().getStringFromFile(
+ "userAccount.json"));
+ }
+}
\ No newline at end of file
diff --git a/api/src/test/resources/access_all_false_string.json b/api/src/test/resources/access_all_false_string.json
new file mode 100644
index 00000000..1cd2bc71
--- /dev/null
+++ b/api/src/test/resources/access_all_false_string.json
@@ -0,0 +1,8 @@
+{
+ "manage": false,
+ "externalize": false,
+ "write": false,
+ "read": false,
+ "update": false,
+ "delete": false
+}
\ No newline at end of file
diff --git a/api/src/test/resources/access_all_true_string.json b/api/src/test/resources/access_all_true_string.json
new file mode 100644
index 00000000..75d73647
--- /dev/null
+++ b/api/src/test/resources/access_all_true_string.json
@@ -0,0 +1,8 @@
+{
+ "manage": true,
+ "externalize": true,
+ "write": true,
+ "read": true,
+ "update": true,
+ "delete": true
+}
\ No newline at end of file
diff --git a/api/src/test/resources/userAccount.json b/api/src/test/resources/userAccount.json
new file mode 100644
index 00000000..0fbfc01e
--- /dev/null
+++ b/api/src/test/resources/userAccount.json
@@ -0,0 +1,21 @@
+{
+ "created": "2013-04-18T17:15:08.407",
+ "lastUpdated": "2017-05-02T17:02:37.817",
+ "name": "John Traore",
+ "id": "xE7jOejl9FI",
+ "birthday": "1971-04-08T00:00:00.000",
+ "education": "Master of super using",
+ "gender": "gender_male",
+ "languages": "English",
+ "displayName": "John Traore",
+ "jobTitle": "Super user",
+ "firstName": "John",
+ "surname": "Traore",
+ "employer": "DHIS",
+ "interests": "Football, swimming, singing, dancing",
+ "introduction": "I am the super user of DHIS 2",
+ "email": "someone@dhis2.org",
+ "organisationUnits": [{
+ "id": "ImspTQPwCqd"
+ }]
+}
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
index 59656a3e..982c2a6d 100755
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -1,4 +1,5 @@
apply plugin: 'com.android.application'
+apply plugin: 'jacoco-android'
android {
compileSdkVersion 25
@@ -8,8 +9,8 @@ android {
applicationId "org.hisp.dhis.android.dashboard"
minSdkVersion 15
targetSdkVersion 25
- versionCode 5
- versionName "0.6.5"
+ versionCode 7
+ versionName "0.6.7"
}
compileOptions {
@@ -23,7 +24,14 @@ android {
}
lintOptions {
- disable 'RtlSymmetry', 'RtlHardcoded', 'ContentDescription'
+ disable 'RtlSymmetry', 'RtlHardcoded', 'ContentDescription', 'RestrictedApi'
+ abortOnError false
+ }
+
+ buildTypes {
+ debug {
+ testCoverageEnabled true
+ }
}
}
@@ -43,4 +51,7 @@ dependencies {
// Other
compile 'com.jakewharton:butterknife:7.0.1'
compile 'com.github.chrisbanes.photoview:library:1.2.4'
+
+ // Java test dependencies
+ testCompile "junit:junit:4.10"
}
diff --git a/app/src/main/ic_event_report-web.png b/app/src/main/ic_event_report-web.png
new file mode 100644
index 00000000..243af003
Binary files /dev/null and b/app/src/main/ic_event_report-web.png differ
diff --git a/app/src/main/ic_pivot_table-web.png b/app/src/main/ic_pivot_table-web.png
new file mode 100644
index 00000000..42ecc34f
Binary files /dev/null and b/app/src/main/ic_pivot_table-web.png differ
diff --git a/app/src/main/java/org/hisp/dhis/android/dashboard/DhisService.java b/app/src/main/java/org/hisp/dhis/android/dashboard/DhisService.java
index 60e6bb55..5ebf5125 100755
--- a/app/src/main/java/org/hisp/dhis/android/dashboard/DhisService.java
+++ b/app/src/main/java/org/hisp/dhis/android/dashboard/DhisService.java
@@ -27,6 +27,7 @@
package org.hisp.dhis.android.dashboard;
import android.app.Service;
+import android.content.Context;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
@@ -54,6 +55,8 @@ public final class DhisService extends Service {
public static final int SYNC_DASHBOARDS = 5;
public static final int SYNC_DASHBOARD_CONTENT = 6;
public static final int SYNC_INTERPRETATIONS = 7;
+ public static final int PULL_INTERPRETATION_IMAGES = 8;
+ public static final int PULL_DASHBOARD_IMAGES = 9;
private final IBinder mBinder = new ServiceBinder();
private DhisController mDhisController;
@@ -165,6 +168,28 @@ public Object execute() throws APIException {
});
}
+ public void pullInterpretationImages(final DhisController.ImageNetworkPolicy imageNetworkPolicy, final Context context) {
+ JobExecutor.enqueueJob(new NetworkJob
+ Steps:
+ 1. Please open or create the .git/hooks/post-commit and .git/hooks/post-checkout files.
+ 2. If the file does not exist, add the following lines:
+ #!/bin/sh
+ gitPath=$(git rev-parse --show-toplevel)
+ sh ${gitPath}/generate_last_commit.sh
+ 2. If the file already exists, you only need add the following lines at the end:
+ gitPath=$(git rev-parse --show-toplevel)
+ sh ${gitPath}/generate_last_commit.sh
+ 3. Run "git checkout".
]]>
+
+
+
+
+ "Images size"
+ "Width:"
+ "Height:"
+ The value is not valid, please enter a value between %1$d and %2$d
+ "The App is synchronizing with the server, please try again after it's finished"
diff --git a/app/src/test/java/TextUtilsTest.java b/app/src/test/java/TextUtilsTest.java
new file mode 100644
index 00000000..8fff2c09
--- /dev/null
+++ b/app/src/test/java/TextUtilsTest.java
@@ -0,0 +1,17 @@
+import static org.junit.Assert.assertTrue;
+
+import org.hisp.dhis.android.dashboard.utils.TextUtils;
+import org.junit.Test;
+
+public class TextUtilsTest {
+
+ @Test
+ public void test_empty_string_is_empty() {
+ assertTrue(TextUtils.isEmpty(""));
+ }
+
+ @Test
+ public void test_null_string_is_empty() {
+ assertTrue(TextUtils.isEmpty(null));
+ }
+}
diff --git a/buddybuild_postbuild.sh b/buddybuild_postbuild.sh
new file mode 100644
index 00000000..507c8e47
--- /dev/null
+++ b/buddybuild_postbuild.sh
@@ -0,0 +1,9 @@
+#!/usr/bin/env bash
+
+# Upload CodeCov report
+echo "ConnectedCheck: "
+./gradlew connectedCheck
+
+echo "Send report to CodeCov"
+bash <(curl -s https://codecov.io/bash) -t ${CODECOV_TOKEN}
+
diff --git a/buddybuild_postclone.sh b/buddybuild_postclone.sh
new file mode 100644
index 00000000..83e8e1f0
--- /dev/null
+++ b/buddybuild_postclone.sh
@@ -0,0 +1,10 @@
+#!/usr/bin/env bash
+
+# Definitions
+gitPath=$(git rev-parse --show-toplevel)
+
+# Generate last commit
+sh ${gitPath}/generate_last_commit.sh
+
+echo "Generate Test Coverage Report:"
+./gradlew build jacocoTestReport assembleAndroidTest
diff --git a/build.gradle b/build.gradle
index b1ecb178..9bc13480 100755
--- a/build.gradle
+++ b/build.gradle
@@ -6,6 +6,7 @@ buildscript {
dependencies {
classpath 'com.android.tools.build:gradle:2.3.0'
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.4'
+ classpath 'com.dicedmelon.gradle:jacoco-android:0.1.1'
}
}
diff --git a/generate_last_commit.sh b/generate_last_commit.sh
new file mode 100644
index 00000000..08506669
--- /dev/null
+++ b/generate_last_commit.sh
@@ -0,0 +1,8 @@
+#!/bin/sh
+gitPath=$(git rev-parse --show-toplevel)
+filePath="${gitPath}/app/src/main/res/raw/lastcommit.txt"
+echo "Last commit path $filePath"
+commit=$(git log -1 HEAD --format=%H)
+echo "Saving last commit: ${commit}"
+echo ${commit} > $filePath
+echo "Done."