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

Feature/gh 1733/legal updates #414

Merged
merged 17 commits into from Jul 18, 2019
Merged
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
a2e4762
Begin implementation of legal consent checkbox
wlycdgr Jul 1, 2019
5a1f223
Add Public License and Privacy Policy links
wlycdgr Jul 1, 2019
466dd63
Remove old legal disclaimer from account creation form
wlycdgr Jul 1, 2019
84e44bb
Fix account creation form legal consent checkbox formatting
wlycdgr Jul 1, 2019
c00031f
Merge branch 'develop' into feature/GH-1733/legal-updates
wlycdgr Jul 3, 2019
5276732
Disable linting for legal terms checkbox label because linter is conf…
wlycdgr Jul 3, 2019
cbeafde
Merge branch 'develop' into feature/GH-1733/legal-updates
wlycdgr Jul 3, 2019
2f8662d
Block account creation in extension if legal consent checkbox is unch…
wlycdgr Jul 3, 2019
8ab9c4f
Remove placeholder legal consent string from messages json. Add place…
wlycdgr Jul 17, 2019
7799238
Swap in correct legal consent string for hub account creation form. A…
wlycdgr Jul 17, 2019
01f49c4
Implement legal consent checkbox state change handling
wlycdgr Jul 17, 2019
e8232ac
Improve and tidy legal consent checkbox UI in hub
wlycdgr Jul 17, 2019
da542fa
Update hub account creation form snapshots
wlycdgr Jul 17, 2019
30d725a
Resolve merge conflict in messages. Merge develop in.
wlycdgr Jul 17, 2019
b5a99d3
Reverse order of checkboxes in extension account creation form to mat…
wlycdgr Jul 17, 2019
87279fd
Merge branch 'develop' into feature/GH-1733/legal-updates
wlycdgr Jul 18, 2019
9eaa3ae
Change setState to use callback in hub account creation form checkbox…
wlycdgr Jul 18, 2019
File filter
Filter file types
Jump to
Jump to file
Failed to load files.

Always

Just for now

@@ -2228,6 +2228,23 @@
"cliqz_feature_status_off": {
"message": "Off"
},
"create_account_form_legal_consent_checkbox_label": {
"message": "I accept the $LINK_TERMS_START$Terms and Conditions$LINK_END$, the $LINK_LICENSE_START$Public License Agreement$LINK_END$, and consent to data practices found in the $LINK_PRIVACY_START$Privacy Policy$LINK_END$.",
"placeholders": {
"link_end": {
"content": "</a>"
},
"link_license_start": {
"content": "<a target=\"_blank\" href=\"https://www.mozilla.org/en-US/MPL/2.0/\" rel=\"noopener noreferrer\">"
},
"link_privacy_start": {
"content": "<a target=\"_blank\" href=\"https://www.ghostery.com/about-ghostery/browser-extension-privacy-policy/\" rel=\"noopener noreferrer\">"
},
"link_terms_start": {
"content": "<a target=\"_blank\" href=\"https://www.ghostery.com/about-ghostery/ghostery-terms-and-conditions/\" rel=\"noopener noreferrer\">"
}
}
},
"ghostery_rewards": {
"message": "ghostery rewards"
}
@@ -33,9 +33,12 @@ const CreateAccountView = (props) => {
password,
passwordInvalidError,
passwordLengthError,
legalConsentChecked,
legalConsentNotCheckedError,
promotionsChecked,
handleInputChange,
handleCheckboxChange,
handleLegalConsentCheckboxChange,
handlePromotionsCheckboxChange,
handleSubmit,
} = props;

