Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

WIP Copy and edit forms inside "Edit saved form" #886

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,10 @@
import android.widget.TextView;
import android.widget.Toast;

import org.javarosa.core.model.Constants;
import org.javarosa.core.model.FormIndex;
import org.javarosa.core.model.data.IAnswerData;
import org.javarosa.core.model.data.StringData;
import org.javarosa.core.model.instance.TreeElement;
import org.javarosa.form.api.FormEntryCaption;
import org.javarosa.form.api.FormEntryController;
Expand Down Expand Up @@ -2555,10 +2557,16 @@ public void run() {
boolean showFirst = reqIntent.getBooleanExtra("start", false);

if (!showFirst) {
if (reqIntent.getStringExtra(ApplicationConstants.BundleKeys.FORM_MODE).equals(ApplicationConstants.FormModes.DUPLICATED)) {
renameMediaFiles(formController);
getIntent().removeExtra(ApplicationConstants.BundleKeys.FORM_MODE);
}
// we've just loaded a saved form, so start in the hierarchy view
Intent i = new Intent(this, FormHierarchyActivity.class);
String formMode = reqIntent.getStringExtra(ApplicationConstants.BundleKeys.FORM_MODE);
if (formMode == null || ApplicationConstants.FormModes.EDIT_SAVED.equalsIgnoreCase(formMode)) {
if (formMode == null
|| ApplicationConstants.FormModes.EDIT_SAVED.equalsIgnoreCase(formMode)
|| ApplicationConstants.FormModes.DUPLICATED.equalsIgnoreCase(formMode)) {
i.putExtra(ApplicationConstants.BundleKeys.FORM_MODE, ApplicationConstants.FormModes.EDIT_SAVED);
startActivity(i);
return; // so we don't show the intro screen before jumping to the hierarchy
Expand Down Expand Up @@ -2869,6 +2877,42 @@ public void onSavePointError(String errorMessage) {
}
}

private void renameMediaFiles(FormController formController) {
List<FormEntryPrompt> formEntryPrompts = null;
try {
formEntryPrompts = formController.getAllQuestionPrompts();
} catch (JavaRosaException e) {
Timber.e(e);
}
if (formEntryPrompts != null) {
for (FormEntryPrompt formEntryPrompt : formEntryPrompts) {
try {
if (formEntryPrompt.getControlType() == Constants.CONTROL_IMAGE_CHOOSE
|| formEntryPrompt.getControlType() == Constants.CONTROL_AUDIO_CAPTURE
|| formEntryPrompt.getControlType() == Constants.CONTROL_VIDEO_CAPTURE
|| formEntryPrompt.getControlType() == Constants.CONTROL_OSM_CAPTURE) {

String originalAnswer = formEntryPrompt.getAnswerText();
if (originalAnswer != null) {
String newAnswer = System.currentTimeMillis()
+ originalAnswer.substring(originalAnswer.lastIndexOf("."));

formController
.saveAnswer(formEntryPrompt.getIndex(), new StringData(newAnswer));

new File(formController.getInstancePath().getParent()
+ "/" + originalAnswer)
.renameTo(new File(formController.getInstancePath().getParent()
+ "/" + newAnswer));
}
}
} catch (JavaRosaException e) {
Timber.e(e);
}
}
}
}

/**
* Used whenever we need to show empty view and be able to recognize it from the code
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,15 @@

import android.app.AlertDialog;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
import android.widget.TextView;
Expand All @@ -36,14 +38,22 @@
import org.odk.collect.android.provider.InstanceProviderAPI.InstanceColumns;
import org.odk.collect.android.tasks.InstanceSyncTask;
import org.odk.collect.android.utilities.ApplicationConstants;
import org.odk.collect.android.utilities.FileUtils;
import org.odk.collect.android.utilities.InstanceUtils;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;

/**
* Responsible for displaying all the valid instances in the instance directory.
*
* @author Yaw Anokwa (yanokwa@gmail.com)
* @author Carl Hartung (carlhartung@gmail.com)
*/
public class InstanceChooserList extends InstanceListActivity implements DiskSyncListener {
public class InstanceChooserList extends InstanceListActivity implements DiskSyncListener, AdapterView.OnItemLongClickListener {
private static final String INSTANCE_LIST_ACTIVITY_SORTING_ORDER = "instanceListActivitySortingOrder";
private static final String VIEW_SENT_FORM_SORTING_ORDER = "ViewSentFormSortingOrder";

Expand Down Expand Up @@ -86,6 +96,7 @@ public void onCreate(Bundle savedInstanceState) {
};
}
setupAdapter();
getListView().setOnItemLongClickListener(this);

instanceSyncTask = new InstanceSyncTask();
instanceSyncTask.setDiskSyncListener(this);
Expand All @@ -112,37 +123,10 @@ protected void onListItemClick(ListView listView, View view, int position, long
instanceUri.toString());

if (view.findViewById(R.id.visible_off).getVisibility() != View.VISIBLE) {
String action = getIntent().getAction();
if (Intent.ACTION_PICK.equals(action)) {
// caller is waiting on a picked form
setResult(RESULT_OK, new Intent().setData(instanceUri));
} else {
// the form can be edited if it is incomplete or if, when it was
// marked as complete, it was determined that it could be edited
// later.
String status = c.getString(c.getColumnIndex(InstanceColumns.STATUS));
String strCanEditWhenComplete =
c.getString(c.getColumnIndex(InstanceColumns.CAN_EDIT_WHEN_COMPLETE));

boolean canEdit = status.equals(InstanceProviderAPI.STATUS_INCOMPLETE)
|| Boolean.parseBoolean(strCanEditWhenComplete);
if (!canEdit) {
createErrorDialog(getString(R.string.cannot_edit_completed_form),
DO_NOT_EXIT);
return;
}
// caller wants to view/edit a form, so launch formentryactivity
Intent parentIntent = this.getIntent();
Intent intent = new Intent(Intent.ACTION_EDIT, instanceUri);
String formMode = parentIntent.getStringExtra(ApplicationConstants.BundleKeys.FORM_MODE);
if (formMode == null || ApplicationConstants.FormModes.EDIT_SAVED.equalsIgnoreCase(formMode)) {
intent.putExtra(ApplicationConstants.BundleKeys.FORM_MODE, ApplicationConstants.FormModes.EDIT_SAVED);
} else {
intent.putExtra(ApplicationConstants.BundleKeys.FORM_MODE, ApplicationConstants.FormModes.VIEW_SENT);
}
startActivity(intent);
}
finish();
String status = c.getString(c.getColumnIndex(InstanceColumns.STATUS));
String strCanEditWhenComplete =
c.getString(c.getColumnIndex(InstanceColumns.CAN_EDIT_WHEN_COMPLETE));
openForm(false, instanceUri, status, strCanEditWhenComplete);
}
}

Expand Down Expand Up @@ -248,4 +232,108 @@ public void onClick(DialogInterface dialog, int i) {
}


@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
if (view.findViewById(R.id.visible_off).getVisibility() != View.VISIBLE) {
showDuplicateFormDialog(position);
}
return true;
}

private void showDuplicateFormDialog(final int position) {
AlertDialog alertDialog = new AlertDialog.Builder(this).create();
alertDialog.setTitle(getString(R.string.duplicate_form_dialog_title));
alertDialog.setMessage(getString(R.string.duplicate_form_dialog_message));
DialogInterface.OnClickListener dialogYesNoListener =
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int i) {
switch (i) {
case DialogInterface.BUTTON_POSITIVE:
duplicateForm(position);
break;
}
}
};
alertDialog.setCancelable(false);
alertDialog.setButton(DialogInterface.BUTTON_POSITIVE, getString(R.string.duplicate), dialogYesNoListener);
alertDialog.setButton(DialogInterface.BUTTON_NEGATIVE, getString(R.string.cancel), dialogYesNoListener);
alertDialog.show();
}

