{"action":"created","comment":{"url":"https://api.github.com/repos/opendatakit/collect/pulls/comments/106783222","pull_request_review_id":27726471,"id":106783222,"diff_hunk":"@@ -490,8 +497,16 @@ private boolean uploadOneSubmission(String urlString, String id, String instance\n                         outcome.mResults.put(id, fail + response.getStatusLine().getReasonPhrase()\n                                 + \" (\" + responseCode + \") at \" + urlString);\n                     } else {\n-                        outcome.mResults.put(id, fail + response.getStatusLine().getReasonPhrase()\n-                                + \" (\" + responseCode + \") at \" + urlString);\n+                        // Custom messaging response if fail.\n+                        // If Custom Server Response enabled then confirm response is valid","path":"collect_app/src/main/java/org/odk/collect/android/tasks/InstanceUploaderTask.java","position":51,"original_position":51,"commit_id":"a23da420aebc5199394ea82b5b99b3585c491c81","original_commit_id":"a23da420aebc5199394ea82b5b99b3585c491c81","user":{"login":"lognaturel","id":967540,"avatar_url":"https://avatars0.githubusercontent.com/u/967540?v=3","gravatar_id":"","url":"https://api.github.com/users/lognaturel","html_url":"https://github.com/lognaturel","followers_url":"https://api.github.com/users/lognaturel/followers","following_url":"https://api.github.com/users/lognaturel/following{/other_user}","gists_url":"https://api.github.com/users/lognaturel/gists{/gist_id}","starred_url":"https://api.github.com/users/lognaturel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lognaturel/subscriptions","organizations_url":"https://api.github.com/users/lognaturel/orgs","repos_url":"https://api.github.com/users/lognaturel/repos","events_url":"https://api.github.com/users/lognaturel/events{/privacy}","received_events_url":"https://api.github.com/users/lognaturel/received_events","type":"User","site_admin":false},"body":"Since there's no setting, Custom Server Response can't be disabled anymore! There's another comment just like this that can also be edited below.","created_at":"2017-03-18T15:25:38Z","updated_at":"2017-03-18T15:27:41Z","html_url":"https://github.com/opendatakit/collect/pull/465#discussion_r106783222","pull_request_url":"https://api.github.com/repos/opendatakit/collect/pulls/465","_links":{"self":{"href":"https://api.github.com/repos/opendatakit/collect/pulls/comments/106783222"},"html":{"href":"https://github.com/opendatakit/collect/pull/465#discussion_r106783222"},"pull_request":{"href":"https://api.github.com/repos/opendatakit/collect/pulls/465"}}},"pull_request":{"url":"https://api.github.com/repos/opendatakit/collect/pulls/465","id":108192881,"html_url":"https://github.com/opendatakit/collect/pull/465","diff_url":"https://github.com/opendatakit/collect/pull/465.diff","patch_url":"https://github.com/opendatakit/collect/pull/465.patch","issue_url":"https://api.github.com/repos/opendatakit/collect/issues/465","number":465,"state":"open","locked":false,"title":"Feature/custom messaging","user":{"login":"jnordling","id":11786919,"avatar_url":"https://avatars1.githubusercontent.com/u/11786919?v=3","gravatar_id":"","url":"https://api.github.com/users/jnordling","html_url":"https://github.com/jnordling","followers_url":"https://api.github.com/users/jnordling/followers","following_url":"https://api.github.com/users/jnordling/following{/other_user}","gists_url":"https://api.github.com/users/jnordling/gists{/gist_id}","starred_url":"https://api.github.com/users/jnordling/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jnordling/subscriptions","organizations_url":"https://api.github.com/users/jnordling/orgs","repos_url":"https://api.github.com/users/jnordling/repos","events_url":"https://api.github.com/users/jnordling/events{/privacy}","received_events_url":"https://api.github.com/users/jnordling/received_events","type":"User","site_admin":false},"body":"PR for issue #194 \r\n\r\nCustom Messaging Response handled during form submission, both success and error messaging. Ill be referencing #194 discussion \r\n\r\n### Part 1) Preferences/Admin/General\r\nMitch mentioned in the issue that this is a feature that should be in through preferences. so I added is as Custom Server Responses. Just the same as all other settings. It can be toggled on/off via the Administrative menu. Whether or not is enabled is handled in the InstanceUploaderTask class. See image below.\r\n\r\n|        |           | \r\n| ------------- |:-------------:| \r\n| <img src=\"https://cloud.githubusercontent.com/assets/11786919/23374111/d722006c-fcf0-11e6-9aec-940d0204ad06.png\" width=\"300\">      | <img src=\"https://cloud.githubusercontent.com/assets/11786919/23374111/d722006c-fcf0-11e6-9aec-940d0204ad06.png\" width=\"300\"> | \r\n\r\n---\r\n### Part2) ResponseMessageParser\r\nAdding ResponseMessageParser class was added to handle the parsing from the server. The reason that I made it its own class is because I can see future use cased to parse messaging from the server response in other areas such as on downloading a form. \r\nThis ResponseMessageParser is located in the org.odk.collect.android.utilities package with other similar style functions.\r\n\r\n### Part3) InstanceUploaderTask\r\nThis is where the important stuff happens. The InstanceUploaderTask handles the submission to there server for each of the selected form to send off the its respective server. Note that this has been tested with ODK Aggregate, Ona.io, Formhub, and Cadasta's Platform.  \r\n\r\nSo there are a bunch of error checking via the response code. It it gets passed it usual test (basically the authentication, files checking, response code) It is either a successful response and was created or it  has error response indicates it was not created, of failed for anther reason. Currently is just displays standard IO messaging. Now if a valid javarosa response message is returned back and the Custom response feature is enabled it will show the message. Otherwise it it is not valid of Custom response feature is NOT enabled then use the default messaging. \r\n\r\nVery excited about this. It opens the door to some interesting options for sending detail,info, instructions back down to the user. Ill describe how this feature is used by Cadasta further down.\r\n\r\nHere is a reference for the javarosa response details\r\n\r\n```\r\n<OpenRosaResponse xmlns=\"http://openrosa.org/http/response\">\r\n        <message>Form Received! You've submitted 5 forms today</message>\r\n </OpenRosaResponse>\r\n```\r\n\r\nhttps://bitbucket.org/javarosa/javarosa/wiki/FormSubmissionAPI\r\n\r\n### Part4) Strings/UI\r\nOne thing to note is that there where strings for the UI. These will have to be added for translation in the future. \r\n\r\n### Part 5) Use Cases & Tests\r\n\r\nThis feature has been tested with ODK Aggregate, Ona.io, Formhub, Cadasta. I see no reason why this would not work with any OpenRosaApi complient application. ODK requires this to be able to receive and submit forms. In all cases I tested it seem that each platform has there own flavor of messaging. Which is great! means it works out of the gate with out and server side developement. \r\n\r\nThe example below uses demo ODK Aggregate system i have. Give it a try is you want. http://geoodk-demo.appspot.com. The image on the left is the standard message and the message on the right is the message that is returned via the message tag of the response.\r\n\r\n|  Standard Message      |    Custom Message      | \r\n| ------------- |:-------------:| \r\n| <img src=\"https://cloud.githubusercontent.com/assets/11786919/23376192/4b977b5e-fcf9-11e6-979a-7d8922200bd7.png\" width=\"300\">      | <img src=\"https://cloud.githubusercontent.com/assets/11786919/23376219/5dc9f306-fcf9-11e6-9cd6-7d5b130774e2.png\" width=\"300\"> | \r\n\r\nThis images are just to show if you uncheck the custom message, messaging functions as default messaging. \r\n\r\n|  Custom Message OFF |   Response      | \r\n| ------------- |:-------------:| \r\n| <img src=\"https://cloud.githubusercontent.com/assets/11786919/23376654/f1ba9ca4-fcfa-11e6-8672-d15e031fb489.png\" width=\"300\">      | <img src=\"https://cloud.githubusercontent.com/assets/11786919/23376588/adc1a22c-fcfa-11e6-994e-dd1277410044.png\" width=\"300\"> | \r\n\r\n### Another Note\r\nThis image was for testing multiple submissions. Works just fine. Mitch mentioned in the issue about multiple HTTP requests. In this case the message is for each instance. For instance more than 10MB of image/audio/video attachments) The messaging is at the error and success level not sure that this is effect by this. Would be good to test if anyone has an example to share. As far as i can see it seems good.\r\n\r\n### How it will be used with Cadasta and example. \r\n\r\nSo Cadasta has some logic on the server side that if a users sends a form and based on some requirements they have via groups/roles access, questions answers response logic (lets say a user needs to fill out a form/survey before the form they are filling out, or maybe a form/survey is only for a certain season or time period) they use case goes on and on. (Cadasta looks really promising for a server ODK side app)\r\n\r\nIn this example this form is failing because I did not fill out a field and Cadasta requires. (I know you can handle that via a \"require\" in the form, but was just for a simple example to show the difference)\r\n\r\n\r\n|  Custom Message OFF |   Response      | \r\n| ------------- |:-------------:| \r\n| <img src=\"https://cloud.githubusercontent.com/assets/11786919/23377771/33314116-fcff-11e6-8f7e-4985b2c20dd8.png\" width=\"300\">      | <img src=\"https://cloud.githubusercontent.com/assets/11786919/23377785/3f6c65aa-fcff-11e6-8241-3f850b2a93a1.png\" width=\"300\"> | \r\n\r\nIf i missed anything let me know! I can see use for both debugging forms aswell as for targeted user feedback and messaging. \r\n\r\nAll hail ODK!!! :)\r\n\r\nJon\r\n\r\n\r\n\r\n\r\n\r\n\r\n","created_at":"2017-02-27T20:18:37Z","updated_at":"2017-03-18T15:27:41Z","closed_at":null,"merged_at":null,"merge_commit_sha":"9df0dd1f7218d5c7f274b5cca2b8b4406272c862","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/opendatakit/collect/pulls/465/commits","review_comments_url":"https://api.github.com/repos/opendatakit/collect/pulls/465/comments","review_comment_url":"https://api.github.com/repos/opendatakit/collect/pulls/comments{/number}","comments_url":"https://api.github.com/repos/opendatakit/collect/issues/465/comments","statuses_url":"https://api.github.com/repos/opendatakit/collect/statuses/a23da420aebc5199394ea82b5b99b3585c491c81","head":{"label":"jnordling:feature/custom-messaging","ref":"feature/custom-messaging","sha":"a23da420aebc5199394ea82b5b99b3585c491c81","user":{"login":"jnordling","id":11786919,"avatar_url":"https://avatars1.githubusercontent.com/u/11786919?v=3","gravatar_id":"","url":"https://api.github.com/users/jnordling","html_url":"https://github.com/jnordling","followers_url":"https://api.github.com/users/jnordling/followers","following_url":"https://api.github.com/users/jnordling/following{/other_user}","gists_url":"https://api.github.com/users/jnordling/gists{/gist_id}","starred_url":"https://api.github.com/users/jnordling/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jnordling/subscriptions","organizations_url":"https://api.github.com/users/jnordling/orgs","repos_url":"https://api.github.com/users/jnordling/repos","events_url":"https://api.github.com/users/jnordling/events{/privacy}","received_events_url":"https://api.github.com/users/jnordling/received_events","type":"User","site_admin":false},"repo":{"id":82405632,"name":"collect","full_name":"jnordling/collect","owner":{"login":"jnordling","id":11786919,"avatar_url":"https://avatars1.githubusercontent.com/u/11786919?v=3","gravatar_id":"","url":"https://api.github.com/users/jnordling","html_url":"https://github.com/jnordling","followers_url":"https://api.github.com/users/jnordling/followers","following_url":"https://api.github.com/users/jnordling/following{/other_user}","gists_url":"https://api.github.com/users/jnordling/gists{/gist_id}","starred_url":"https://api.github.com/users/jnordling/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jnordling/subscriptions","organizations_url":"https://api.github.com/users/jnordling/orgs","repos_url":"https://api.github.com/users/jnordling/repos","events_url":"https://api.github.com/users/jnordling/events{/privacy}","received_events_url":"https://api.github.com/users/jnordling/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/jnordling/collect","description":"ODK Collect is an Android app for filling out forms. It's been used to collect millions of data points in challenging environments around the world. Contribute and make the world a better place! ✨📋✨","fork":true,"url":"https://api.github.com/repos/jnordling/collect","forks_url":"https://api.github.com/repos/jnordling/collect/forks","keys_url":"https://api.github.com/repos/jnordling/collect/keys{/key_id}","collaborators_url":"https://api.github.com/repos/jnordling/collect/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/jnordling/collect/teams","hooks_url":"https://api.github.com/repos/jnordling/collect/hooks","issue_events_url":"https://api.github.com/repos/jnordling/collect/issues/events{/number}","events_url":"https://api.github.com/repos/jnordling/collect/events","assignees_url":"https://api.github.com/repos/jnordling/collect/assignees{/user}","branches_url":"https://api.github.com/repos/jnordling/collect/branches{/branch}","tags_url":"https://api.github.com/repos/jnordling/collect/tags","blobs_url":"https://api.github.com/repos/jnordling/collect/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/jnordling/collect/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/jnordling/collect/git/refs{/sha}","trees_url":"https://api.github.com/repos/jnordling/collect/git/trees{/sha}","statuses_url":"https://api.github.com/repos/jnordling/collect/statuses/{sha}","languages_url":"https://api.github.com/repos/jnordling/collect/languages","stargazers_url":"https://api.github.com/repos/jnordling/collect/stargazers","contributors_url":"https://api.github.com/repos/jnordling/collect/contributors","subscribers_url":"https://api.github.com/repos/jnordling/collect/subscribers","subscription_url":"https://api.github.com/repos/jnordling/collect/subscription","commits_url":"https://api.github.com/repos/jnordling/collect/commits{/sha}","git_commits_url":"https://api.github.com/repos/jnordling/collect/git/commits{/sha}","comments_url":"https://api.github.com/repos/jnordling/collect/comments{/number}","issue_comment_url":"https://api.github.com/repos/jnordling/collect/issues/comments{/number}","contents_url":"https://api.github.com/repos/jnordling/collect/contents/{+path}","compare_url":"https://api.github.com/repos/jnordling/collect/compare/{base}...{head}","merges_url":"https://api.github.com/repos/jnordling/collect/merges","archive_url":"https://api.github.com/repos/jnordling/collect/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/jnordling/collect/downloads","issues_url":"https://api.github.com/repos/jnordling/collect/issues{/number}","pulls_url":"https://api.github.com/repos/jnordling/collect/pulls{/number}","milestones_url":"https://api.github.com/repos/jnordling/collect/milestones{/number}","notifications_url":"https://api.github.com/repos/jnordling/collect/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/jnordling/collect/labels{/name}","releases_url":"https://api.github.com/repos/jnordling/collect/releases{/id}","deployments_url":"https://api.github.com/repos/jnordling/collect/deployments","created_at":"2017-02-18T18:00:19Z","updated_at":"2017-02-18T18:00:22Z","pushed_at":"2017-03-17T22:56:52Z","git_url":"git://github.com/jnordling/collect.git","ssh_url":"git@github.com:jnordling/collect.git","clone_url":"https://github.com/jnordling/collect.git","svn_url":"https://github.com/jnordling/collect","homepage":"https://github.com/opendatakit/collect","size":32538,"stargazers_count":0,"watchers_count":0,"language":"Java","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"opendatakit:master","ref":"master","sha":"4baa5b828eec94088c21e3ccae0693a6623d6298","user":{"login":"opendatakit","id":6222985,"avatar_url":"https://avatars3.githubusercontent.com/u/6222985?v=3","gravatar_id":"","url":"https://api.github.com/users/opendatakit","html_url":"https://github.com/opendatakit","followers_url":"https://api.github.com/users/opendatakit/followers","following_url":"https://api.github.com/users/opendatakit/following{/other_user}","gists_url":"https://api.github.com/users/opendatakit/gists{/gist_id}","starred_url":"https://api.github.com/users/opendatakit/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/opendatakit/subscriptions","organizations_url":"https://api.github.com/users/opendatakit/orgs","repos_url":"https://api.github.com/users/opendatakit/repos","events_url":"https://api.github.com/users/opendatakit/events{/privacy}","received_events_url":"https://api.github.com/users/opendatakit/received_events","type":"Organization","site_admin":false},"repo":{"id":40213809,"name":"collect","full_name":"opendatakit/collect","owner":{"login":"opendatakit","id":6222985,"avatar_url":"https://avatars3.githubusercontent.com/u/6222985?v=3","gravatar_id":"","url":"https://api.github.com/users/opendatakit","html_url":"https://github.com/opendatakit","followers_url":"https://api.github.com/users/opendatakit/followers","following_url":"https://api.github.com/users/opendatakit/following{/other_user}","gists_url":"https://api.github.com/users/opendatakit/gists{/gist_id}","starred_url":"https://api.github.com/users/opendatakit/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/opendatakit/subscriptions","organizations_url":"https://api.github.com/users/opendatakit/orgs","repos_url":"https://api.github.com/users/opendatakit/repos","events_url":"https://api.github.com/users/opendatakit/events{/privacy}","received_events_url":"https://api.github.com/users/opendatakit/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/opendatakit/collect","description":"ODK Collect is an Android app for filling out forms. It's been used to collect billions of data points in challenging environments around the world. Contribute and make the world a better place! ✨📋✨","fork":false,"url":"https://api.github.com/repos/opendatakit/collect","forks_url":"https://api.github.com/repos/opendatakit/collect/forks","keys_url":"https://api.github.com/repos/opendatakit/collect/keys{/key_id}","collaborators_url":"https://api.github.com/repos/opendatakit/collect/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/opendatakit/collect/teams","hooks_url":"https://api.github.com/repos/opendatakit/collect/hooks","issue_events_url":"https://api.github.com/repos/opendatakit/collect/issues/events{/number}","events_url":"https://api.github.com/repos/opendatakit/collect/events","assignees_url":"https://api.github.com/repos/opendatakit/collect/assignees{/user}","branches_url":"https://api.github.com/repos/opendatakit/collect/branches{/branch}","tags_url":"https://api.github.com/repos/opendatakit/collect/tags","blobs_url":"https://api.github.com/repos/opendatakit/collect/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/opendatakit/collect/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/opendatakit/collect/git/refs{/sha}","trees_url":"https://api.github.com/repos/opendatakit/collect/git/trees{/sha}","statuses_url":"https://api.github.com/repos/opendatakit/collect/statuses/{sha}","languages_url":"https://api.github.com/repos/opendatakit/collect/languages","stargazers_url":"https://api.github.com/repos/opendatakit/collect/stargazers","contributors_url":"https://api.github.com/repos/opendatakit/collect/contributors","subscribers_url":"https://api.github.com/repos/opendatakit/collect/subscribers","subscription_url":"https://api.github.com/repos/opendatakit/collect/subscription","commits_url":"https://api.github.com/repos/opendatakit/collect/commits{/sha}","git_commits_url":"https://api.github.com/repos/opendatakit/collect/git/commits{/sha}","comments_url":"https://api.github.com/repos/opendatakit/collect/comments{/number}","issue_comment_url":"https://api.github.com/repos/opendatakit/collect/issues/comments{/number}","contents_url":"https://api.github.com/repos/opendatakit/collect/contents/{+path}","compare_url":"https://api.github.com/repos/opendatakit/collect/compare/{base}...{head}","merges_url":"https://api.github.com/repos/opendatakit/collect/merges","archive_url":"https://api.github.com/repos/opendatakit/collect/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/opendatakit/collect/downloads","issues_url":"https://api.github.com/repos/opendatakit/collect/issues{/number}","pulls_url":"https://api.github.com/repos/opendatakit/collect/pulls{/number}","milestones_url":"https://api.github.com/repos/opendatakit/collect/milestones{/number}","notifications_url":"https://api.github.com/repos/opendatakit/collect/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/opendatakit/collect/labels{/name}","releases_url":"https://api.github.com/repos/opendatakit/collect/releases{/id}","deployments_url":"https://api.github.com/repos/opendatakit/collect/deployments","created_at":"2015-08-04T23:21:33Z","updated_at":"2017-03-18T09:28:06Z","pushed_at":"2017-03-18T15:27:07Z","git_url":"git://github.com/opendatakit/collect.git","ssh_url":"git@github.com:opendatakit/collect.git","clone_url":"https://github.com/opendatakit/collect.git","svn_url":"https://github.com/opendatakit/collect","homepage":"https://github.com/opendatakit/collect","size":32524,"stargazers_count":56,"watchers_count":56,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":277,"mirror_url":null,"open_issues_count":214,"forks":277,"open_issues":214,"watchers":56,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/opendatakit/collect/pulls/465"},"html":{"href":"https://github.com/opendatakit/collect/pull/465"},"issue":{"href":"https://api.github.com/repos/opendatakit/collect/issues/465"},"comments":{"href":"https://api.github.com/repos/opendatakit/collect/issues/465/comments"},"review_comments":{"href":"https://api.github.com/repos/opendatakit/collect/pulls/465/comments"},"review_comment":{"href":"https://api.github.com/repos/opendatakit/collect/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/opendatakit/collect/pulls/465/commits"},"statuses":{"href":"https://api.github.com/repos/opendatakit/collect/statuses/a23da420aebc5199394ea82b5b99b3585c491c81"}}}}
{"actor":{"display_login":"lognaturel"}}