From 4d3d41c1ea2ba77391d1e82a22e8f581acec94e1 Mon Sep 17 00:00:00 2001 From: Brian Peiris <brianpeiris@gmail.com> Date: Tue, 10 Apr 2018 19:22:36 -0700 Subject: [PATCH] add terms checkbox to profile entry panel --- src/assets/stylesheets/entry.scss | 28 ++++-------- src/assets/stylesheets/profile.scss | 29 +++++++++++++ src/assets/stylesheets/shared.scss | 22 +++++++++- src/assets/translations.data.json | 6 +++ src/react-components/profile-entry-panel.js | 47 +++++++++++++++++---- src/react-components/ui-root.js | 2 +- src/storage/store.js | 1 + src/utils/identity.js | 1 + 8 files changed, 105 insertions(+), 31 deletions(-) diff --git a/src/assets/stylesheets/entry.scss b/src/assets/stylesheets/entry.scss index 04d1bbfad..abed31db3 100644 --- a/src/assets/stylesheets/entry.scss +++ b/src/assets/stylesheets/entry.scss @@ -20,28 +20,18 @@ justify-content: center; &__screen-sharing { - font-size: 1.4em; - margin-left: 2.95em; - margin-top: 0.6em; - } + font-size: 1.4em; + margin-left: 2.95em; + margin-top: 0.6em; - &__screen-sharing-checkbox { - appearance: none; - -moz-appearance: none; - -webkit-appearance: none; - width: 2em; - height: 2em; - border: 3px solid white; - border-radius: 9px; - vertical-align: sub; - margin: 0 0.6em + &__checkbox { + @extend %checkbox; + } + &__checkbox:checked { + @extend %checkbox-checked; + } } - &__screen-sharing-checkbox:checked { - border: 9px double white; - outline: 9px solid white; - outline-offset: -18px; - } &__secondary { width: 100%; diff --git a/src/assets/stylesheets/profile.scss b/src/assets/stylesheets/profile.scss index 53af72ede..c0e48ffd2 100644 --- a/src/assets/stylesheets/profile.scss +++ b/src/assets/stylesheets/profile.scss @@ -41,6 +41,10 @@ color: $grey-text; } + &__display-name-label { + font-size: 1.2em; + margin-right: 0.5em; + } &__form-field-text { @extend %rounded-border; @extend %default-font; @@ -54,6 +58,31 @@ margin: 0.5em 0; } + &__terms { + margin-bottom: 16px; + + &__checkbox { + @extend %checkbox; + vertical-align: unset; + } + &__checkbox:checked { + @extend %checkbox-checked; + } + + &__text { + display: inline-block; + max-width: 20em; + } + + &__link { + color: white; + } + + &__link:visited { + color: grey; + } + } + &__form-submit { @extend %bottom-button; margin: 0; diff --git a/src/assets/stylesheets/shared.scss b/src/assets/stylesheets/shared.scss index 796dc23b8..f95994358 100644 --- a/src/assets/stylesheets/shared.scss +++ b/src/assets/stylesheets/shared.scss @@ -23,8 +23,8 @@ $darker-grey: rgba(64, 64, 64, 1.0); margin-top: auto; margin-bottom: 30px; cursor: pointer; - border: 4px solid white; - border-radius: 16px; + border: 3px solid white; + border-radius: 14px; padding: 12px; background: none; color: white; @@ -48,3 +48,21 @@ $darker-grey: rgba(64, 64, 64, 1.0); border: none; font-size: 64pt; } + +%checkbox { + appearance: none; + -moz-appearance: none; + -webkit-appearance: none; + width: 2em; + height: 2em; + border: 3px solid white; + border-radius: 9px; + vertical-align: sub; + margin: 0 0.6em +} + +%checkbox-checked { + border: 9px double white; + outline: 9px solid white; + outline-offset: -18px; +} diff --git a/src/assets/translations.data.json b/src/assets/translations.data.json index 9201daed2..1b9844c8a 100644 --- a/src/assets/translations.data.json +++ b/src/assets/translations.data.json @@ -14,8 +14,14 @@ "entry.daydream-via-chrome": "Using Google Chrome", "entry.enable-screen-sharing": "Share my desktop", "profile.save": "SAVE", + "profile.display_name.label": "Display name:", "profile.display_name.validation_warning": "Alphanumerics and hyphens. At least 3 characters, no more than 32", "profile.header": "Your identity", + "profile.terms.prefix": "I confirm that I am over the age of 13 and agree to the", + "profile.terms.privacy": "privacy policy", + "profile.terms.conjunction": "and", + "profile.terms.tou": "terms of use", + "profile.terms.suffix": ".", "profile.avatar-selector.loading": "Loading Avatars...", "audio.title": "Test your audio", "audio.subtitle-desktop": "Confirm HMD speaker output", diff --git a/src/react-components/profile-entry-panel.js b/src/react-components/profile-entry-panel.js index af1c7382f..96016e0a5 100644 --- a/src/react-components/profile-entry-panel.js +++ b/src/react-components/profile-entry-panel.js @@ -28,9 +28,11 @@ class ProfileEntryPanel extends Component { saveStateAndFinish = e => { e.preventDefault(); + if (!this.state.has_agreed_to_terms) return; this.props.store.update({ profile: { has_saved_profile: true, + has_agreed_to_terms: true, display_name: this.state.display_name, avatar_id: this.state.avatar_id } @@ -75,20 +77,47 @@ class ProfileEntryPanel extends Component { <div className="profile-entry__subtitle"> <FormattedMessage id="profile.header" /> </div> - <input - className="profile-entry__form-field-text" - value={this.state.display_name} - onChange={e => this.setState({ display_name: e.target.value })} - required - pattern={SCHEMA.definitions.profile.properties.display_name.pattern} - title={formatMessage({ id: "profile.display_name.validation_warning" })} - ref={inp => (this.nameInput = inp)} - /> + <label> + <span className="profile-entry__display-name-label"> + <FormattedMessage id="profile.display_name.label" /> + </span> + <input + className="profile-entry__form-field-text" + value={this.state.display_name} + onChange={e => this.setState({ display_name: e.target.value })} + required + pattern={SCHEMA.definitions.profile.properties.display_name.pattern} + title={formatMessage({ id: "profile.display_name.validation_warning" })} + ref={inp => (this.nameInput = inp)} + /> + </label> <iframe className="profile-entry__avatar-selector" src={`/${this.props.htmlPrefix}avatar-selector.html#avatar_id=${this.state.avatar_id}`} ref={ifr => (this.avatarSelector = ifr)} /> + {!this.props.store.state.profile.has_agreed_to_terms && ( + <label className="profile-entry__terms"> + <input + className="profile-entry__terms__checkbox" + type="checkbox" + required + value={this.state.has_agreed_to_terms} + onChange={e => this.setState({ has_agreed_to_terms: e.target.value })} + /> + <span className="profile-entry__terms__text"> + <FormattedMessage id="profile.terms.prefix" />{" "} + <a className="profile-entry__terms__link" target="_blank" href="/privacy"> + <FormattedMessage id="profile.terms.privacy" /> + </a>{" "} + <FormattedMessage id="profile.terms.conjunction" />{" "} + <a className="profile-entry__terms__link" target="_blank" href="/terms"> + <FormattedMessage id="profile.terms.tou" /> + </a> + <FormattedMessage id="profile.terms.suffix" /> + </span> + </label> + )} <input className="profile-entry__form-submit" type="submit" value={formatMessage({ id: "profile.save" })} /> </div> </form> diff --git a/src/react-components/ui-root.js b/src/react-components/ui-root.js index f0d364dbc..07488ced3 100644 --- a/src/react-components/ui-root.js +++ b/src/react-components/ui-root.js @@ -539,7 +539,7 @@ class UIRoot extends Component { /firefox/i.test(navigator.userAgent) && ( <label className="entry-panel__screen-sharing"> <input - className="entry-panel__screen-sharing-checkbox" + className="entry-panel__screen-sharing__checkbox" type="checkbox" value={this.state.shareScreen} onChange={this.setStateAndRequestScreen} diff --git a/src/storage/store.js b/src/storage/store.js index b9f7366ab..0e76ee5a0 100644 --- a/src/storage/store.js +++ b/src/storage/store.js @@ -17,6 +17,7 @@ export const SCHEMA = { additionalProperties: false, properties: { has_saved_profile: { type: "boolean" }, + has_agreed_to_terms: { type: "boolean" }, display_name: { type: "string", pattern: "^[A-Za-z0-9-]{3,32}$" }, avatar_id: { type: "string" } } diff --git a/src/utils/identity.js b/src/utils/identity.js index e4d79896c..917553d7c 100644 --- a/src/utils/identity.js +++ b/src/utils/identity.js @@ -172,6 +172,7 @@ export const avatarIds = avatars.map(av => av.id); export function generateDefaultProfile() { const name = selectRandom(names); return { + has_agreed_to_terms: false, has_saved_profile: false, display_name: name.replace(/^./, name[0].toUpperCase()), avatar_id: selectRandom(avatarIds) -- GitLab