@@ -45,6 +48,9 @@ const CreateAccountView = (props) => {
const confirmInputClassNames = ClassNames('CreateAccountView__inputBox', {
error: confirmEmailError,
});
const legalConsentCheckboxInputLabelClassNames = ClassNames('CreateAccountView__inputLabel clickable', {
error: legalConsentNotCheckedError,
});
const passwordInputClassNames = ClassNames('CreateAccountView__inputBox', {
error: passwordInvalidError || passwordLengthError,
});
@@ -165,12 +171,25 @@ const CreateAccountView = (props) => {
)}
</div>
<div className="columns small-12 medium-5">
<div className="CreateAccountView__checkboxContainer CreateAccountView--marginBottom flex-container align-middle">
<div className="CreateAccountView__checkboxContainer CreateAccountView--marginBottom flex-container">
<ToggleCheckbox
checked={legalConsentChecked}
className="ToggleCheckbox--flush-left"
onChange={handleLegalConsentCheckboxChange}
/>
<span
className={legalConsentCheckboxInputLabelClassNames}
onClick={handleLegalConsentCheckboxChange}
dangerouslySetInnerHTML={{ __html: t('create_account_form_legal_consent_checkbox_label') }}
/>
</div>
<div className="CreateAccountView__checkboxContainer CreateAccountView--marginBottom flex-container">
<ToggleCheckbox
checked={promotionsChecked}
onChange={handleCheckboxChange}
className="ToggleCheckbox--flush-left"
onChange={handlePromotionsCheckboxChange}
/>
<span className="CreateAccountView__inputLabel clickable" onClick={handleCheckboxChange}>
<span className="CreateAccountView__inputLabel clickable" onClick={handlePromotionsCheckboxChange}>
{t('hub_create_account_checkbox_promotions')}
</span>
</div>
@@ -212,12 +231,14 @@ CreateAccountView.propTypes = {
confirmEmailError: PropTypes.bool.isRequired,
firstName: PropTypes.string.isRequired,
lastName: PropTypes.string.isRequired,
legalConsentChecked: PropTypes.bool.isRequired,
password: PropTypes.string.isRequired,
passwordInvalidError: PropTypes.bool.isRequired,
passwordLengthError: PropTypes.bool.isRequired,
promotionsChecked: PropTypes.bool.isRequired,
handleInputChange: PropTypes.func.isRequired,
handleCheckboxChange: PropTypes.func.isRequired,
handleLegalConsentCheckboxChange: PropTypes.func.isRequired,
handlePromotionsCheckboxChange: PropTypes.func.isRequired,
handleSubmit: PropTypes.func.isRequired,
};

@@ -11,6 +11,8 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0
*/

$color-create-account-form-error-red: #e74055;

