Skip to content
This repository was archived by the owner on Jan 7, 2020. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion email_app/app/actions/actionTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ const ACTION_TYPES = {
// Mail Inbox
PUSH_MAIL: 'PUSH_MAIL',
MAIL_PROCESSING: 'MAIL_PROCESSING',
CLEAR_MAIL_PROCESSING: 'CLEAR_MAIL_PROCESSING',
SET_ACTIVE_MAIL: 'SET_ACTIVE_MAIL',

CANCEL_COMPOSE: 'CANCEL_COMPOSE',
Expand Down
4 changes: 2 additions & 2 deletions email_app/app/actions/create_account_actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@ export const createAccount = (emailId) => {
};

export const createAccountError = (error) => ({
type: ACTION_TYPES.CREATE_ACCOUNT_ERROR,
error
type: ACTION_TYPES.CREATE_ACCOUNT,
payload: Promise.reject(error)
});
13 changes: 3 additions & 10 deletions email_app/app/actions/mail_actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@ export const sendEmail = (email, to) => {
let app = getState().initializer.app;
return dispatch({
type: ACTION_TYPES.MAIL_PROCESSING,
msg: 'Sending email...',
payload: storeEmail(app, email, to)
.then(() => dispatch(clearMailProcessing))
.then(() => Promise.resolve())
});
};
};
Expand All @@ -18,9 +17,8 @@ export const saveEmail = (account, key) => {
let app = getState().initializer.app;
return dispatch({
type: ACTION_TYPES.MAIL_PROCESSING,
msg: 'Saving email...',
payload: archiveEmail(app, account, key)
.then(() => dispatch(clearMailProcessing))
.then(() => Promise.resolve())
});
};
};
Expand All @@ -30,17 +28,12 @@ export const deleteEmail = (container, key) => {
let app = getState().initializer.app;
return dispatch({
type: ACTION_TYPES.MAIL_PROCESSING,
msg: 'Deleting email...',
payload: removeEmail(app, container, key)
.then(() => dispatch(clearMailProcessing))
.then(() => Promise.resolve())
});
};
};

export const clearMailProcessing = _ => ({
type: ACTION_TYPES.CLEAR_MAIL_PROCESSING
});

