From 2fdfc4ed731c6c82b7d5ebf995eb114b416a53d8 Mon Sep 17 00:00:00 2001 From: elijah Date: Thu, 6 Oct 2016 22:22:32 -0700 Subject: [feat] ui - email status section --- ui/app/components/main_panel/email_section.js | 97 +++++++++++++++++++-- ui/app/components/main_panel/imap_button.js | 121 ++++++++++++++++++++++++++ ui/app/components/main_panel/main_panel.less | 1 + ui/app/css/common.css | 28 +++++- ui/app/img/error.svg | 107 +++++++++++++++++++++++ 5 files changed, 346 insertions(+), 8 deletions(-) create mode 100644 ui/app/components/main_panel/imap_button.js create mode 100644 ui/app/img/error.svg (limited to 'ui') diff --git a/ui/app/components/main_panel/email_section.js b/ui/app/components/main_panel/email_section.js index a3ff11c..2bb5865 100644 --- a/ui/app/components/main_panel/email_section.js +++ b/ui/app/components/main_panel/email_section.js @@ -1,10 +1,57 @@ import React from 'react' -//import { Button, Glyphicon, Alert } from 'react-bootstrap' +import { Button, Glyphicon, Alert } from 'react-bootstrap' + import SectionLayout from './section_layout' +import IMAPButton from './imap_button' + import Account from 'models/account' import Spinner from 'components/spinner' import bitmask from 'lib/bitmask' +const GENERAL_NOTICES = [ + "KEYMANAGER_KEY_FOUND", // (address) + "KEYMANAGER_KEY_NOT_FOUND", // (address) + "KEYMANAGER_LOOKING_FOR_KEY", // (address) + "KEYMANAGER_DONE_UPLOADING_KEYS", // (address) + + "SMTP_START_ENCRYPT_AND_SIGN", // (from_addr) + "SMTP_END_ENCRYPT_AND_SIGN", // (from_addr) + "SMTP_START_SIGN", // (from_addr) + "SMTP_END_SIGN", // (from_addr) + "SMTP_SEND_MESSAGE_START", // (from_addr) + "SMTP_SEND_MESSAGE_SUCCESS" // (from_addr) +] + +const ACCOUNT_NOTICES = [ + "IMAP_CLIENT_LOGIN", // (username) + + "MAIL_FETCHED_INCOMING", // (userid) + "MAIL_MSG_DECRYPTED", // (userid) + "MAIL_MSG_DELETED_INCOMING", // (userid) + "MAIL_MSG_PROCESSING", // (userid) + "MAIL_MSG_SAVED_LOCALLY", // (userid) + + "SMTP_RECIPIENT_ACCEPTED_ENCRYPTED", // (userid, dest) + "SMTP_RECIPIENT_ACCEPTED_UNENCRYPTED", // (userid, dest) + "SMTP_RECIPIENT_REJECTED", // (userid, dest) + "SMTP_SEND_MESSAGE_ERROR" // (userid, dest) +] + +const STATUSES = [ + "KEYMANAGER_FINISHED_KEY_GENERATION", // (address) + "KEYMANAGER_STARTED_KEY_GENERATION", // (address) + "SMTP_SERVICE_STARTED", + "MAIL_UNREAD_MESSAGES", // (userid, number) + "IMAP_SERVICE_STARTED" +] + +const STATUS_ERRORS = [ + "IMAP_SERVICE_FAILED_TO_START", + "IMAP_UNHANDLED_ERROR", + "SMTP_SERVICE_FAILED_TO_START", + "SMTP_CONNECTION_LOST", // (userid, dest) +] + export default class EmailSection extends React.Component { static get defaultProps() {return{ @@ -14,17 +61,46 @@ export default class EmailSection extends React.Component { constructor(props) { super(props) this.state = { - status: null + status: 'unknown', // on, off, unknown, wait, disabled, error + messages: [], + expanded: true } + this.expand = this.expand.bind(this) this.openKeys = this.openKeys.bind(this) this.openApp = this.openApp.bind(this) this.openPrefs = this.openPrefs.bind(this) + this.logEvent = this.logEvent.bind(this) + } + + componentWillMount() { + let events = [].concat(GENERAL_NOTICES, ACCOUNT_NOTICES, STATUSES, STATUS_ERRORS) + for (let event of events) { + bitmask.events.register(event, this.logEvent) + } + bitmask.mail.status().then(status => { + // either 'running' or 'disabled' + let newstatus = 'error' + if (status['mail'] == 'running') { + newstatus = 'on' + } else if (status['mail'] == 'disabled') { + newstatus = 'disabled' + } + this.setState({status: newstatus}) + }) + } + + logEvent(event, msg) { + console.log("EVENT: " + event, msg) } openKeys() {} openApp() {} openPrefs() {} + expand() { + this.setState({expanded: !this.state.expanded}) + } + render () { //let message = null //if (this.state.error) { @@ -34,13 +110,22 @@ export default class EmailSection extends React.Component { // ) //} let button = null - if (this.state.status == 'ready') { + let body = null + let header =