private void duplicateForm(int position) {
Cursor cursor = (Cursor) getListAdapter().getItem(position);

ContentValues duplicatedValues = new ContentValues();
InstancesDao instancesDao = new InstancesDao();
ContentValues originalValues = instancesDao
.getValuesFromInstanceObject(instancesDao.getInstancesFromCursor(cursor).get(position));

duplicatedValues.put(InstanceColumns.DISPLAY_NAME, originalValues.getAsString(InstanceColumns.DISPLAY_NAME));
duplicatedValues.put(InstanceColumns.SUBMISSION_URI, originalValues.getAsString(InstanceColumns.SUBMISSION_URI));
duplicatedValues.put(InstanceColumns.CAN_EDIT_WHEN_COMPLETE, originalValues.getAsString(InstanceColumns.CAN_EDIT_WHEN_COMPLETE));
duplicatedValues.put(InstanceColumns.JR_FORM_ID, originalValues.getAsString(InstanceColumns.JR_FORM_ID));
duplicatedValues.put(InstanceColumns.JR_VERSION, originalValues.getAsString(InstanceColumns.JR_VERSION));
duplicatedValues.put(InstanceColumns.STATUS, InstanceProviderAPI.STATUS_INCOMPLETE);
duplicatedValues.put(InstanceColumns.LAST_STATUS_CHANGE_DATE, System.currentTimeMillis());

String displaySubtext = InstanceUtils.getDisplaySubtext(InstanceChooserList.this, InstanceProviderAPI.STATUS_INCOMPLETE, new Date());
duplicatedValues.put(InstanceColumns.DISPLAY_SUBTEXT, displaySubtext);

String originalInstanceDirPath = originalValues.getAsString(InstanceColumns.INSTANCE_FILE_PATH).substring(0, originalValues.getAsString(InstanceColumns.INSTANCE_FILE_PATH).lastIndexOf("/"));
String originalInstanceFileName = originalValues.getAsString(InstanceColumns.INSTANCE_FILE_PATH).substring(originalValues.getAsString(InstanceColumns.INSTANCE_FILE_PATH).lastIndexOf("/") + 1);
String instanceName = originalInstanceFileName.substring(0, originalInstanceFileName.indexOf("_"));
String time = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss", Locale.US).format(Calendar.getInstance().getTime());
String duplicatedInstanceDirPath = Collect.INSTANCES_PATH + File.separator + instanceName + "_" + time;

FileUtils.createFolder(duplicatedInstanceDirPath);
copyMediaFiles(originalInstanceDirPath, duplicatedInstanceDirPath);

String duplicatedInstanceFilePath = duplicatedInstanceDirPath + File.separator + instanceName + "_" + time + ".xml";
duplicatedValues.put(InstanceColumns.INSTANCE_FILE_PATH, duplicatedInstanceFilePath);

Uri duplicatedFormUri = instancesDao.saveInstance(duplicatedValues);
FileUtils.copyFile(new File(originalValues.getAsString(InstanceColumns.INSTANCE_FILE_PATH)), new File(duplicatedInstanceFilePath));
openForm(true, duplicatedFormUri, duplicatedValues.getAsString(InstanceColumns.STATUS), duplicatedValues.getAsString(InstanceColumns.CAN_EDIT_WHEN_COMPLETE));
}