export const cancelCompose = _ => ({
type: ACTION_TYPES.CANCEL_COMPOSE
});
3 changes: 1 addition & 2 deletions email_app/app/components/create_account.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ export default class CreateAccount extends Component {

render() {
const { processing, error } = this.props;

return (
<div className="create-account">
<div className="create-account-b">
Expand All @@ -54,7 +53,7 @@ export default class CreateAccount extends Component {
<div className="alert">Email Id must be less than {CONSTANTS.EMAIL_ID_MAX_LENGTH} characters. (This is just a restriction in this tutorial)</div>
</div>
<div className="inp-btn-cnt">
<button type="submit" className="mdl-button mdl-js-button mdl-button--raised bg-primary" disabled={processing}>Create</button>
<button type="submit" className="mdl-button mdl-js-button mdl-button--raised bg-primary" disabled={processing.state}>Create</button>
</div>
</form>
<h4 className="error">{error.message}</h4>
Expand Down
70 changes: 37 additions & 33 deletions email_app/app/components/home.js
Original file line number Diff line number Diff line change
@@ -1,59 +1,63 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { Link, IndexLink } from 'react-router';
import Modal from 'react-modal';
import {ModalDialog, ModalPortal, ModalBackground} from 'react-modal-dialog';
import ReactSpinner from 'react-spinjs';
import className from 'classnames';
import pkg from '../../package.json';
import { CONSTANTS } from '../constants';

const modalStyles = {
content : {
top : '50%',
left : '50%',
right : 'auto',
bottom : 'auto',
marginRight : '-50%',
transform : 'translate(-50%, -50%)'
}
};

export default class Home extends Component {
constructor() {
super();
this.state = {
reconnecting: false
};

this.reconnect = this.reconnect.bind(this);
}

reconnect() {
this.setState({reconnecting: true});
return this.props.reconnectApplication()
.catch((err) => 'not reconnected')
.then(() => this.setState({reconnecting: false}))
const { reconnectApplication, accounts, refreshEmail } = this.props;
return reconnectApplication()
.then(() => refreshEmail(accounts),
(err) => 'failed reconnecting');
}

render() {
const { router } = this.context;
const { coreData, inboxSize, savedSize, network_status } = this.props;
const { coreData, inboxSize, savedSize, network_status, processing } = this.props;

const isNetworkDisconnected = (network_status !== CONSTANTS.NET_STATUS_CONNECTED);
const isModalOpen = processing.state || (network_status !== CONSTANTS.NET_STATUS_CONNECTED);
const spinnerBackgroundStyle = {
zIndex: '5',
position: 'fixed',
height: '100%',
width: '100%',
opacity: '0.75',
backgroundColor: 'white'
}

return (
<div className="home">
<Modal
isOpen={isNetworkDisconnected}
shouldCloseOnOverlayClick={false}
style={modalStyles}
contentLabel="Network connection lost"
>
<div className="text-center">
<div>The application hast lost network connection.</div><br />
<div>Make sure the network link is up before trying to reconnect.</div><br />
<button disabled={this.state.reconnecting} className="mdl-button mdl-js-button bg-primary" onClick={this.reconnect}>Reconnect</button>
</div>
</Modal>
{
isModalOpen &&
<ModalPortal>
{
processing.state ?
<div style={spinnerBackgroundStyle}>
<ReactSpinner />
</div>
:
<ModalBackground>
<ModalDialog>
<div className="text-center">
<div>The application hast lost network connection.</div><br />
<div>Make sure the network link is up before trying to reconnect.</div><br />
<button className="mdl-button mdl-js-button bg-primary" onClick={this.reconnect}>Reconnect</button>
</div>
</ModalDialog>
</ModalBackground>
}
</ModalPortal>
}

<div className="home-b">
<div className={className('float-btn', { hide: router.isActive('/compose_mail') })}>
Expand Down
1 change: 1 addition & 0 deletions email_app/app/components/initializer.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export default class Initializer extends Component {
refreshConfig() {
const { setInitializerTask, refreshConfig } = this.props;
setInitializerTask(MESSAGES.INITIALIZE.CHECK_CONFIGURATION);

return refreshConfig()
.then((_) => {
if (Object.keys(this.props.accounts).length > 0) {
Expand Down
160 changes: 70 additions & 90 deletions email_app/app/components/mail_list.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,27 +9,12 @@ export default class MailList extends Component {
super();
this.listColors = {};
this.activeType = null;
this.goBack = this.goBack.bind(this);
this.refreshEmail = this.refreshEmail.bind(this);
this.handleDeleteFromInbox = this.handleDeleteFromInbox.bind(this);
this.handleDeleteSaved = this.handleDeleteSaved.bind(this);
this.handleSave = this.handleSave.bind(this);
}

goBack() {
const { router } = this.context;

switch (this.activeType) {
case CONSTANTS.HOME_TABS.INBOX: {
return this.props.refreshEmail();
}
case CONSTANTS.HOME_TABS.SAVED: {
router.push('/home');
return router.push('/saved');
}
}
}

refreshEmail(account) {
this.props.refreshEmail(account)
.catch((error) => {
Expand Down Expand Up @@ -76,87 +61,82 @@ export default class MailList extends Component {

render() {
const self = this;
const { processing, coreData, error, inboxSize, inbox, savedSize, saved } = this.props;
const { coreData, error, inboxSize, inbox, savedSize, saved } = this.props;
let container = null;

if (processing) {
container = <li className="mdl-card">Loading...</li>
} else if (Object.keys(error).length > 0) {
container = <li className="error">Error in fetching emails!</li>
} else {
if (inbox) {
this.activeType = CONSTANTS.HOME_TABS.INBOX;
container = (
<div>
{
inboxSize === 0 ? <li className="mdl-card" title="No data in inbox mutableData">Inbox empty</li> : Object.keys(coreData.inbox).map((key) => {
let mail = coreData.inbox[key];
if (!self.listColors.hasOwnProperty(mail.from)) {
self.listColors[mail.from] = `bg-color-${Object.keys(self.listColors).length % 10}`
}
return (
<li className="mdl-card" key={key}>
<div className="icon">
<span className={self.listColors[mail.from]}>{mail.from[0]}</span>
</div>
<div className="cntx">
<h3 className="from">{mail.from}</h3>
<h4 className="date">{dateformat(new Date(mail.time), CONSTANTS.DATE_FORMAT)}</h4>
<p className="subject">{mail.subject}</p>
<p className="context">{mail.body}</p>
if (inbox) {
this.activeType = CONSTANTS.HOME_TABS.INBOX;
container = (
<div>
{
inboxSize === 0 ? <li className="mdl-card" title="No data in inbox mutableData">Inbox empty</li> : Object.keys(coreData.inbox).map((key) => {
let mail = coreData.inbox[key];
if (!self.listColors.hasOwnProperty(mail.from)) {
self.listColors[mail.from] = `bg-color-${Object.keys(self.listColors).length % 10}`
}
return (
<li className="mdl-card" key={key}>
<div className="icon">
<span className={self.listColors[mail.from]}>{mail.from[0]}</span>
</div>
<div className="cntx">
<h3 className="from">{mail.from}</h3>
<h4 className="date">{dateformat(new Date(mail.time), CONSTANTS.DATE_FORMAT)}</h4>
<p className="subject">{mail.subject}</p>
<p className="context">{mail.body}</p>
</div>
<div className="opt">
<div className="opt-i">
<button className="mdl-button mdl-js-button mdl-button--icon" name="add" onClick={this.handleSave}><i className="material-icons" data-index={key}>save</i></button>
</div>
<div className="opt">
<div className="opt-i">
<button className="mdl-button mdl-js-button mdl-button--icon" name="add" onClick={this.handleSave}><i className="material-icons" data-index={key}>save</i></button>
</div>
<div className="opt-i">
<button className="mdl-button mdl-js-button mdl-button--icon" name="delete" onClick={this.handleDeleteFromInbox}><i className="material-icons" data-index={key}>delete</i></button>
</div>
<div className="opt-i">
<button className="mdl-button mdl-js-button mdl-button--icon" name="delete" onClick={this.handleDeleteFromInbox}><i className="material-icons" data-index={key}>delete</i></button>
</div>
</li>
)
})
}
</div>
);
}
if (saved) {
this.activeType = CONSTANTS.HOME_TABS.SAVED;
container = (
<div>
{
savedSize === 0 ? <li className="mdl-card">Saved empty</li> : Object.keys(coreData.saved).map((key) => {
let mail = coreData.saved[key];
if (!mail) {
return;
}
if (!self.listColors.hasOwnProperty(mail.from)) {
self.listColors[mail.from] = `bg-color-${Object.keys(self.listColors).length % 10}`
}
return (
<li className="mdl-card" key={key}>
<div className="icon">
<span className={this.listColors[mail.from]}>{mail.from[0]}</span>
</div>
<div className="cntx">
<h3 className="from">{mail.from}</h3>
<h4 className="date">{dateformat(new Date(mail.time), CONSTANTS.DATE_FORMAT)}</h4>
<p className="subject">{mail.subject}</p>
<p className="context">{mail.body}</p>
</div>
<div className="opt">
<div className="opt-i">
<button className="mdl-button mdl-js-button mdl-button--icon" name="delete" onClick={this.handleDeleteSaved}><i className="material-icons" data-index={key}>delete</i></button>
</div>
</div>
</li>
)
})
}
</div>
);
}
if (saved) {
this.activeType = CONSTANTS.HOME_TABS.SAVED;
container = (
<div>
{
savedSize === 0 ? <li className="mdl-card">Saved empty</li> : Object.keys(coreData.saved).map((key) => {
let mail = coreData.saved[key];
if (!mail) {
return;
}
if (!self.listColors.hasOwnProperty(mail.from)) {
self.listColors[mail.from] = `bg-color-${Object.keys(self.listColors).length % 10}`
}
return (
<li className="mdl-card" key={key}>
<div className="icon">
<span className={this.listColors[mail.from]}>{mail.from[0]}</span>
</div>
<div className="cntx">
<h3 className="from">{mail.from}</h3>
<h4 className="date">{dateformat(new Date(mail.time), CONSTANTS.DATE_FORMAT)}</h4>
<p className="subject">{mail.subject}</p>
<p className="context">{mail.body}</p>
</div>
<div className="opt">
<div className="opt-i">
<button className="mdl-button mdl-js-button mdl-button--icon" name="delete" onClick={this.handleDeleteSaved}><i className="material-icons" data-index={key}>delete</i></button>
</div>
</li>
)
})
}
</div>
);
}
</div>
</li>
)
})
}
</div>
);
}

return (
<ul className="mail-list-item mdl-list">
{container}
Expand Down
6 changes: 2 additions & 4 deletions email_app/app/containers/compose_mail_container.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
import { connect } from 'react-redux';
import ComposeMail from '../components/compose_mail';
import { cancelCompose, sendEmail, clearMailProcessing } from '../actions/mail_actions';
import { cancelCompose, sendEmail } from '../actions/mail_actions';

const mapStateToProps = state => {
return {
app: state.initializer.app,
fromMail: state.initializer.coreData.id,
error: state.mail.error,
processing: state.mail.processing
error: state.mail.error
};
};

const mapDispatchToProps = dispatch => {
return {
sendEmail: (email, to) => (dispatch(sendEmail(email, to))),
clearMailProcessing: _ => (dispatch(clearMailProcessing())),
cancelCompose: _ => dispatch(cancelCompose())
};
};
Expand Down
2 changes: 1 addition & 1 deletion email_app/app/containers/create_account_container.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { storeNewAccount } from '../actions/initializer_actions';
const mapStateToProps = state => {
return {
error: state.createAccount.error,
processing: state.createAccount.processing,
processing: state.initializer.processing,
newAccount: state.createAccount.newAccount,
coreData: state.initializer.coreData
};
Expand Down
Loading