// Create Account View
.CreateAccountView {
padding-top: 80px;
@@ -54,17 +56,17 @@
}
.CreateAccountView__inputBox.error {
margin-bottom: 8px;
border-color: #e74055;
border-color: $color-create-account-form-error-red;
}
.CreateAccountView__inputBox:focus {
// Foundation Overrides
box-shadow: none;
border-color: #4a4a4a;
border-color: $color-create-account-form-error-red;
}
.CreateAccountView__inputError {
font-size: 12;
line-height: 14px;
color: #e74055;
color: $color-create-account-form-error-red;
margin-bottom: 13px;
}
.CreateAccountView__link {
@@ -77,6 +79,13 @@
.CreateAccountView__button {
min-width: 180px;
}
.CreateAccountView__inputLabel {
flex-grow: 1; // ensure left-justify alignment in single column layout
padding-top: 10px; // align with checkbox top
}
.CreateAccountView__inputLabel.error{
color: $color-create-account-form-error-red;
}
@media only screen and (max-width: 740px) {
.CreateAccountView {
padding-top: 20px;
@@ -37,6 +37,8 @@ class CreateAccountViewContainer extends Component {
confirmEmailError: false,
firstName: '',
lastName: '',
legalConsentChecked: false,
legalConsentNotCheckedError: false,
password: '',
passwordInvalidError: false,
passwordLengthError: false,
@@ -93,11 +95,17 @@ class CreateAccountViewContainer extends Component {
}

/**
* Update input checkbox values by updating state.
* Update legal consetnt checkbox value by updating state
*/
_handleCheckboxChange = () => {
const promotionsChecked = !this.state.promotionsChecked;
this.setState({ promotionsChecked });
_handleLegalConsentCheckboxChange = () => {
this.setState(prevState => ({ legalConsentChecked: !prevState.legalConsentChecked }));
}

/**
* Update promotions checkbox value by updating state
*/
_handlePromotionsCheckboxChange = () => {
this.setState(prevState => ({ promotionsChecked: !prevState.promotionsChecked }));
}

/**
@@ -111,6 +119,7 @@ class CreateAccountViewContainer extends Component {
confirmEmail,
firstName,
lastName,
legalConsentChecked,
password,
promotionsChecked
} = this.state;
@@ -123,12 +132,13 @@ class CreateAccountViewContainer extends Component {
this.setState({
emailError: !emailIsValid,
confirmEmailError: !confirmIsValid,
legalConsentNotCheckedError: !legalConsentChecked,
passwordInvalidError: invalidChars,
passwordLengthError: invalidLength,
validateInput: true,
});

if (!emailIsValid || !confirmIsValid || !passwordIsValid) {
if (!emailIsValid || !confirmIsValid || !legalConsentChecked || !passwordIsValid) {
return;
}
this.props.actions.setToast({
@@ -166,6 +176,8 @@ class CreateAccountViewContainer extends Component {
confirmEmailError,
firstName,
lastName,
legalConsentChecked,
legalConsentNotCheckedError,
password,
passwordInvalidError,
passwordLengthError,
@@ -178,12 +190,15 @@ class CreateAccountViewContainer extends Component {
confirmEmailError,
firstName,
lastName,
legalConsentChecked,
legalConsentNotCheckedError,
password,
passwordInvalidError,
passwordLengthError,
promotionsChecked,
handleInputChange: this._handleInputChange,
handleCheckboxChange: this._handleCheckboxChange,
handleLegalConsentCheckboxChange: this._handleLegalConsentCheckboxChange,
handlePromotionsCheckboxChange: this._handlePromotionsCheckboxChange,
handleSubmit: this._handleCreateAccountAttempt
};
const signedInChildProps = {
@@ -145,11 +145,33 @@ exports[`app/hub/Views/CreateAccount component Snapshot tests with react-test-re
className="columns small-12 medium-5"
>
<div
className="CreateAccountView__checkboxContainer CreateAccountView--marginBottom flex-container align-middle"
className="CreateAccountView__checkboxContainer CreateAccountView--marginBottom flex-container"
>
<div
className="ToggleCheckbox ToggleCheckbox--active"
onClick={[Function]}
className="ToggleCheckbox ToggleCheckbox--flush-left"
>
<svg
viewBox="0 0 24 24"
>
<path
d="M19 5v14H5V5h14m0-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z"
/>
</svg>
</div>
<span
className="CreateAccountView__inputLabel clickable"
dangerouslySetInnerHTML={
Object {
"__html": "create_account_form_legal_consent_checkbox_label",
}
}
/>
</div>
<div
className="CreateAccountView__checkboxContainer CreateAccountView--marginBottom flex-container"
>
<div
className="ToggleCheckbox ToggleCheckbox--flush-left ToggleCheckbox--active"
>
<svg
viewBox="0 0 24 24"
@@ -161,7 +183,6 @@ exports[`app/hub/Views/CreateAccount component Snapshot tests with react-test-re
</div>
<span
className="CreateAccountView__inputLabel clickable"
onClick={[Function]}
>
hub_create_account_checkbox_promotions
</span>
@@ -388,11 +409,33 @@ exports[`app/hub/Views/CreateAccount component Snapshot tests with react-test-re
className="columns small-12 medium-5"
>
<div
className="CreateAccountView__checkboxContainer CreateAccountView--marginBottom flex-container align-middle"
className="CreateAccountView__checkboxContainer CreateAccountView--marginBottom flex-container"
>
<div
className="ToggleCheckbox"
onClick={[Function]}
className="ToggleCheckbox ToggleCheckbox--flush-left"
>
<svg
viewBox="0 0 24 24"
>
<path
d="M19 5v14H5V5h14m0-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z"
/>
</svg>
</div>
<span
className="CreateAccountView__inputLabel clickable"
dangerouslySetInnerHTML={
Object {
"__html": "create_account_form_legal_consent_checkbox_label",
}
}
/>
</div>
<div
className="CreateAccountView__checkboxContainer CreateAccountView--marginBottom flex-container"
>
<div
className="ToggleCheckbox ToggleCheckbox--flush-left"
>
<svg
viewBox="0 0 24 24"
@@ -404,7 +447,6 @@ exports[`app/hub/Views/CreateAccount component Snapshot tests with react-test-re
</div>
<span
className="CreateAccountView__inputLabel clickable"
onClick={[Function]}
>
hub_create_account_checkbox_promotions
</span>
@@ -32,6 +32,8 @@ class CreateAccount extends React.Component {
confirmEmailError: false,
firstName: '',
lastName: '',
legalConsentChecked: false,
legalConsentNotCheckedError: false,
password: '',
promotionsChecked: true,
loading: false,
@@ -67,7 +69,7 @@ class CreateAccount extends React.Component {
e.preventDefault();
this.setState({ loading: true }, () => {
const {
email, confirmEmail, firstName, lastName, password, promotionsChecked
email, confirmEmail, firstName, lastName, legalConsentChecked, password, promotionsChecked
} = this.state;
this.setState({ loading: true }, () => {
if (!validateEmail(email)) {
@@ -98,10 +100,18 @@ class CreateAccount extends React.Component {
}
return;
}
if (!legalConsentChecked) {
this.setState({
legalConsentNotCheckedError: true,
loading: false,
});
return;
}

this.setState({
emailError: false,
confirmEmailError: false,
legalConsentNotCheckedError: false,
passwordInvalidError: false,
passwordLengthError: false,
}, () => {
@@ -129,7 +139,7 @@ class CreateAccount extends React.Component {
*/
render() {
const {
email, confirmEmail, firstName, lastName, password, promotionsChecked, loading, emailError, confirmEmailError, passwordInvalidError, passwordLengthError
email, confirmEmail, firstName, lastName, password, promotionsChecked, legalConsentChecked, loading, emailError, confirmEmailError, legalConsentNotCheckedError, passwordInvalidError, passwordLengthError
} = this.state;
const buttonClasses = ClassNames('button ghostery-button', { loading });
return (
@@ -200,6 +210,15 @@ class CreateAccount extends React.Component {
</div>
</div>
</div>
<div className="row">
<div className="small-12 columns">
<div id="create-account-legal-consent-checkbox" className={(legalConsentNotCheckedError ? 'checkbox-error' : '')}>
<input id="legalConsentChecked" name="legalConsentChecked" type="checkbox" checked={legalConsentChecked} onChange={this.handleCheckboxChange} />
{/* eslint-disable-next-line jsx-a11y/label-has-associated-control */}
This conversation was marked as resolved by christophertino

This comment has been minimized.

@christophertino

christophertino Jul 17, 2019
Member

Do we still need this lint exclusion?

This comment has been minimized.

@wlycdgr

wlycdgr Jul 18, 2019
Author Member

Without it, the jsx-a11y linter plugin complains that "A form label must be associated with a control". It thinks the label is empty because we are using dangerouslySetInnerHTML attribute to set the text instead of inserting the string directly into the tag as with the promotions checkbox. But if we don't use dangerouslySetInnerHTML, the links in the string are displayed as plain text HTML.

This feels almost like a bug / unaccounted-for use case in the interaction between React and the linter plugin. Given that, I think this is a case where disabling the linter is the lesser of two evils, the other option being changing the checkbox implementation and probably making it more complicated and inconsistent with the promotions checkbox implementation. What do you think?

<label htmlFor="legalConsentChecked" dangerouslySetInnerHTML={{ __html: t('create_account_form_legal_consent_checkbox_label') }} />
</div>
</div>
</div>
<div className="row">
<div className="small-12 columns">
<div id="create-account-promotions">
@@ -210,9 +229,6 @@ class CreateAccount extends React.Component {
</div>
<div className="row">
<div className="small-12 columns">
<div id="create-account-privacy-container">
<p id="accept-privacy-label" dangerouslySetInnerHTML={{ __html: t('account_creation_privacy_statement') }} />
</div>
<div id="account-creation-buttons" className="row align-center">
<div className="small-6 columns text-center">
<Link to={(this.props.is_expert ? '/detail' : '/')} id="create-account-cancel" className="cancel button hollow">
ProTip! Use n and p to navigate between commits in a pull request.