private void copyMediaFiles(String originalDir, String duplicatedDir) {
File file = new File(originalDir);
for (final File mediaFile : file.listFiles()) {
if (!mediaFile.isDirectory() && !mediaFile.getName().endsWith(".xml")) {
FileUtils.copyFile(mediaFile, new File(duplicatedDir + File.separator + mediaFile.getName()));
}
}
}

private void openForm(boolean duplicated, Uri instanceUri, String status, String strCanEditWhenComplete) {
String action = getIntent().getAction();
if (Intent.ACTION_PICK.equals(action)) {
// caller is waiting on a picked form
setResult(RESULT_OK, new Intent().setData(instanceUri));
} else {
boolean canEdit = status.equals(InstanceProviderAPI.STATUS_INCOMPLETE)
|| Boolean.parseBoolean(strCanEditWhenComplete);
if (!canEdit) {
createErrorDialog(getString(R.string.cannot_edit_completed_form),
DO_NOT_EXIT);
return;
}
// caller wants to view/edit a form, so launch formentryactivity
Intent parentIntent = this.getIntent();
Intent intent = new Intent(Intent.ACTION_EDIT, instanceUri);
String formMode = parentIntent.getStringExtra(ApplicationConstants.BundleKeys.FORM_MODE);
if (duplicated) {
intent.putExtra(ApplicationConstants.BundleKeys.FORM_MODE, ApplicationConstants.FormModes.DUPLICATED);
} else {
if (formMode == null || ApplicationConstants.FormModes.EDIT_SAVED.equalsIgnoreCase(formMode)) {
intent.putExtra(ApplicationConstants.BundleKeys.FORM_MODE, ApplicationConstants.FormModes.EDIT_SAVED);
} else {
intent.putExtra(ApplicationConstants.BundleKeys.FORM_MODE, ApplicationConstants.FormModes.VIEW_SENT);
}
}
startActivity(intent);
}
finish();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -277,9 +277,9 @@ public void deleteInstancesFromIDs(List<String> ids) {

public List<Instance> getInstancesFromCursor(Cursor cursor) {
List<Instance> instances = new ArrayList<>();
if (cursor != null) {
if (cursor != null && cursor.moveToFirst()) {
try {
while (cursor.moveToNext()) {
do {
int displayNameColumnIndex = cursor.getColumnIndex(InstanceProviderAPI.InstanceColumns.DISPLAY_NAME);
int submissionUriColumnIndex = cursor.getColumnIndex(InstanceProviderAPI.InstanceColumns.SUBMISSION_URI);
int canEditWhenCompleteIndex = cursor.getColumnIndex(InstanceProviderAPI.InstanceColumns.CAN_EDIT_WHEN_COMPLETE);
Expand All @@ -305,7 +305,7 @@ public List<Instance> getInstancesFromCursor(Cursor cursor) {
.build();

instances.add(instance);
}
} while (cursor.moveToNext());
} finally {
cursor.close();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
Expand Down Expand Up @@ -808,6 +809,22 @@ public void setLanguage(String language) {
formEntryController.setLanguage(language);
}

/**
* Returns a list of question promps from the whole form.
*/
public List<FormEntryPrompt> getAllQuestionPrompts() throws JavaRosaException {
List<FormEntryPrompt> formEntryPrompts = new ArrayList<>();
int event = stepToNextScreenEvent();
while (event != FormEntryController.EVENT_END_OF_FORM) {
if (event == FormEntryController.EVENT_QUESTION
|| event == FormEntryController.EVENT_GROUP
|| event == FormEntryController.EVENT_REPEAT) {
Collections.addAll(formEntryPrompts, getQuestionPrompts());
}
event = stepToNextScreenEvent();
}
return formEntryPrompts;
}

/**
* Returns an array of question promps.
Expand Down
Loading