From 4e0edc62801a9eb19e40965e5be31deedafd327d Mon Sep 17 00:00:00 2001 From: Aaron Huttner Date: Tue, 23 Aug 2016 17:46:26 -0400 Subject: [PATCH] add voter declaration add disclosure agreement version bump --- app/build.gradle | 2 +- .../grommet/data/api/RegistrationService.java | 18 ++++- .../data/api/model/ApiVoterRegistration.java | 1 + .../grommet/data/db/model/RockyRequest.java | 1 + .../registration/AdditionalInfoFragment.java | 2 +- .../DisclosureAgreementDialogFragment.java | 73 ++++++++++++++++++ .../ui/registration/PersonalInfoFragment.java | 24 +++--- .../ReviewAndConfirmFragment.java | 28 ++++++- .../layout/dialog_disclosure_agreement.xml | 52 +++++++++++++ .../res/layout/fragment_additional_info.xml | 3 + .../res/layout/fragment_assistant_info.xml | 12 ++- .../res/layout/fragment_personal_info.xml | 8 ++ app/src/main/res/values/strings.xml | 74 ++++++++++++++++++- 13 files changed, 276 insertions(+), 22 deletions(-) create mode 100644 app/src/main/java/com/rockthevote/grommet/ui/registration/DisclosureAgreementDialogFragment.java create mode 100644 app/src/main/res/layout/dialog_disclosure_agreement.xml diff --git a/app/build.gradle b/app/build.gradle index b90c92d8..6fab2dc4 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,7 +1,7 @@ // Manifest version information! def versionMajor = 1 def versionMinor = 0 -def versionPatch = 3 +def versionPatch = 4 def versionBuild = 0 // bump for dogfood builds, public betas, etc. apply plugin: 'com.android.application' diff --git a/app/src/main/java/com/rockthevote/grommet/data/api/RegistrationService.java b/app/src/main/java/com/rockthevote/grommet/data/api/RegistrationService.java index 39a3c4a6..f1cb879e 100644 --- a/app/src/main/java/com/rockthevote/grommet/data/api/RegistrationService.java +++ b/app/src/main/java/com/rockthevote/grommet/data/api/RegistrationService.java @@ -63,6 +63,7 @@ import static com.rockthevote.grommet.data.db.model.RockyRequest.Status.ABANDONED; import static com.rockthevote.grommet.data.db.model.RockyRequest.Status.FORM_COMPLETE; import static com.rockthevote.grommet.data.db.model.RockyRequest.Status.IN_PROGRESS; +import static com.rockthevote.grommet.data.db.model.RockyRequest.Status.REGISTER_CLIENT_FAILURE; import static com.rockthevote.grommet.data.db.model.RockyRequest.Status.REGISTER_SERVER_FAILURE; import static com.rockthevote.grommet.data.db.model.RockyRequest.Status.REGISTER_SUCCESS; import static java.util.Map.Entry; @@ -163,6 +164,14 @@ private void doWork(final RockyRequest rockyRequest) { .status(status) .build(), RockyRequest._ID + " = ? ", String.valueOf(rockyRequest.id())); + }, + throwable -> { + // mark the row for removal if the data is corrupt + db.update(RockyRequest.TABLE, + new RockyRequest.Builder() + .status(REGISTER_CLIENT_FAILURE) + .build(), + RockyRequest._ID + " = ? ", String.valueOf(rockyRequest.id())); } ); } @@ -181,6 +190,7 @@ private void cleanup() { + STATUS + " IN (" + "'" + ABANDONED + "', " + "'" + REGISTER_SERVER_FAILURE + "'," + + "'" + REGISTER_CLIENT_FAILURE + "'," + "'" + REGISTER_SUCCESS + "'" + ")"; @@ -270,8 +280,11 @@ private ApiRockyRequestWrapper zipRockyRequest(RockyRequest rockyRequest, EnumMap voterIds, EnumMap additionalInfo) { - - // Get address info objects + /* + * Get address info objects, this is a bit "mucky" because of the way I collect the data + * there will still be an address object even if the user didn't check the box for + * that type + */ ApiAddress apiRegAddress = ApiAddress.fromAddress(addresses.get(REGISTRATION_ADDRESS)); ApiAddress apiMailAddress = rockyRequest.hasMailingAddress() ? ApiAddress.fromAddress(addresses.get(MAILING_ADDRESS)) : null; @@ -345,7 +358,6 @@ private ApiRockyRequestWrapper zipRockyRequest(RockyRequest rockyRequest, return ApiRockyRequestWrapper.builder().apiRockyRequest(apiRockyRequest).build(); } - @Nullable @Override public IBinder onBind(Intent intent) { diff --git a/app/src/main/java/com/rockthevote/grommet/data/api/model/ApiVoterRegistration.java b/app/src/main/java/com/rockthevote/grommet/data/api/model/ApiVoterRegistration.java index c4993c82..df8fa2c2 100644 --- a/app/src/main/java/com/rockthevote/grommet/data/api/model/ApiVoterRegistration.java +++ b/app/src/main/java/com/rockthevote/grommet/data/api/model/ApiVoterRegistration.java @@ -123,6 +123,7 @@ public static ApiVoterRegistration fromDb(RockyRequest rockyRequest, List contactMethods, List additionalInfo, ApiRegistrationHelper registrationHelper) { + return builder() .dateOfBirth(Dates.formatAsISO8601_ShortDate(rockyRequest.dateOfBirth())) .mailingAddress(mailingAddress) diff --git a/app/src/main/java/com/rockthevote/grommet/data/db/model/RockyRequest.java b/app/src/main/java/com/rockthevote/grommet/data/db/model/RockyRequest.java index 5a5bdd32..0cec063f 100644 --- a/app/src/main/java/com/rockthevote/grommet/data/db/model/RockyRequest.java +++ b/app/src/main/java/com/rockthevote/grommet/data/db/model/RockyRequest.java @@ -16,6 +16,7 @@ import rx.functions.Func1; @AutoValue +@SuppressWarnings("mutable") public abstract class RockyRequest implements Parcelable, BaseColumns { public static final String TABLE = "rocky_request"; diff --git a/app/src/main/java/com/rockthevote/grommet/ui/registration/AdditionalInfoFragment.java b/app/src/main/java/com/rockthevote/grommet/ui/registration/AdditionalInfoFragment.java index 2b7dc95f..f9131114 100644 --- a/app/src/main/java/com/rockthevote/grommet/ui/registration/AdditionalInfoFragment.java +++ b/app/src/main/java/com/rockthevote/grommet/ui/registration/AdditionalInfoFragment.java @@ -61,7 +61,7 @@ public class AdditionalInfoFragment extends BaseRegistrationFragment { @BindView(R.id.does_not_have_penn_dot_checkbox) CheckBox noPennDOTCheckbox; - @NotEmpty(messageResId = R.string.error_penn_dot) + @Length(min = 8, max = 8, messageResId = R.string.error_penn_dot) @BindView(R.id.til_penn_dot) TextInputLayout pennDOTTIL; @BindView(R.id.penn_dot_edit_text) EditText pennDOTEditText; diff --git a/app/src/main/java/com/rockthevote/grommet/ui/registration/DisclosureAgreementDialogFragment.java b/app/src/main/java/com/rockthevote/grommet/ui/registration/DisclosureAgreementDialogFragment.java new file mode 100644 index 00000000..a9eb5462 --- /dev/null +++ b/app/src/main/java/com/rockthevote/grommet/ui/registration/DisclosureAgreementDialogFragment.java @@ -0,0 +1,73 @@ +package com.rockthevote.grommet.ui.registration; + +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v4.app.DialogFragment; +import android.text.Html; +import android.text.Spanned; +import android.text.method.LinkMovementMethod; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import com.rockthevote.grommet.R; +import com.rockthevote.grommet.util.ListTagHandler; + +import butterknife.BindView; +import butterknife.ButterKnife; +import butterknife.OnClick; + +public class DisclosureAgreementDialogFragment extends DialogFragment { + + @BindView(R.id.text_content) TextView content; + + private DisclosureListener listener; + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + setCancelable(false); + View v = inflater.inflate(R.layout.dialog_disclosure_agreement, container); + ButterKnife.bind(this, v); + + Spanned result; + + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) { + result = Html.fromHtml(getString(R.string.disclosure_agreement), + Html.FROM_HTML_MODE_LEGACY, null, new ListTagHandler()); + } else { + result = Html.fromHtml(getString(R.string.disclosure_agreement), + null, new ListTagHandler()); + } + + content.setText(result); + content.setMovementMethod(LinkMovementMethod.getInstance()); + return v; + } + + public void setListener(DisclosureListener listener) { + this.listener = listener; + } + + @OnClick(R.id.disclosure_decline_button) + public void onDeclineClick(View v) { + if (null != listener) { + listener.onDeclineClick(); + } + } + + @OnClick(R.id.disclosure_accept_button) + public void onAcceptClick(View v) { + if (null != listener) { + listener.onAcceptClick(); + } + } + + public interface DisclosureListener { + + void onDeclineClick(); + + void onAcceptClick(); + } +} diff --git a/app/src/main/java/com/rockthevote/grommet/ui/registration/PersonalInfoFragment.java b/app/src/main/java/com/rockthevote/grommet/ui/registration/PersonalInfoFragment.java index f4056ace..ba86b2e0 100644 --- a/app/src/main/java/com/rockthevote/grommet/ui/registration/PersonalInfoFragment.java +++ b/app/src/main/java/com/rockthevote/grommet/ui/registration/PersonalInfoFragment.java @@ -9,10 +9,12 @@ import com.f2prateek.rx.preferences.Preference; import com.jakewharton.rxbinding.widget.RxCompoundButton; +import com.mobsandgeeks.saripaar.annotation.Checked; import com.rockthevote.grommet.R; import com.rockthevote.grommet.data.db.model.RockyRequest; import com.rockthevote.grommet.data.db.model.VoterClassification; import com.rockthevote.grommet.data.prefs.CurrentRockyRequestId; +import com.rockthevote.grommet.ui.misc.ObservableValidator; import com.rockthevote.grommet.ui.views.AddressView; import com.squareup.sqlbrite.BriteDatabase; @@ -33,6 +35,9 @@ public class PersonalInfoFragment extends BaseRegistrationFragment { + @Checked(value = false, messageResId = R.string.error_no_address) + @BindView(R.id.no_address_checkbox) CheckBox noAddress; + @BindView(R.id.home_address) AddressView homeAddress; @BindView(R.id.mailing_address) AddressView mailingAddress; @@ -55,6 +60,8 @@ public class PersonalInfoFragment extends BaseRegistrationFragment { private CompositeSubscription subscriptions; + private ObservableValidator validator; + @Nullable @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { @@ -66,6 +73,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); ButterKnife.bind(this, view); + validator = new ObservableValidator(this, getActivity()); } @Override @@ -125,17 +133,9 @@ public Observable verify() { Observable changedAddObs = previousAddress.verify() .flatMap(val -> Observable.just(addressChanged.isChecked() ? val : true)); - return homeAddress.verify() - .concatWith(mailingAddressObs) - .concatWith(changedAddObs) - .toList() - .flatMap(list -> { - Boolean ret = true; - for (Boolean val : list) { - ret = ret && val; - } - - return Observable.just(ret); - }); + return Observable.zip(homeAddress.verify(), mailingAddressObs, + changedAddObs, validator.validate(), + (home, mail, change, other) -> home && mail && change && other); + } } diff --git a/app/src/main/java/com/rockthevote/grommet/ui/registration/ReviewAndConfirmFragment.java b/app/src/main/java/com/rockthevote/grommet/ui/registration/ReviewAndConfirmFragment.java index e50c5af0..2dc6d8ed 100644 --- a/app/src/main/java/com/rockthevote/grommet/ui/registration/ReviewAndConfirmFragment.java +++ b/app/src/main/java/com/rockthevote/grommet/ui/registration/ReviewAndConfirmFragment.java @@ -8,6 +8,7 @@ import android.view.View; import android.view.ViewGroup; import android.widget.Button; +import android.widget.CheckBox; import android.widget.TextView; import com.f2prateek.rx.preferences.Preference; @@ -65,6 +66,8 @@ public class ReviewAndConfirmFragment extends BaseRegistrationFragment implement @BindView(R.id.signature_pad_error) TextView signaturePadError; @BindView(R.id.button_register) Button buttonRegister; + @BindView(R.id.checkbox_agreement) CheckBox confirmCheckbox; + @Inject @EventRegTotal Preference eventRegTotal; @Inject @AppRegTotal Preference appRegTotal; @@ -73,6 +76,7 @@ public class ReviewAndConfirmFragment extends BaseRegistrationFragment implement @Inject BriteDatabase db; private CompositeSubscription subscriptions; + private DisclosureAgreementDialogFragment dialog; @Nullable @Override @@ -85,11 +89,28 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); ButterKnife.bind(this, view); + + dialog = new DisclosureAgreementDialogFragment(); + dialog.setCancelable(false); } @Override public void onResume() { super.onResume(); + dialog.setListener(new DisclosureAgreementDialogFragment.DisclosureListener() { + @Override + public void onDeclineClick() { + confirmCheckbox.setChecked(false); + dialog.dismiss(); + } + + @Override + public void onAcceptClick() { + buttonRegister.setEnabled(true); + dialog.dismiss(); + } + }); + subscriptions = new CompositeSubscription(); signaturePad.setOnSignedListener(this); @@ -155,6 +176,7 @@ public void onPause() { super.onPause(); subscriptions.unsubscribe(); signaturePad.setOnSignedListener(null); + dialog.setListener(null); } @OnClick(R.id.clear_signature) @@ -164,7 +186,9 @@ public void onClearSignatureClick(View v) { @OnCheckedChanged(R.id.checkbox_agreement) public void onCheckChanged(boolean checked) { - buttonRegister.setEnabled(checked); + if (checked) { + dialog.show(getFragmentManager(), "disclosure_dialog"); + } } @Override @@ -192,7 +216,7 @@ public void onClear() { RockyRequest._ID + " = ? ", String.valueOf(rockyRequestRowId.get())); } - // the default value is set in the datamodule + // the default value is set in the data module @SuppressWarnings("ConstantConditions") @OnClick(R.id.button_register) public void onRegisterClick(View v) { diff --git a/app/src/main/res/layout/dialog_disclosure_agreement.xml b/app/src/main/res/layout/dialog_disclosure_agreement.xml new file mode 100644 index 00000000..10e26b07 --- /dev/null +++ b/app/src/main/res/layout/dialog_disclosure_agreement.xml @@ -0,0 +1,52 @@ + + + + + + + + + +