Commit aafebc22 authored by rahadi's avatar rahadi

WIP: added updating and its error interface

parent 537fbff6
......@@ -87,6 +87,8 @@ public class CapiFormFragment extends Fragment implements FormListDownloaderList
private static final String FORM_VERSION_KEY = "formversion";
private static final String HAS_BEEN_DOWNLOADED = "hasbeendownloaded";
private static final String FORM_TYPE_KEY = "formtype";
private static final boolean EXIT = true;
private static final boolean DO_NOT_EXIT = false;
......@@ -226,11 +228,14 @@ public class CapiFormFragment extends Fragment implements FormListDownloaderList
String formName = c.getString(c.getColumnIndex(FormsProviderAPI.FormsColumns.DISPLAY_NAME));
String formVersion = c.getString(c.getColumnIndex(FormsProviderAPI.FormsColumns.JR_FORM_ID));
String formId = c.getString(c.getColumnIndex(FormsProviderAPI.FormsColumns.JR_FORM_ID));
String formType = c.getString(c.getColumnIndex(FormsProviderAPI.FormsColumns.FORM_TYPE));
item.put(FORMNAME, formName);
item.put(FORM_ID_KEY, formId);
item.put(FORM_VERSION_KEY, formVersion);
item.put(HAS_BEEN_DOWNLOADED, "true");
item.put(FORM_TYPE_KEY, formType);
downloadedFormsBefore.add(item);
} while (c.moveToNext());
......@@ -492,6 +497,11 @@ public class CapiFormFragment extends Fragment implements FormListDownloaderList
item.put(FORM_ID_KEY, details.formID);
item.put(FORM_VERSION_KEY, details.formVersion);
FormsDao formsDao = new FormsDao();
Cursor c = formsDao.getFormsCursor(FormsProviderAPI.FormsColumns.JR_FORM_ID + "=?",
new String[]{details.formID});
item.put(FORM_TYPE_KEY, c.getString(c.getColumnIndex(FormsProviderAPI.FormsColumns.FORM_TYPE)));
if (!mFormListContain(details.formName)) {
// Insert the new form in alphabetical order.
if (mFormList.size() == 0) {
......
......@@ -321,7 +321,7 @@ public class FormHierarchyFragment extends Fragment implements AdapterView.OnIte
}
// Add this group name to the drop down list for this repeating group.
HierarchyElement h = formList.get(formList.size() - 1);
h.addChild(new HierarchyElement("rensponse "
h.addChild(new HierarchyElement("response "
+ (fc.getMultiplicity() + 1), null, null, Color.WHITE, CHILD, fc
.getIndex(),1));
break;
......
package id.ac.stis.capi.lessthink.activities;
import android.content.ContentUris;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
......@@ -8,12 +11,13 @@ import android.view.View;
import android.widget.Toast;
import java.io.File;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import id.ac.stis.capi.R;
import id.ac.stis.capi.collectiva.preferences.Constants;
import id.ac.stis.capi.lessthink.fragments.FormEntryDialogFragment;
import id.ac.stis.capi.lessthink.listeners.OnAddButtonClickListener;
import id.ac.stis.capi.lessthink.models.FormLabels;
import id.ac.stis.capi.lessthink.models.InstanceValues;
import id.ac.stis.capi.lessthink.utils.XmlUtils;
......@@ -24,8 +28,9 @@ import id.ac.stis.capi.odk.dao.FormsDao;
import id.ac.stis.capi.odk.dao.InstancesDao;
import id.ac.stis.capi.odk.dto.Form;
import id.ac.stis.capi.odk.dto.Instance;
import id.ac.stis.capi.odk.provider.FormsProviderAPI;
import id.ac.stis.capi.odk.provider.InstanceProviderAPI;
import timber.log.Timber;
import id.ac.stis.capi.odk.utilities.ApplicationConstants;
public class ListingInstanceActivity extends AppCompatActivity {
......@@ -36,6 +41,7 @@ public class ListingInstanceActivity extends AppCompatActivity {
private TableRowView tableRowView;
private TableFooterView tableFooterView;
private String formId, formName;
private FormEntryDialogFragment entryDialogFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
......@@ -82,8 +88,53 @@ public class ListingInstanceActivity extends AppCompatActivity {
tableRowView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(ListingInstanceActivity.this, "Click : " + view.getTag(), Toast.LENGTH_LONG).show();
// Toast.makeText(ListingInstanceActivity.this, "Click : " + view.getTag(), Toast.LENGTH_LONG).show();
String instanceUuid = view.getTag().toString();
entryDialogFragment = FormEntryDialogFragment.newInstance(instanceUuid,
FormEntryDialogFragment.MODE_EDIT, false);
entryDialogFragment.show(getSupportFragmentManager(), instanceUuid);
//
// Intent i =new Intent(ListingInstanceActivity.this, ListingFormEntryActivity.class);
// i.putExtra("instanceUuid", view.getTag().toString());
// startActivity(i);
}
});
tableFooterView.setOnAddButtonClickListener(new OnAddButtonClickListener() {
@Override
public void onAddButtonClick(View v) {
fillBlankForm();
}
});
}
//todo: update yow
private void fillBlankForm() {
Cursor formslist = new FormsDao().getFormsCursor();
//getting id
long itemIdPosition = -1;
if (formslist.moveToFirst()) {
do {
if (formslist.getString(formslist.getColumnIndex(FormsProviderAPI.FormsColumns.JR_FORM_ID)).equals(formId)) {
itemIdPosition = formslist.getLong(formslist.getColumnIndex(FormsProviderAPI.FormsColumns._ID));
}
} while (formslist.moveToNext());
}
if (itemIdPosition > -1) {
// get uri to form
Uri formUri = ContentUris.withAppendedId(FormsProviderAPI.FormsColumns.CONTENT_URI, itemIdPosition);
// caller wants to view/edit a form, so launch formentryactivity
Intent intent = new Intent(Intent.ACTION_EDIT, formUri);
intent.putExtra("fillblankform", true);
intent.putExtra(Constants.CURRENT_FORMNAME, getIntent().getStringExtra(FORMNAME));
intent.putExtra(ApplicationConstants.BundleKeys.FORM_MODE, ApplicationConstants.FormModes.EDIT_SAVED);
startActivity(intent);
} else {
//xxxseharusnya tidak terjadi, tidak mungkin itemIdposition < 1
Toast.makeText(this, "Form not exist", Toast.LENGTH_SHORT).show();
}
}
}
package id.ac.stis.capi.lessthink.adapters;
import android.content.pm.PackageManager;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import java.util.ArrayList;
import id.ac.stis.capi.lessthink.models.BaseHierarchy;
import id.ac.stis.capi.odk.widgets.QuestionWidget;
/**
* Author : Rahadi Jalu
* Email : 14.8325@stis.ac.id
* Company: Politeknik Statistika STIS
*/
public class HierarchyAdapter extends BaseAdapter {
private ArrayList<BaseHierarchy> hierarchies;
public HierarchyAdapter(ArrayList<BaseHierarchy> hierarchies) {
this.hierarchies = hierarchies;
}
@Override
public int getCount() {
return hierarchies.size();
}
@Override
public Object getItem(int position) {
return hierarchies.get(position);
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public int getItemViewType(int position) {
return hierarchies.get(position).getType();
}
@Override
public int getViewTypeCount() {
return 2;
}
@Override
public boolean isEnabled(int position) {
return false;
}
@Override
public View getView(final int position, View view, final ViewGroup parent) {
View v = hierarchies.get(position).getView();
if (v instanceof QuestionWidget) {
v.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
for (BaseHierarchy hierarchy : hierarchies) {
View checkFocus = hierarchy.getView();
if (checkFocus != v) {
checkFocus.clearFocus();
} else {
v.requestFocus();
}
}
} else {
v.clearFocus();
}
}
});
}
return v;
}
}
\ No newline at end of file
package id.ac.stis.capi.lessthink.interfaces;
/**
* Author : Rahadi Jalu
* Email : 14.8325@stis.ac.id
* Company: Politeknik Statistika STIS
*/
public interface UpdatingErrorInterface {
/**
* Shows error message to the view.
* Specifically made for updating mode.
*
* @param message error message to be shown. maybe constraintMsg or requiredMsg.
* */
void setError(String message);
/**
* Clears error message of the view.
* Specifically made for updating mode.
* */
void clearError();
}
package id.ac.stis.capi.lessthink.listeners;
import android.view.View;
/**
* Author : Rahadi Jalu
* Email : 14.8325@stis.ac.id
* Company: Politeknik Statistika STIS
*/
public interface OnAddButtonClickListener {
void onAddButtonClick(View v);
}
package id.ac.stis.capi.lessthink.listeners;
import android.view.View;
import org.javarosa.core.model.FormIndex;
import id.ac.stis.capi.odk.widgets.QuestionWidget;
/**
* Author : Rahadi Jalu
* Email : 14.8325@stis.ac.id
* Company: Politeknik Statistika STIS
*/
public interface OnChangeListener {
void onChange(QuestionWidget questionWidget, FormIndex formIndex);
}
package id.ac.stis.capi.lessthink.listeners;
/**
* Author : Rahadi Jalu
* Email : 14.8325@stis.ac.id
* Company: Politeknik Statistika STIS
*/
public interface OnEditRutaSavedListener {
void onEditRutaSaved();
}
package id.ac.stis.capi.lessthink.models;
import android.view.View;
/**
* Author : Rahadi Jalu
* Email : 14.8325@stis.ac.id
* Company: Politeknik Statistika STIS
*/
public abstract class BaseHierarchy {
public static final int HIERARCHY_TYPE_PROMPT = 0;
public static final int HIERARCHY_TYPE_CAPTION = 1;
private int type;
private int level;
public BaseHierarchy(int type, int level) {
this.type = type;
this.level = level;
}
public abstract View getView();
public int getType() {
return type;
}
public int getLevel() {
return level;
}
}
package id.ac.stis.capi.lessthink.models;
import android.content.Context;
import android.view.View;
import android.widget.TextView;
import org.javarosa.form.api.FormEntryCaption;
/**
* Author : Rahadi Jalu
* Email : 14.8325@stis.ac.id
* Company: Politeknik Statistika STIS
*/
public class CaptionHierarchy extends BaseHierarchy {
private TextView textView;
private FormEntryCaption caption;
public CaptionHierarchy(Context context, FormEntryCaption caption, int level) {
super(HIERARCHY_TYPE_CAPTION, level);
this.caption = caption;
this.textView = new TextView(context);
textView.setText(caption.getLongText());
}
public FormEntryCaption getCaption() {
return caption;
}
@Override
public View getView() {
return textView;
}
}
package id.ac.stis.capi.lessthink.models;
import android.content.Context;
import android.view.View;
import org.javarosa.form.api.FormEntryPrompt;
import id.ac.stis.capi.odk.widgets.QuestionWidget;
import id.ac.stis.capi.odk.widgets.WidgetFactory;
/**
* Author : Rahadi Jalu
* Email : 14.8325@stis.ac.id
* Company: Politeknik Statistika STIS
*/
public class PromptHierarchy extends BaseHierarchy {
private QuestionWidget widget;
private FormEntryPrompt prompt;
public PromptHierarchy(Context context, FormEntryPrompt prompt, int level) {
super(HIERARCHY_TYPE_PROMPT, level);
this.prompt = prompt;
this.widget = WidgetFactory.createWidgetFromPrompt(prompt, context, false);
}
public FormEntryPrompt getPrompt() {
return prompt;
}
@Override
public View getView() {
return widget;
}
}
......@@ -37,7 +37,6 @@ import id.ac.stis.capi.lessthink.models.FormLabels;
import id.ac.stis.capi.lessthink.models.InstanceValues;
import id.ac.stis.capi.odk.application.Collect;
import id.ac.stis.capi.odk.dao.FormsDao;
import id.ac.stis.capi.odk.logic.FormDetails;
import id.ac.stis.capi.odk.provider.FormsProviderAPI;
import timber.log.Timber;
......@@ -243,6 +242,73 @@ public class XmlUtils {
return null;
}
public static File generateEmptyInstanceFile(File file,String formId, String formName) {
if (file.exists()) {
try {
FileInputStream fis = new FileInputStream(file);
KXmlParser parser = new KXmlParser();
parser.setInput(new InputStreamReader(fis));
Document doc = new Document();
doc.parse(parser);
Element root = doc.getRootElement();
HashMap<String, String> namespaceSet = new HashMap<>();
for (int i = 0; i < root.getAttributeCount(); i++) {
if (root.getAttributeName(i).contains("xmlns")) {
namespaceSet.put(root.getAttributeName(i), root.getAttributeValue(i));
}
}
Element head = root.getElement(root.getNamespace(), "h:head");
Element model = getChildElement(head, "model");
Element instance = getChildElement(model, "instance");
int i;
int idx = instance.getChildCount();
for (i = 0; i < idx; i++) {
if (instance.isText(i)) {
continue;
}
if (instance.getType(i) == Element.ELEMENT) {
break;
}
}
if (i < idx) {
Element e = instance.getElement(i);
File out = new File(Collect.EMPTY_INSTANCES_PATH + File.separator + formName + ".xml");
int j = 2;
while (out.exists()) {
out = new File(Collect.EMPTY_INSTANCES_PATH + File.separator + formName + "_" + j + ".xml");
j++;
}
FileOutputStream fos = new FileOutputStream(out);
KXmlSerializer serializer = new KXmlSerializer();
serializer.setOutput(new OutputStreamWriter(fos));
Set<String> nsKeys = namespaceSet.keySet();
for (String key : nsKeys) {
e.setAttribute(root.getNamespace(), key, namespaceSet.get(key));
}
e.write(serializer);
serializer.flush();
serializer.endDocument();
fos.close();
ContentValues v = new ContentValues();
v.put(FormsProviderAPI.FormsColumns.EMPTY_INSTANCE_FILE_PATH, out.getAbsolutePath());
new FormsDao().updateForm(v, FormsProviderAPI.FormsColumns.JR_FORM_ID + "=?", new String[]{formId});
return out;
}
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
public static File generateEmptyInstanceFile(String formId, String formName) {
Cursor c = Collect.getInstance().getContentResolver().query(FormsProviderAPI.FormsColumns.CONTENT_URI,
......
......@@ -15,6 +15,7 @@ import android.widget.TextView;
import android.widget.Toast;
import id.ac.stis.capi.R;
import id.ac.stis.capi.lessthink.listeners.OnAddButtonClickListener;
import id.ac.stis.capi.lessthink.listeners.OnFooterNavigationListener;
/**
......@@ -29,6 +30,7 @@ public class TableFooterView extends RelativeLayout implements View.OnClickListe
private LinearLayout pageIndicator, navigationWrapper;
private int textSize, componentColor, footerColor, currentPage, pageCount;
private OnFooterNavigationListener onFooterNavigationListener;
private OnAddButtonClickListener onAddButtonClickListener;
public TableFooterView(Context context, AttributeSet attrs) {
super(context, attrs);
......@@ -174,6 +176,10 @@ public class TableFooterView extends RelativeLayout implements View.OnClickListe
this.onFooterNavigationListener = onFooterNavigationListener;
}
public void setOnAddButtonClickListener(OnAddButtonClickListener onAddButtonClickListener) {
this.onAddButtonClickListener = onAddButtonClickListener;
}
public int getTextSize() {
return textSize;
}
......@@ -208,7 +214,11 @@ public class TableFooterView extends RelativeLayout implements View.OnClickListe
public void onClick(View view) {
switch (view.getId()) {
case R.id.footer_view_add_button:
Toast.makeText(getContext(), "ADD", Toast.LENGTH_LONG).show();
if (onAddButtonClickListener != null) {
onAddButtonClickListener.onAddButtonClick(view);
} else {
Toast.makeText(getContext(), "Add Button is Not Implemented Yet", Toast.LENGTH_LONG).show();
}
break;
case R.id.footer_view_prev_button:
// Toast.makeText(getContext(), "PREV", Toast.LENGTH_LONG).show();
......
......@@ -197,7 +197,12 @@ public class TableRowView extends HorizontalScrollView implements OnHandlerMoved
int availableHeight = container.getHeight();
int currIdx = this.rowCount * page - this.rowCount;
int maxIdx = this.rowCount != 0 && this.rowCount * page < rows.size() ? this.rowCount * page : rows.size();
int maxIdx;
if(this.rowCount != 0 && this.rowCount * page < rows.size()) {
maxIdx = this.rowCount * page;
} else {
maxIdx = rows.size();
}
Timber.d("Max Idx : %s", maxIdx);
......@@ -277,10 +282,12 @@ public class TableRowView extends HorizontalScrollView implements OnHandlerMoved
// Timber.d("Row Height : %s, Available Height : %s", rowHeight, availableHeight);
}
this.rowCount = container.getHeight() / rowHeight;
this.currentPage = page;
if(rows.size() > 0) {
this.rowCount = container.getHeight() / rowHeight;
this.currentPage = page;
calculatePageCount();
calculatePageCount();
}
animate().alpha(1.0f).setDuration(animationDuration);
}
......
......@@ -94,8 +94,8 @@ import id.ac.stis.capi.odk.listeners.AdvanceToNextListener;
import id.ac.stis.capi.odk.listeners.FormLoaderListener;
import id.ac.stis.capi.odk.listeners.FormSavedListener;
import id.ac.stis.capi.odk.listeners.SavePointListener;
import id.ac.stis.capi.odk.logic.FailedConstraint;
import id.ac.stis.capi.odk.logic.FormController;
import id.ac.stis.capi.odk.logic.FormController.FailedConstraint;
import id.ac.stis.capi.odk.preferences.AdminKeys;
import id.ac.stis.capi.odk.preferences.AdminPreferencesActivity;
import id.ac.stis.capi.odk.preferences.AdminSharedPreferences;
......@@ -892,11 +892,11 @@ public class FormEntryActivity extends SlidingActivity implements AnimationListe
|| evaluateConstraints == EVALUATE_CONSTRAINTS_BUT_CAN_SKIP) {
isNeedToEvaluated = true;
}
FailedConstraint constraint = formController.saveAllScreenAnswers(answers,
ArrayList<FailedConstraint> constraint = formController.saveAllScreenAnswers(answers,
isNeedToEvaluated);
if (constraint != null && (evaluateConstraints == EVALUATE_CONSTRAINTS
|| evaluateConstraints == EVALUATE_CONSTRAINTS_BUT_CAN_SKIP)) {
createConstraintToast(constraint.index, constraint.status);
createConstraintToast(constraint);
checkErrorHandler();
return false;
}
......@@ -1994,51 +1994,58 @@ public class FormEntryActivity extends SlidingActivity implements AnimationListe
/**
* Creates and displays a dialog displaying the violated constraint.
*/
private void createConstraintToast(FormIndex index, int saveStatus) {
private void createConstraintToast(ArrayList<FailedConstraint> failedConstraints) {
FormController formController = Collect.getInstance()
.getFormController();
String constraintText;
switch (saveStatus) {
case FormEntryController.ANSWER_CONSTRAINT_VIOLATED:
Collect.getInstance()
.getActivityLogger()
.logInstanceAction(this,
"createConstraintToast.ANSWER_CONSTRAINT_VIOLATED",
"show", index);
constraintText = formController
.getQuestionPromptConstraintText(index);
if (constraintText == null) {
constraintText = formController.getQuestionPrompt(index)
.getSpecialFormQuestionText("constraintMsg");
if (constraintText == null) {
constraintText = getString(R.string.invalid_answer_error);
}
}
break;
case FormEntryController.ANSWER_REQUIRED_BUT_EMPTY:
Collect.getInstance()
.getActivityLogger()
.logInstanceAction(this,
"createConstraintToast.ANSWER_REQUIRED_BUT_EMPTY",
"show", index);
constraintText = formController
.getQuestionPromptRequiredText(index);
if (constraintText == null) {
constraintText = formController.getQuestionPrompt(index)
.getSpecialFormQuestionText("requiredMsg");
if (constraintText == null) {
constraintText = getString(R.string.required_answer_error);
}
String constraintText = "";
if (failedConstraints.size() > 1) {
constraintText = "Can't go to the next question, You have " + failedConstraints.size() + " errors input";
} else {
for (int i = 0; i < failedConstraints.size(); i++) {
FailedConstraint failedConstraint = failedConstraints.get(i);
switch (failedConstraint.status) {
case FormEntryController.ANSWER_CONSTRAINT_VIOLATED:
Collect.getInstance()
.getActivityLogger()
.logInstanceAction(this,
"createConstraintToast.ANSWER_CONSTRAINT_VIOLATED",
"show", failedConstraint.index);
String constraintTextLocal = formController
.getQuestionPromptConstraintText(failedConstraint.index);
if (constraintTextLocal == null || constraintTextLocal.trim().length() == 0) {
constraintTextLocal = formController.getQuestionPrompt(failedConstraint.index)
.getSpecialFormQuestionText("constraintMsg");
if (constraintTextLocal == null || constraintTextLocal.trim().length() == 0) {
constraintTextLocal = getString(R.string.invalid_answer_error);
}
}
constraintText = constraintTextLocal;
// constraintText = constraintText+constraintTextLocal;
break;
case FormEntryController.ANSWER_REQUIRED_BUT_EMPTY:
Collect.getInstance()
.getActivityLogger()
.logInstanceAction(this,
"createConstraintToast.ANSWER_REQUIRED_BUT_EMPTY",
"show", failedConstraint.index);
String constraintTextLocalB = formController
.getQuestionPromptRequiredText(failedConstraint.index);
if (constraintTextLocalB == null || constraintTextLocalB.trim().length() == 0) {
constraintTextLocalB = formController.getQuestionPrompt(failedConstraint.index)