Android: Document adding/editing

This commit is contained in:
jendib 2014-12-11 22:13:06 +01:00
parent a762ce4715
commit 17e5c65d04
10 changed files with 225 additions and 43 deletions

View File

@ -98,15 +98,15 @@
<orderEntry type="jdk" jdkName="Android API 21 Platform" jdkType="Android SDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" exported="" name="recyclerview-v7-21.0.0" level="project" />
<orderEntry type="library" exported="" name="appcompat-v7-21.0.3" level="project" />
<orderEntry type="library" exported="" name="fab-0.0.6" level="project" />
<orderEntry type="library" exported="" name="android-easing-1.0.3" level="project" />
<orderEntry type="library" exported="" name="support-annotations-21.0.2" level="project" />
<orderEntry type="library" exported="" name="imagezoom-1.0.5" level="project" />
<orderEntry type="library" exported="" name="support-v4-21.0.2" level="project" />
<orderEntry type="library" exported="" name="support-annotations-21.0.3" level="project" />
<orderEntry type="library" exported="" name="support-v4-21.0.3" level="project" />
<orderEntry type="library" exported="" name="eventbus-2.4.0" level="project" />
<orderEntry type="library" exported="" name="android-query.0.26.8" level="project" />
<orderEntry type="library" exported="" name="tokenautocomplete-1.2.1" level="project" />
<orderEntry type="library" exported="" name="appcompat-v7-21.0.2" level="project" />
<orderEntry type="library" exported="" name="android-async-http-1.4.6" level="project" />
</component>
</module>

View File

@ -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'

View File

@ -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();

View File

@ -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<String> 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:

View File

@ -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")));

View File

@ -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;
}
}

View File

@ -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.
*

View File

@ -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<String> 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<String> 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);
}
}

View File

@ -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),

View File

@ -76,6 +76,9 @@
<string name="language_japanese">Japanese</string>
<string name="save">Save</string>
<string name="edit_document">Edit document</string>
<string name="error_editing_document">Network error, please try again</string>
<string name="document_editing_title">Please wait</string>
<string name="document_editing_message">Sending your data</string>
</resources>