summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAndrej Mihajlov <and@mullvad.net>2017-10-14 16:07:02 +0200
committerAndrej Mihajlov <and@mullvad.net>2017-10-19 14:16:38 +0200
commitabb86c88dc23096714c58785cc2393585d54ea27 (patch)
tree2e70147771e2f308c75bd40b9381d2d817b8f973
parent7798e9233661a759b5a6bd1c189b825c8fce2fbb (diff)
downloadmullvadvpn-abb86c88dc23096714c58785cc2393585d54ea27.tar.xz
mullvadvpn-abb86c88dc23096714c58785cc2393585d54ea27.zip
Add support form fields and validation
-rw-r--r--app/components/Support.css79
-rw-r--r--app/components/Support.js73
-rw-r--r--app/containers/SupportPage.js4
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) => {}
};
};