diff --git a/docs-android/app/app.iml b/docs-android/app/app.iml
index 46bcd543..59404e26 100644
--- a/docs-android/app/app.iml
+++ b/docs-android/app/app.iml
@@ -98,15 +98,15 @@
+
-
-
+
+
-
diff --git a/docs-android/app/build.gradle b/docs-android/app/build.gradle
index 31b88246..4e0567b0 100644
--- a/docs-android/app/build.gradle
+++ b/docs-android/app/build.gradle
@@ -3,7 +3,7 @@ buildscript {
mavenCentral()
}
dependencies {
- classpath 'com.android.tools.build:gradle:1.0.0-rc1'
+ classpath 'com.android.tools.build:gradle:1.0.0'
}
}
apply plugin: 'com.android.application'
@@ -14,7 +14,7 @@ repositories {
android {
compileSdkVersion 21
- buildToolsVersion "21.1.1"
+ buildToolsVersion "21.1.2"
defaultConfig {
minSdkVersion 14
@@ -31,7 +31,7 @@ android {
dependencies {
compile fileTree(dir: 'libs', include: '*.jar')
- compile 'com.android.support:appcompat-v7:21.0.2'
+ compile 'com.android.support:appcompat-v7:21.0.3'
compile 'com.android.support:recyclerview-v7:21.0.0'
compile 'com.loopj.android:android-async-http:1.4.6'
compile 'it.sephiroth.android.library.imagezoom:imagezoom:1.0.5'
diff --git a/docs-android/app/src/main/java/com/sismics/docs/MainApplication.java b/docs-android/app/src/main/java/com/sismics/docs/MainApplication.java
index 3506654f..f959913c 100644
--- a/docs-android/app/src/main/java/com/sismics/docs/MainApplication.java
+++ b/docs-android/app/src/main/java/com/sismics/docs/MainApplication.java
@@ -21,7 +21,7 @@ public class MainApplication extends Application {
ApplicationContext.getInstance().setUserInfo(getApplicationContext(), json);
// TODO Fullscreen preview
- // TODO Documents adding/editing
+ // TODO Document deleting
// TODO Files adding/deleting
super.onCreate();
diff --git a/docs-android/app/src/main/java/com/sismics/docs/activity/DocumentEditActivity.java b/docs-android/app/src/main/java/com/sismics/docs/activity/DocumentEditActivity.java
index 889d7010..e59ec4a3 100644
--- a/docs-android/app/src/main/java/com/sismics/docs/activity/DocumentEditActivity.java
+++ b/docs-android/app/src/main/java/com/sismics/docs/activity/DocumentEditActivity.java
@@ -1,5 +1,7 @@
package com.sismics.docs.activity;
+import android.app.ProgressDialog;
+import android.content.DialogInterface;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
@@ -8,22 +10,29 @@ import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.EditText;
import android.widget.Spinner;
+import android.widget.Toast;
import com.sismics.docs.R;
import com.sismics.docs.adapter.LanguageAdapter;
import com.sismics.docs.adapter.TagAutoCompleteAdapter;
+import com.sismics.docs.event.DocumentAddEvent;
import com.sismics.docs.event.DocumentEditEvent;
+import com.sismics.docs.listener.JsonHttpResponseHandler;
+import com.sismics.docs.resource.DocumentResource;
import com.sismics.docs.ui.view.DatePickerView;
import com.sismics.docs.ui.view.TagsCompleteTextView;
import com.sismics.docs.util.PreferenceUtil;
+import org.apache.http.Header;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.Date;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
import de.greenrobot.event.EventBus;
@@ -96,6 +105,7 @@ public class DocumentEditActivity extends ActionBarActivity {
tagsEditText.allowDuplicates(false);
tagsEditText.setAdapter(new TagAutoCompleteAdapter(this, 0, tagList));
+ // TODO Form validation
// Fill the activity
if (document == null) {
datePickerView.setDate(new Date());
@@ -123,35 +133,83 @@ public class DocumentEditActivity extends ActionBarActivity {
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.save:
- JSONObject outputDoc = new JSONObject();
- try {
- if (document != null) {
- outputDoc.putOpt("id", document.optString("id"));
- outputDoc.putOpt("shared", document.optBoolean("shared"));
- }
- outputDoc.putOpt("title", titleEditText.getText().toString());
- outputDoc.putOpt("description", descriptionEditText.getText().toString());
- if (languageSpinner.getSelectedItem() != null) {
- LanguageAdapter.Language language = (LanguageAdapter.Language) languageSpinner.getSelectedItem();
- outputDoc.putOpt("language", language.getId());
- }
- if (datePickerView.getDate() != null) {
- outputDoc.putOpt("create_date", datePickerView.getDate().getTime());
- }
- JSONArray tags = new JSONArray();
- for (Object object : tagsEditText.getObjects()) {
- if (object instanceof JSONObject) {
- tags.put(object);
- }
- }
- outputDoc.putOpt("tags", tags);
- } catch (JSONException e) {
- Log.e(DocumentEditActivity.class.getSimpleName(), "Error building JSON for document", e);
+ // Metadata
+ final String title = titleEditText.getText().toString();
+ final String description = descriptionEditText.getText().toString();
+ LanguageAdapter.Language language = (LanguageAdapter.Language) languageSpinner.getSelectedItem();
+ final String langId = language.getId();
+ final long createDate = datePickerView.getDate().getTime();
+ Set tagIdList = new HashSet<>();
+ for (Object object : tagsEditText.getObjects()) {
+ JSONObject tag = (JSONObject) object;
+ tagIdList.add(tag.optString("id"));
}
- EventBus.getDefault().post(new DocumentEditEvent(outputDoc));
- setResult(RESULT_OK);
- finish();
+ // Cancellable progress dialog
+ final ProgressDialog progressDialog = ProgressDialog.show(this,
+ getString(R.string.document_editing_title),
+ getString(R.string.document_editing_message), true, true,
+ new DialogInterface.OnCancelListener() {
+ @Override
+ public void onCancel(DialogInterface dialog) {
+ DocumentResource.cancel(DocumentEditActivity.this);
+ }
+ });
+
+ // Server callback
+ JsonHttpResponseHandler callback = new JsonHttpResponseHandler() {
+ @Override
+ public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
+ // Build a fake document JSON to update the UI
+ final JSONObject outputDoc = new JSONObject();
+ try {
+ if (document == null) {
+ outputDoc.putOpt("id", response.optString("id"));
+ outputDoc.putOpt("shared", false);
+ } else {
+ outputDoc.putOpt("id", document.optString("id"));
+ outputDoc.putOpt("shared", document.optBoolean("shared"));
+ }
+ outputDoc.putOpt("title", title);
+ outputDoc.putOpt("description", description);
+ outputDoc.putOpt("language", langId);
+ outputDoc.putOpt("create_date", createDate);
+ JSONArray tags = new JSONArray();
+ for (Object object : tagsEditText.getObjects()) {
+ tags.put(object);
+ }
+ outputDoc.putOpt("tags", tags);
+ } catch (JSONException e) {
+ Log.e(DocumentEditActivity.class.getSimpleName(), "Error building JSON for document", e);
+ }
+
+ // Fire the right event
+ if (document == null) {
+ EventBus.getDefault().post(new DocumentAddEvent(outputDoc));
+ } else {
+ EventBus.getDefault().post(new DocumentEditEvent(outputDoc));
+ }
+ setResult(RESULT_OK);
+ finish();
+ }
+
+ @Override
+ public void onAllFailure(int statusCode, Header[] headers, byte[] responseBytes, Throwable throwable) {
+ Toast.makeText(DocumentEditActivity.this, R.string.error_editing_document, Toast.LENGTH_LONG).show();
+ }
+
+ @Override
+ public void onFinish() {
+ progressDialog.dismiss();
+ }
+ };
+
+ // Actual server call
+ if (document == null) {
+ DocumentResource.add(this, title, description, tagIdList, langId, createDate, callback);
+ } else {
+ DocumentResource.edit(this, document.optString("id"), title, description, tagIdList, langId, createDate, callback);
+ }
return true;
case android.R.id.home:
diff --git a/docs-android/app/src/main/java/com/sismics/docs/activity/DocumentViewActivity.java b/docs-android/app/src/main/java/com/sismics/docs/activity/DocumentViewActivity.java
index 570b8d5b..b49e5042 100644
--- a/docs-android/app/src/main/java/com/sismics/docs/activity/DocumentViewActivity.java
+++ b/docs-android/app/src/main/java/com/sismics/docs/activity/DocumentViewActivity.java
@@ -118,6 +118,8 @@ public class DocumentViewActivity extends ActionBarActivity {
* @param document Document in JSON format
*/
private void refreshDocument(JSONObject document) {
+ this.document = document;
+
String id = document.optString("id");
String title = document.optString("title");
String date = DateFormat.getDateFormat(this).format(new Date(document.optLong("create_date")));
diff --git a/docs-android/app/src/main/java/com/sismics/docs/event/DocumentAddEvent.java b/docs-android/app/src/main/java/com/sismics/docs/event/DocumentAddEvent.java
new file mode 100644
index 00000000..244b68a5
--- /dev/null
+++ b/docs-android/app/src/main/java/com/sismics/docs/event/DocumentAddEvent.java
@@ -0,0 +1,33 @@
+package com.sismics.docs.event;
+
+import org.json.JSONObject;
+
+/**
+ * Document add event.
+ *
+ * @author bgamard.
+ */
+public class DocumentAddEvent {
+ /**
+ * Document.
+ */
+ private JSONObject document;
+
+ /**
+ * Create a document add event.
+ *
+ * @param document Document
+ */
+ public DocumentAddEvent(JSONObject document) {
+ this.document = document;
+ }
+
+ /**
+ * Getter of document.
+ *
+ * @return document
+ */
+ public JSONObject getDocument() {
+ return document;
+ }
+}
diff --git a/docs-android/app/src/main/java/com/sismics/docs/fragment/DocListFragment.java b/docs-android/app/src/main/java/com/sismics/docs/fragment/DocListFragment.java
index 8a0d1d09..3047e9c1 100644
--- a/docs-android/app/src/main/java/com/sismics/docs/fragment/DocListFragment.java
+++ b/docs-android/app/src/main/java/com/sismics/docs/fragment/DocListFragment.java
@@ -17,6 +17,7 @@ import com.sismics.docs.R;
import com.sismics.docs.activity.DocumentEditActivity;
import com.sismics.docs.activity.DocumentViewActivity;
import com.sismics.docs.adapter.DocListAdapter;
+import com.sismics.docs.event.DocumentAddEvent;
import com.sismics.docs.event.DocumentEditEvent;
import com.sismics.docs.event.SearchEvent;
import com.sismics.docs.listener.JsonHttpResponseHandler;
@@ -44,6 +45,11 @@ public class DocListFragment extends Fragment {
*/
private String query;
+ /**
+ * Request code of adding document.
+ */
+ private static final int REQUEST_CODE_ADD_DOCUMENT = 1;
+
// View cache
private EmptyRecyclerView recyclerView;
private SwipeRefreshLayout swipeRefreshLayout;
@@ -87,9 +93,7 @@ public class DocListFragment extends Fragment {
public void onItemClick(View view, int position) {
JSONObject document = adapter.getItemAt(position);
if (document != null) {
- Intent intent = new Intent(getActivity(), DocumentViewActivity.class);
- intent.putExtra("document", document.toString());
- startActivity(intent);
+ openDocument(document);
}
}
}));
@@ -123,7 +127,7 @@ public class DocListFragment extends Fragment {
@Override
public void onClick(View v) {
Intent intent = new Intent(getActivity(), DocumentEditActivity.class);
- startActivityForResult(intent, 1);
+ startActivityForResult(intent, REQUEST_CODE_ADD_DOCUMENT);
}
});
@@ -134,11 +138,6 @@ public class DocListFragment extends Fragment {
return view;
}
- @Override
- public void onActivityResult(int requestCode, int resultCode, Intent data) {
- // TODO Reload the documents after document creation and open it from data
- }
-
@Override
public void onDestroyView() {
EventBus.getDefault().unregister(this);
@@ -164,6 +163,30 @@ public class DocListFragment extends Fragment {
adapter.updateDocument(event.getDocument());
}
+ /**
+ * A document add event has been fired.
+ *
+ * @param event Document add event
+ */
+ public void onEvent(DocumentAddEvent event) {
+ // Refresh the list, maybe the new document fit in it
+ loadDocuments(getView(), true);
+
+ // Open the newly created document
+ openDocument(event.getDocument());
+ }
+
+ /**
+ * Open a document.
+ *
+ * @param document Document to open
+ */
+ private void openDocument(JSONObject document) {
+ Intent intent = new Intent(getActivity(), DocumentViewActivity.class);
+ intent.putExtra("document", document.toString());
+ startActivity(intent);
+ }
+
/**
* Refresh the document list.
*
diff --git a/docs-android/app/src/main/java/com/sismics/docs/resource/DocumentResource.java b/docs-android/app/src/main/java/com/sismics/docs/resource/DocumentResource.java
index 502976ab..bff65450 100644
--- a/docs-android/app/src/main/java/com/sismics/docs/resource/DocumentResource.java
+++ b/docs-android/app/src/main/java/com/sismics/docs/resource/DocumentResource.java
@@ -5,6 +5,8 @@ import android.content.Context;
import com.loopj.android.http.RequestParams;
import com.sismics.docs.listener.JsonHttpResponseHandler;
+import java.util.Set;
+
/**
* Access to /document API.
*
@@ -43,4 +45,62 @@ public class DocumentResource extends BaseResource {
client.get(getApiUrl(context) + "/document/" + id, responseHandler);
}
+
+ /**
+ * PUT /document.
+ *
+ * @param context Context
+ * @param title Title
+ * @param description Description
+ * @param tagIdList Tags ID list
+ * @param language Language
+ * @param createDate Create date
+ * @param responseHandler Callback
+ */
+ public static void add(Context context, String title, String description,
+ Set tagIdList, String language, long createDate, JsonHttpResponseHandler responseHandler) {
+ init(context);
+
+ RequestParams params = new RequestParams();
+ params.put("title", title);
+ params.put("description", description);
+ params.put("tags", tagIdList);
+ params.put("language", language);
+ params.put("create_date", createDate);
+ client.put(getApiUrl(context) + "/document", params, responseHandler);
+ }
+
+ /**
+ * POST /document/id.
+ *
+ * @param context Context
+ * @param id ID
+ * @param title Title
+ * @param description Description
+ * @param tagIdList Tags ID list
+ * @param language Language
+ * @param createDate Create date
+ * @param responseHandler Callback
+ */
+ public static void edit(Context context, String id, String title, String description,
+ Set tagIdList, String language, long createDate, JsonHttpResponseHandler responseHandler) {
+ init(context);
+
+ RequestParams params = new RequestParams();
+ params.put("title", title);
+ params.put("description", description);
+ params.put("tags", tagIdList);
+ params.put("language", language);
+ params.put("create_date", createDate);
+ client.post(getApiUrl(context) + "/document/" + id, params, responseHandler);
+ }
+
+ /**
+ * Cancel pending requests.
+ *
+ * @param context Context
+ */
+ public static void cancel(Context context) {
+ client.cancelRequests(context, true);
+ }
}
diff --git a/docs-android/app/src/main/java/com/sismics/docs/ui/view/DatePickerView.java b/docs-android/app/src/main/java/com/sismics/docs/ui/view/DatePickerView.java
index 83475819..1ef99e81 100644
--- a/docs-android/app/src/main/java/com/sismics/docs/ui/view/DatePickerView.java
+++ b/docs-android/app/src/main/java/com/sismics/docs/ui/view/DatePickerView.java
@@ -40,6 +40,9 @@ public class DatePickerView extends TextView implements DatePickerDialog.OnDateS
@Override
public void onClick(View v) {
final Calendar calendar = Calendar.getInstance();
+ if (date != null) {
+ calendar.setTime(date);
+ }
new DatePickerDialog(
DatePickerView.this.getContext(), DatePickerView.this,
calendar.get(Calendar.YEAR),
diff --git a/docs-android/app/src/main/res/values/strings.xml b/docs-android/app/src/main/res/values/strings.xml
index 901f7512..bf00ac3a 100644
--- a/docs-android/app/src/main/res/values/strings.xml
+++ b/docs-android/app/src/main/res/values/strings.xml
@@ -76,6 +76,9 @@
Japanese
Save
Edit document
+ Network error, please try again
+ Please wait
+ Sending your data