diff options
| author | Andrej Mihajlov <and@mullvad.net> | 2017-10-14 16:07:02 +0200 |
|---|---|---|
| committer | Andrej Mihajlov <and@mullvad.net> | 2017-10-19 14:16:38 +0200 |
| commit | abb86c88dc23096714c58785cc2393585d54ea27 (patch) | |
| tree | 2e70147771e2f308c75bd40b9381d2d817b8f973 | |
| parent | 7798e9233661a759b5a6bd1c189b825c8fce2fbb (diff) | |
| download | mullvadvpn-abb86c88dc23096714c58785cc2393585d54ea27.tar.xz mullvadvpn-abb86c88dc23096714c58785cc2393585d54ea27.zip | |
Add support form fields and validation
| -rw-r--r-- | app/components/Support.css | 79 | ||||
| -rw-r--r-- | app/components/Support.js | 73 | ||||
| -rw-r--r-- | app/containers/SupportPage.js | 4 |
3 files changed, 151 insertions, 5 deletions
diff --git a/app/components/Support.css b/app/components/Support.css index a5aedd073d..2870c75533 100644 --- a/app/components/Support.css +++ b/app/components/Support.css @@ -45,6 +45,15 @@ font-weight: 900; line-height: 40px; color: #FFFFFF; + margin-bottom: 16px; +} + +.support__subtitle { + font-family: "Open Sans"; + font-size: 13px; + font-weight: 600; + line-height: normal; + color: rgba(255,255,255,0.8); } .support__content { @@ -54,6 +63,72 @@ justify-content: space-between; } -.support__main { - margin-bottom: 24px; +.support__form { + display: flex; + flex: 1 1 auto; + flex-direction: column; +} + +.support__form-row { + padding: 0 24px; +} + +.support__form-row + .support__form-row { + margin-top: 16px; +} + +.support__form-row--description { + display: flex; + flex: 1 1 auto; +} + +.support__form-email { + width: 100%; + border-radius: 8px; + border: 0; + overflow: hidden; + padding: 10px 12px 12px 12px; + font-family: "Open Sans"; + font-size: 13px; + font-weight: 600; + line-height: 26px; + color: #294D73; + background-color: #fff; +} + +.support__form-email::-webkit-input-placeholder { + color: rgba(41,77,115,0.4); +} + +.support__form-description-scroll-wrap { + width: 100%; + display: flex; + border-radius: 8px; + overflow: hidden; +} + +.support__form-description { + width: 100%; + border: 0; + overflow-y: scroll; + resize: none; + padding: 10px 12px 12px 12px; + font-family: "Open Sans"; + font-size: 13px; + font-weight: 600; + line-height: 1.4em; + color: #294D73; + background-color: #fff; +} + +.support__form-description::-webkit-input-placeholder { + color: rgba(41,77,115,0.4); +} + +.support__footer { + padding: 24px; +} + +.support__footer .button + .button { + margin-top: 16px; }
\ No newline at end of file diff --git a/app/components/Support.js b/app/components/Support.js index 8564c8e51c..7f15ac5f45 100644 --- a/app/components/Support.js +++ b/app/components/Support.js @@ -1,13 +1,50 @@ // @flow import React, { Component } from 'react'; import { Layout, Container, Header } from './Layout'; +import ExternalLinkSVG from '../assets/images/icon-extLink.svg'; +export type SupportReport = { + email: string, + description: string +}; + +export type SupportState = SupportReport; export type SupportProps = { onClose: () => void; + onViewLogs: () => void; + onSend: (report: SupportReport) => void; }; export default class Support extends Component { props: SupportProps; + state: SupportState = { + email: '', + description: '' + } + + validate() { + return this.state.description.trim().length > 0; + } + + onChangeEmail = (e: Event) => { + const input = e.target; + if(!(input instanceof HTMLInputElement)) { + throw new Error('input must be an instance of HTMLInputElement'); + } + this.setState({ email: input.value }); + } + + onChangeDescription = (e: Event) => { + const input = e.target; + if(!(input instanceof HTMLTextAreaElement)) { + throw new Error('input must be an instance of HTMLTextAreaElement'); + } + this.setState({ description: input.value }); + } + + onSend = () => { + this.props.onSend(this.state); + } render() { return ( @@ -22,11 +59,43 @@ export default class Support extends Component { <div className="support__container"> <div className="support__header"> - <h2 className="support__title">Support</h2> + <h2 className="support__title">Contact support</h2> + <div className="support__subtitle"> + { `To help you more effectively, your app's log file will be attached to this message. + Your data will remain secure and private, as it is encrypted and anonymised before sending.` } + </div> </div> <div className="support__content"> - <div className="support__main"> + <div className="support__form"> + <div className="support__form-row"> + <input className="support__form-email" + type="email" + placeholder="Your email" + value={ this.state.email } + onChange={ this.onChangeEmail } + autoFocus={ true } /> + </div> + <div className="support__form-row support__form-row--description"> + <div className="support__form-description-scroll-wrap"> + <textarea className="support__form-description" + placeholder="Describe your problem" + value={ this.state.description } + onChange={ this.onChangeDescription } /> + </div> + </div> + <div className="support__footer"> + <button type="button" + className="button button--primary" + onClick={ this.props.onViewLogs }> + <span className="support__form-view-logs button-label">View app logs</span> + <ExternalLinkSVG className="button-icon button-icon--16" /> + </button> + <button type="button" + className="support__form-send button button--positive" + disabled={ !this.validate() } + onClick={ this.onSend }>Send</button> + </div> </div> </div> diff --git a/app/containers/SupportPage.js b/app/containers/SupportPage.js index c35aa50ade..fe579395f6 100644 --- a/app/containers/SupportPage.js +++ b/app/containers/SupportPage.js @@ -8,7 +8,9 @@ const mapStateToProps = (state) => { const mapDispatchToProps = (dispatch, _props) => { return { - onClose: () => dispatch(push('/settings')) + onClose: () => dispatch(push('/settings')), + onViewLogs: () => {}, + onSend: (_report) => {} }; }; |