Mail

+ if (this.state.status == 'on') { button = } + if (this.state.status == 'disabled') { + header =

Mail Disabled

+ } + if (this.state.expanded) { + body = ( + + ) + } return ( - -

inbox:

-
+ ) } } diff --git a/ui/app/components/main_panel/imap_button.js b/ui/app/components/main_panel/imap_button.js new file mode 100644 index 0000000..98d8bad --- /dev/null +++ b/ui/app/components/main_panel/imap_button.js @@ -0,0 +1,121 @@ +// +// Button to show details for configuring mail clients +// + +import React from 'react' +import { Modal, Form, FormGroup, ControlLabel, FormControl, Col, Label, Button} from 'react-bootstrap' +import Account from 'models/account' +import bitmask from 'lib/bitmask' + +export default class IMAPButton extends React.Component { + + static get defaultProps() {return{ + account: null, + title: "Connect Mail Client" + }} + + constructor(props) { + super(props) + this.state = { + showModal: false, + imapPort: '1984', + smtpPort: '2013', + token: '' + } + this.onClick = this.onClick.bind(this) + this.onClose = this.onClose.bind(this) + } + + onClose() { + this.setState({showModal: false}) + } + + onClick() { + if (!this.state.token) { + bitmask.mail.get_token().then(response => { + if (response.user == this.props.account.address) { + this.setState({token: response.token}) + } + }) + } + this.setState({showModal: true}) + } + + componentWillMount() {} + + // don't allow fields to be changed + onChange() {} + + render () { + let rowStyle = {height: '30px'} // to match bootstrap's input element height + let form = null + let modal = null + + if (this.state.showModal) { + form = ( +
+

+ You can use any application that supports IMAP to read and send + email through Bitmask. +

+

Configuration for Thunderbird

+

+ For Thunderbird, you can use the Bitmask extension. Search for + "Bitmask" in Thunderbird's add-on manager. +

+

Configuration for other mail clients

+

+ Alternately, configure your mail client with the following options: +

+ + Username + + + + + + Password + + + + + + IMAP + +
+ localhost +     + {this.state.imapPort} +
+ +
+ + SMTP + +
+ localhost +     + {this.state.smtpPort} +
+ +
+
+ ) + modal = ( + + + {this.props.title} + + + {form} + + + ) + } + + return ( + + ) + } + +} diff --git a/ui/app/components/main_panel/main_panel.less b/ui/app/components/main_panel/main_panel.less index 2e97913..7383a6c 100644 --- a/ui/app/components/main_panel/main_panel.less +++ b/ui/app/components/main_panel/main_panel.less @@ -229,6 +229,7 @@ } .icon { padding-right: @section-padding; + height: @icon-size; img { width: @icon-size; height: @icon-size; diff --git a/ui/app/css/common.css b/ui/app/css/common.css index fcae7fa..a0d2c35 100644 --- a/ui/app/css/common.css +++ b/ui/app/css/common.css @@ -63,15 +63,38 @@ body { */ .center-container { - display: -webkit-flex; display: flex; + -webkit-flex-flow: row nowrap; flex-flow: row nowrap; + -webkit-justify-content: center; justify-content: center; + + -webkit-align-content: center; + align-content: center; + + -webkit-align-items: center; + align-items: center; +} + +.center-vertical { + display: -webkit-flex; + display: flex; + + -webkit-flex-direction: row; + flex-direction: row; + + -webkit-flex-flow: row nowrap; + flex-flow: row nowrap; + + -webkit-justify-content: flex-start; + justify-content: flex-start; + -webkit-align-content: center; align-content: center; + -webkit-align-items: center; align-items: center; } @@ -84,7 +107,8 @@ body { width: 100%; } -.center-container .center-item { +.center-container .center-item, +.center-vertical .center-item { -webkit-flex: 0 1 auto; flex: 0 1 auto; } diff --git a/ui/app/img/error.svg b/ui/app/img/error.svg new file mode 100644 index 0000000..69024a4 --- /dev/null +++ b/ui/app/img/error.svg @@ -0,0 +1,107 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + -- cgit v1.2.3