diff options
Diffstat (limited to 'front/odiparpack/app/components/Email')
| -rw-r--r-- | front/odiparpack/app/components/Email/ComposeEmail.js | 65 | ||||
| -rw-r--r-- | front/odiparpack/app/components/Email/ComposeEmailForm.js | 262 | ||||
| -rw-r--r-- | front/odiparpack/app/components/Email/EmailHeader.js | 49 | ||||
| -rw-r--r-- | front/odiparpack/app/components/Email/EmailList.js | 314 | ||||
| -rw-r--r-- | front/odiparpack/app/components/Email/EmailSidebar.js | 162 | ||||
| -rw-r--r-- | front/odiparpack/app/components/Email/email-jss.js | 238 |
6 files changed, 1090 insertions, 0 deletions
diff --git a/front/odiparpack/app/components/Email/ComposeEmail.js b/front/odiparpack/app/components/Email/ComposeEmail.js new file mode 100644 index 0000000..8d06ebd --- /dev/null +++ b/front/odiparpack/app/components/Email/ComposeEmail.js @@ -0,0 +1,65 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { withStyles } from '@material-ui/core/styles'; +import Add from '@material-ui/icons/Add'; +import { Fab, Tooltip } from '@material-ui/core'; +import ComposeEmailForm from './ComposeEmailForm'; +import FloatingPanel from '../Panel/FloatingPanel'; +import styles from './email-jss'; + + +class ComposeEmail extends React.Component { + render() { + const { + classes, + open, + closeForm, + sendEmail, + to, + subject, + validMail, + inputChange, + compose + } = this.props; + const branch = ''; + return ( + <div> + <Tooltip title="Compose Email"> + <Fab color="secondary" onClick={() => compose()} className={classes.addBtn}> + <Add /> + </Fab> + </Tooltip> + <FloatingPanel + openForm={open} + branch={branch} + closeForm={closeForm} + title="Compose Email" + extraSize + > + <ComposeEmailForm + to={to} + subject={subject} + validMail={validMail} + sendEmail={sendEmail} + closeForm={closeForm} + inputChange={inputChange} + /> + </FloatingPanel> + </div> + ); + } +} + +ComposeEmail.propTypes = { + classes: PropTypes.object.isRequired, + open: PropTypes.bool.isRequired, + to: PropTypes.string.isRequired, + subject: PropTypes.string.isRequired, + validMail: PropTypes.string.isRequired, + compose: PropTypes.func.isRequired, + closeForm: PropTypes.func.isRequired, + sendEmail: PropTypes.func.isRequired, + inputChange: PropTypes.func.isRequired, +}; + +export default withStyles(styles)(ComposeEmail); diff --git a/front/odiparpack/app/components/Email/ComposeEmailForm.js b/front/odiparpack/app/components/Email/ComposeEmailForm.js new file mode 100644 index 0000000..3620d4d --- /dev/null +++ b/front/odiparpack/app/components/Email/ComposeEmailForm.js @@ -0,0 +1,262 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { Editor } from 'react-draft-wysiwyg'; +import { convertFromRaw, EditorState, convertToRaw } from 'draft-js'; +import draftToHtml from 'draftjs-to-html'; +import Dropzone from 'react-dropzone'; +import { withStyles } from '@material-ui/core/styles'; +import TextField from '@material-ui/core/TextField'; +import Attachment from '@material-ui/icons/Attachment'; +import FileIcon from '@material-ui/icons/Description'; +import ActionDelete from '@material-ui/icons/Delete'; +import Send from '@material-ui/icons/Send'; +import EditorStyle from 'ba-styles/TextEditor.scss'; +import css from 'ba-styles/Form.scss'; +import 'ba-styles/vendors/react-draft-wysiwyg/react-draft-wysiwyg.css'; +import { Button, Grid, Typography, Snackbar, IconButton } from '@material-ui/core'; +import isImage from '../Forms/helpers/helpers.js'; +import styles from './email-jss'; + + +const content = { + blocks: [{ + key: '637gr', + text: 'Lorem ipsum dolor sit amet 😀', + type: 'unstyled', + depth: 0, + inlineStyleRanges: [], + entityRanges: [], + data: {} + }], + entityMap: {} +}; + +class ComposeEmailForm extends React.Component { + constructor(props) { + super(props); + const contentBlock = convertFromRaw(content); + if (contentBlock) { + const editorState = EditorState.createWithContent(contentBlock); + this.state = { + openSnackBar: false, + errorMessage: '', + files: [], + editorState, + emailContent: draftToHtml(convertToRaw(editorState.getCurrentContent())), + }; + } + this.onDrop = this.onDrop.bind(this); + } + + onDrop(filesVal) { + const { files } = this.state; + let oldFiles = files; + const filesLimit = 3; + oldFiles = oldFiles.concat(filesVal); + if (oldFiles.length > filesLimit) { + console.log('Cannot upload more than ' + filesLimit + ' items.'); + } else { + this.setState({ files: oldFiles }); + } + } + + onEditorStateChange = editorState => { + this.setState({ + editorState, + emailContent: draftToHtml(convertToRaw(editorState.getCurrentContent())) + }); + }; + + onDropRejected() { + this.setState({ + openSnackBar: true, + errorMessage: 'File too big, max size is 3MB', + }); + } + + handleRequestCloseSnackBar = () => { + this.setState({ + openSnackBar: false, + }); + }; + + handleRemove(file, fileIndex) { + const thisFiles = this.state.files; + // This is to prevent memory leaks. + window.URL.revokeObjectURL(file.preview); + + thisFiles.splice(fileIndex, 1); + this.setState({ files: thisFiles }); + } + + handleSend = (to, subject, emailContent, files) => { + this.props.sendEmail(to, subject, emailContent, files); + this.setState({ emailContent: '', files: [] }); + }; + + render() { + const { + classes, + closeForm, + to, + subject, + validMail, + inputChange + } = this.props; + const { + editorState, + emailContent, + files, + openSnackBar, + errorMessage, + } = this.state; + let dropzoneRef; + const deleteBtn = (file, index) => ( + <div className="middle"> + <IconButton onClick={() => this.handleRemove(file, index)}> + <ActionDelete className="removeBtn" /> + </IconButton> + </div> + ); + const previews = filesArray => filesArray.map((file, index) => { + if (isImage(file)) { + const base64Img = URL.createObjectURL(file); + return ( + <div key={index.toString()} className={classes.item}> + <div className="imageContainer col fileIconImg"> + <figure className="imgWrap"><img className="smallPreviewImg" src={base64Img} alt="preview" /></figure> + {deleteBtn(file, index)} + </div> + <Typography noWrap variant="caption">{file.name}</Typography> + </div> + ); + } + return ( + <div key={index.toString()} className={classes.item}> + <div className="imageContainer col fileIconImg"> + <div className="fileWrap"> + <FileIcon className="smallPreviewImg" alt="preview" /> + {deleteBtn(file, index)} + </div> + </div> + <Typography noWrap variant="caption">{file.name}</Typography> + </div> + ); + }); + const fileSizeLimit = 3000000; + return ( + <div> + <form> + <section className={css.bodyForm}> + <div> + <TextField + error={validMail === 'Invalid email'} + id="to" + label="To" + helperText={validMail} + className={classes.field} + type="email" + placeholder="To" + value={to} + onChange={(event) => inputChange(event, 'to')} + margin="normal" + /> + </div> + <div> + <TextField + id="subject" + label="Subject" + className={classes.field} + placeholder="Subject" + value={subject} + onChange={(event) => inputChange(event, 'subject')} + margin="normal" + /> + </div> + <Grid container alignItems="center"> + <Dropzone + className={classes.hiddenDropzone} + acceptClassName="stripes" + onDrop={this.onDrop} + maxSize={fileSizeLimit} + ref={(node) => { dropzoneRef = node; }} + > + {({ getRootProps, getInputProps }) => ( + <div {...getRootProps()}> + <input {...getInputProps()} /> + </div> + )} + </Dropzone> + <Button + className={classes.buttonUpload} + color="secondary" + component="button" + onClick={() => { + dropzoneRef.open(); + }} + > + <Attachment /> + Attach Files + </Button> + + <Typography variant="caption">(Max 3MB)</Typography> + </Grid> + <div className={classes.preview}> + {previews(files)} + </div> + <div> + <Editor + editorState={editorState} + editorClassName={EditorStyle.TextEditor} + toolbarClassName={EditorStyle.ToolbarEditor} + onEditorStateChange={this.onEditorStateChange} + toolbar={{ + options: ['inline', 'fontSize', 'fontFamily', 'colorPicker', 'image', 'emoji', 'list', 'textAlign', 'link'], + inline: { inDropdown: true }, + color: true, + list: { inDropdown: true }, + textAlign: { inDropdown: true }, + link: { inDropdown: true }, + }} + /> + </div> + </section> + <div className={css.buttonArea}> + <Button type="button" onClick={() => closeForm()}> + Discard + </Button> + <Button + variant="contained" + color="secondary" + type="button" + disabled={!to || !subject} + onClick={() => this.handleSend(to, subject, emailContent, files)} + > + Send + {' '} + <Send className={classes.sendIcon} /> + </Button> + </div> + </form> + <Snackbar + open={openSnackBar} + message={errorMessage} + autoHideDuration={4000} + onClose={this.handleRequestCloseSnackBar} + /> + </div> + ); + } +} + +ComposeEmailForm.propTypes = { + classes: PropTypes.object.isRequired, + to: PropTypes.string.isRequired, + subject: PropTypes.string.isRequired, + validMail: PropTypes.string.isRequired, + sendEmail: PropTypes.func.isRequired, + closeForm: PropTypes.func.isRequired, + inputChange: PropTypes.func.isRequired, +}; + +export default withStyles(styles)(ComposeEmailForm); diff --git a/front/odiparpack/app/components/Email/EmailHeader.js b/front/odiparpack/app/components/Email/EmailHeader.js new file mode 100644 index 0000000..eceb757 --- /dev/null +++ b/front/odiparpack/app/components/Email/EmailHeader.js @@ -0,0 +1,49 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { withStyles } from '@material-ui/core/styles'; +import SearchIcon from '@material-ui/icons/Search'; +import MenuIcon from '@material-ui/icons/Menu'; +import { AppBar, Hidden, Toolbar, Typography, IconButton } from '@material-ui/core'; +import styles from './email-jss'; + + +class EmailHeader extends React.Component { + render() { + const { classes, search, handleDrawerToggle } = this.props; + return ( + <AppBar position="absolute" className={classes.appBar}> + <Toolbar> + <Hidden smDown> + <Typography variant="h6" color="inherit" className={classes.title} noWrap> + Email + </Typography> + </Hidden> + <IconButton + color="inherit" + aria-label="open drawer" + onClick={() => handleDrawerToggle()} + className={classes.navIconHide} + > + <MenuIcon /> + </IconButton> + <div className={classes.flex}> + <div className={classes.wrapper}> + <div className={classes.search}> + <SearchIcon /> + </div> + <input className={classes.input} onChange={(event) => search(event)} placeholder="Search Email" /> + </div> + </div> + </Toolbar> + </AppBar> + ); + } +} + +EmailHeader.propTypes = { + classes: PropTypes.object.isRequired, + search: PropTypes.func.isRequired, + handleDrawerToggle: PropTypes.func.isRequired, +}; + +export default withStyles(styles)(EmailHeader); diff --git a/front/odiparpack/app/components/Email/EmailList.js b/front/odiparpack/app/components/Email/EmailList.js new file mode 100644 index 0000000..1fc3507 --- /dev/null +++ b/front/odiparpack/app/components/Email/EmailList.js @@ -0,0 +1,314 @@ +import React, { Fragment } from 'react'; +import PropTypes from 'prop-types'; +import { withStyles } from '@material-ui/core/styles'; +import Bookmark from '@material-ui/icons/Bookmark'; +import Delete from '@material-ui/icons/Delete'; +import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; +import classNames from 'classnames'; +import Flag from '@material-ui/icons/Flag'; +import People from '@material-ui/icons/People'; +import QuestionAnswer from '@material-ui/icons/QuestionAnswer'; +import ReportIcon from '@material-ui/icons/Report'; +import LabelIcon from '@material-ui/icons/Label'; +import FileIcon from '@material-ui/icons/Description'; +import Download from '@material-ui/icons/CloudDownload'; +import StarBorder from '@material-ui/icons/StarBorder'; +import Star from '@material-ui/icons/Star'; +import { + List, + Typography, + ExpansionPanel, + ExpansionPanelDetails, + ExpansionPanelSummary, + ExpansionPanelActions, + Tooltip, + IconButton, + Avatar, + Button, + ListSubheader, + Menu, + MenuItem, + Divider, +} from '@material-ui/core'; +import isImage from '../Forms/helpers/helpers.js'; +import styles from './email-jss'; + + +const ITEM_HEIGHT = 80; +class EmailList extends React.Component { + state = { + anchorElOpt: null, + itemToMove: null + }; + + handleClickOpt = (event, item) => { + this.setState({ + anchorElOpt: event.currentTarget, + itemToMove: item + }); + }; + + handleCloseOpt = () => { + this.setState({ anchorElOpt: null }); + }; + + handleMoveTo = (item, category) => { + this.props.moveTo(item, category); + this.setState({ anchorElOpt: null }); + } + + render() { + const { + classes, + emailData, + openMail, + filterPage, + keyword, + remove, + toggleStar, + reply + } = this.props; + const { anchorElOpt, itemToMove } = this.state; + /* Basic Filter */ + const inbox = emailData.filter(item => item.get('category') !== 'sent' && item.get('category') !== 'spam'); + const stared = emailData.filter(item => item.get('stared')); + const sent = emailData.filter(item => item.get('category') === 'sent'); + const spam = emailData.filter(item => item.get('category') === 'spam'); + /* Category Filter */ + const updates = emailData.filter(item => item.get('category') === 'updates'); + const social = emailData.filter(item => item.get('category') === 'social'); + const forums = emailData.filter(item => item.get('category') === 'forums'); + const promos = emailData.filter(item => item.get('category') === 'promos'); + const getCategory = cat => { + switch (cat) { + case 'updates': + return ( + <span className={classNames(classes.iconOrange, classes.category)}> + <Flag /> + {' '} +Updates + </span> + ); + case 'social': + return ( + <span className={classNames(classes.iconRed, classes.category)}> + <People /> + {' '} +Social + </span> + ); + case 'promos': + return ( + <span className={classNames(classes.iconBlue, classes.category)}> + <LabelIcon /> + {' '} +Promos + </span> + ); + case 'forums': + return ( + <span className={classNames(classes.iconCyan, classes.category)}> + <QuestionAnswer /> + {' '} +Forums + </span> + ); + default: + return false; + } + }; + const attachmentPreview = filesArray => filesArray.map((file, index) => { + const base64File = URL.createObjectURL(file); + if (isImage(file)) { + return ( + <div key={index.toString()} className={classes.item}> + <div className="imageContainer col fileIconImg"> + <div className="downloadBtn"> + <IconButton color="secondary" component="a" href={base64File} target="_blank"> + <Download /> + </IconButton> + </div> + <figure className="imgWrap"><img className="smallPreviewImg" src={base64File} alt="preview" /></figure> + </div> + <Typography noWrap>{file.name}</Typography> + </div> + ); + } + return ( + <div key={index.toString()} className={classes.item}> + <div className="imageContainer col fileIconImg"> + <div className="fileWrap"> + <div className="downloadBtn"> + <IconButton color="secondary" href={base64File} target="_blank"> + <Download /> + </IconButton> + </div> + <FileIcon className="smallPreviewImg" alt="preview" /> + </div> + </div> + <Typography noWrap>{file.name}</Typography> + </div> + ); + }); + const getEmail = dataArray => dataArray.map(mail => { + const renderHTML = { __html: mail.get('content') }; + if (mail.get('subject').toLowerCase().indexOf(keyword) === -1) { + return false; + } + return ( + <ExpansionPanel className={classes.emailList} key={mail.get('id')} onChange={() => openMail(mail)}> + <ExpansionPanelSummary className={classes.emailSummary} expandIcon={<ExpandMoreIcon />}> + <div className={classes.fromHeading}> + <Tooltip id="tooltip-mark" title="Stared"> + <IconButton onClick={() => toggleStar(mail)} className={classes.starBtn}>{mail.get('stared') ? (<Star className={classes.iconOrange} />) : (<StarBorder />) }</IconButton> + </Tooltip> + {mail.get('category') !== 'spam' + ? (<Avatar alt="avatar" src={mail.get('avatar')} className={classes.avatar} />) + : (<Avatar alt="avatar" className={classes.avatar}><ReportIcon /></Avatar>) + } + <Typography className={classes.heading}> + {mail.get('category') === 'sent' && ('To ')} + {mail.get('name')} + <Typography variant="caption" display="block">{mail.get('date')}</Typography> + </Typography> + </div> + <div className={classes.column}> + <Typography className={classes.secondaryHeading} noWrap>{mail.get('subject')}</Typography> + {getCategory(mail.get('category'))} + </div> + </ExpansionPanelSummary> + <ExpansionPanelDetails className={classes.details}> + <section> + <div className={classes.topAction}> + <Typography className={classes.headMail}> + {mail.get('category') !== 'sent' && ( + <Fragment> +From + {mail.get('name')} + {' '} +to me + </Fragment> + )} + </Typography> + <div className={classes.opt}> + <Tooltip id="tooltip-mark" title="Stared"> + <IconButton onClick={() => toggleStar(mail)}>{mail.get('stared') ? (<Star className={classes.iconOrange} />) : (<StarBorder />) }</IconButton> + </Tooltip> + <Tooltip id="tooltip-mark" title="Mark message to"> + <IconButton + className={classes.button} + aria-label="mark" + aria-owns={anchorElOpt ? 'long-menu' : null} + aria-haspopup="true" + onClick={(event) => this.handleClickOpt(event, mail)} + > + <Bookmark /> + </IconButton> + </Tooltip> + <Tooltip id="tooltip-mark" title="Remove mail"> + <IconButton className={classes.button} aria-label="Delete" onClick={() => remove(mail)}><Delete /></IconButton> + </Tooltip> + </div> + </div> + <div className={classes.emailContent}> + <Typography variant="h6" gutterBottom>{mail.get('subject')}</Typography> + <article dangerouslySetInnerHTML={renderHTML} /> + </div> + <div className={classes.preview}> + {attachmentPreview(mail.get('attachment'))} + </div> + </section> + </ExpansionPanelDetails> + <Divider /> + <ExpansionPanelActions> + <div className={classes.action}> + <Button size="small">Forwad</Button> + <Button size="small" color="secondary" onClick={() => reply(mail)}>Reply</Button> + </div> + </ExpansionPanelActions> + </ExpansionPanel> + ); + }); + const showEmail = category => { + switch (category) { + case 'inbox': + return getEmail(inbox); + case 'stared': + return getEmail(stared); + case 'sent': + return getEmail(sent); + case 'spam': + return getEmail(spam); + case 'updates': + return getEmail(updates); + case 'social': + return getEmail(social); + case 'promos': + return getEmail(promos); + case 'forums': + return getEmail(forums); + default: + return getEmail(inbox); + } + }; + return ( + <main className={classes.content}> + <div className={classes.toolbar} /> + <Menu + id="long-menu" + anchorEl={anchorElOpt} + open={Boolean(anchorElOpt)} + onClose={this.handleCloseOpt} + className={classes.markMenu} + PaperProps={{ style: { maxHeight: ITEM_HEIGHT * 4.5, width: 200 } }} + > + <List + component="nav" + subheader={<ListSubheader component="div">Mark to... </ListSubheader>} + /> + <MenuItem selected onClick={() => this.handleMoveTo(itemToMove, 'updates')}> + <Flag className={classes.iconOrange} /> + {' '} +Updates + </MenuItem> + <MenuItem onClick={() => this.handleMoveTo(itemToMove, 'social')}> + <People className={classes.iconRed} /> + {' '} +Social + </MenuItem> + <MenuItem onClick={() => this.handleMoveTo(itemToMove, 'promos')}> + <LabelIcon className={classes.iconBlue} /> + {' '} +Promos + </MenuItem> + <MenuItem onClick={() => this.handleMoveTo(itemToMove, 'forums')}> + <QuestionAnswer className={classes.iconCyan} /> + {' '} +Forums + </MenuItem> + <Divider /> + <MenuItem onClick={() => this.handleMoveTo(itemToMove, 'spam')}> + <ReportIcon /> + {' '} +Spam + </MenuItem> + </Menu> + {showEmail(filterPage)} + </main> + ); + } +} + +EmailList.propTypes = { + classes: PropTypes.object.isRequired, + emailData: PropTypes.object.isRequired, + openMail: PropTypes.func.isRequired, + moveTo: PropTypes.func.isRequired, + remove: PropTypes.func.isRequired, + toggleStar: PropTypes.func.isRequired, + reply: PropTypes.func.isRequired, + filterPage: PropTypes.string.isRequired, + keyword: PropTypes.string.isRequired, +}; + +export default withStyles(styles)(EmailList); diff --git a/front/odiparpack/app/components/Email/EmailSidebar.js b/front/odiparpack/app/components/Email/EmailSidebar.js new file mode 100644 index 0000000..1951de2 --- /dev/null +++ b/front/odiparpack/app/components/Email/EmailSidebar.js @@ -0,0 +1,162 @@ +import React, { Fragment } from 'react'; +import PropTypes from 'prop-types'; +import { withStyles } from '@material-ui/core/styles'; +import InboxIcon from '@material-ui/icons/MoveToInbox'; +import SendIcon from '@material-ui/icons/Send'; +import ReportIcon from '@material-ui/icons/Report'; +import StarIcon from '@material-ui/icons/Star'; +import Flag from '@material-ui/icons/Flag'; +import People from '@material-ui/icons/People'; +import QuestionAnswer from '@material-ui/icons/QuestionAnswer'; +import LabelIcon from '@material-ui/icons/Label'; +import Add from '@material-ui/icons/Add'; +import { + Drawer, + List, + ListItem, + ListItemIcon, + ListItemText, + Hidden, + Button, + Divider, +} from '@material-ui/core'; +import styles from './email-jss'; + + +const MenuList = props => { + const { + classes, + compose, + goto, + selected, + } = props; + return ( + <Fragment> + <List> + <ListItem> + <Button variant="contained" onClick={compose} fullWidth color="primary"> + <Add /> + {' '} +Compose + </Button> + </ListItem> + <ListItem button className={selected === 'inbox' ? classes.selected : ''} onClick={() => goto('inbox')}> + <ListItemIcon> + <InboxIcon /> + </ListItemIcon> + <ListItemText primary="Inbox" /> + </ListItem> + <ListItem button className={selected === 'stared' ? classes.selected : ''} onClick={() => goto('stared')}> + <ListItemIcon> + <StarIcon /> + </ListItemIcon> + <ListItemText primary="Stared" /> + </ListItem> + <ListItem button className={selected === 'sent' ? classes.selected : ''} onClick={() => goto('sent')}> + <ListItemIcon> + <SendIcon /> + </ListItemIcon> + <ListItemText primary="Sent" /> + </ListItem> + <ListItem button className={selected === 'spam' ? classes.selected : ''} onClick={() => goto('spam')}> + <ListItemIcon> + <ReportIcon /> + </ListItemIcon> + <ListItemText primary="Spam" /> + </ListItem> + </List> + <Divider className={classes.divider} /> + <List> + <ListItem button className={selected === 'updates' ? classes.selected : ''} onClick={() => goto('updates')}> + <ListItemIcon> + <Flag className={classes.iconOrange} /> + </ListItemIcon> + <ListItemText primary="Updates" /> + </ListItem> + <ListItem button className={selected === 'social' ? classes.selected : ''} onClick={() => goto('social')}> + <ListItemIcon> + <People className={classes.iconRed} /> + </ListItemIcon> + <ListItemText primary="Social" /> + </ListItem> + <ListItem button className={selected === 'promos' ? classes.selected : ''} onClick={() => goto('promos')}> + <ListItemIcon> + <LabelIcon className={classes.iconBlue} /> + </ListItemIcon> + <ListItemText primary="Promos" /> + </ListItem> + <ListItem button className={selected === 'forums' ? classes.selected : ''} onClick={() => goto('forums')}> + <ListItemIcon> + <QuestionAnswer className={classes.iconCyan} /> + </ListItemIcon> + <ListItemText primary="Forums" /> + </ListItem> + </List> + </Fragment> + ); +}; + +MenuList.propTypes = { + classes: PropTypes.object.isRequired, + compose: PropTypes.func.isRequired, + goto: PropTypes.func.isRequired, + selected: PropTypes.string.isRequired, +}; + +const MenuEmail = withStyles(styles)(MenuList); + +class EmailSidebar extends React.Component { + render() { + const { + classes, + compose, + goto, + selected, + handleDrawerToggle, + mobileOpen + } = this.props; + return ( + <Fragment> + <Hidden mdUp> + <Drawer + variant="temporary" + open={mobileOpen} + onClose={handleDrawerToggle} + classes={{ + paper: classes.drawerPaper, + }} + ModalProps={{ + keepMounted: true, // Better open performance on mobile. + }} + > + <div className={classes.toolbar} /> + <MenuEmail compose={compose} goto={goto} selected={selected} /> + </Drawer> + </Hidden> + <Hidden smDown> + <Drawer + variant="permanent" + className={classes.sidebar} + classes={{ + paper: classes.drawerPaper, + }} + > + <div className={classes.toolbar} /> + <MenuEmail compose={compose} goto={goto} selected={selected} /> + </Drawer> + </Hidden> + </Fragment> + ); + } +} + +EmailSidebar.propTypes = { + classes: PropTypes.object.isRequired, + compose: PropTypes.func.isRequired, + goto: PropTypes.func.isRequired, + handleDrawerToggle: PropTypes.func.isRequired, + selected: PropTypes.string.isRequired, + mobileOpen: PropTypes.bool.isRequired, +}; + +export default withStyles(styles)(EmailSidebar); diff --git a/front/odiparpack/app/components/Email/email-jss.js b/front/odiparpack/app/components/Email/email-jss.js new file mode 100644 index 0000000..6775966 --- /dev/null +++ b/front/odiparpack/app/components/Email/email-jss.js @@ -0,0 +1,238 @@ +import { fade } from '@material-ui/core/styles/colorManipulator'; +import { red, orange, indigo as blue, cyan } from '@material-ui/core/colors'; +const drawerWidth = 240; +const styles = theme => ({ + iconRed: { + color: red[500] + }, + iconOrange: { + color: orange[500] + }, + iconBlue: { + color: blue[500] + }, + iconCyan: { + color: cyan[500] + }, + appBar: { + zIndex: 130, + background: theme.palette.secondary.main, + '& ::-webkit-input-placeholder': { + color: theme.palette.common.white + }, + '& ::-moz-placeholder': { + color: theme.palette.common.white + }, + '& :-ms-input-placeholder': { + color: theme.palette.common.white + }, + '& :-moz-placeholder': { + color: theme.palette.common.white + } + }, + flex: { + flex: 1, + }, + wrapper: { + fontFamily: theme.typography.fontFamily, + position: 'relative', + marginLeft: theme.spacing(1), + borderRadius: 2, + background: fade(theme.palette.common.white, 0.15), + '&:hover': { + background: fade(theme.palette.common.white, 0.25), + }, + '& $input': { + transition: theme.transitions.create('width'), + }, + }, + addBtn: { + position: 'fixed', + bottom: 30, + right: 30, + zIndex: 1000 + }, + sidebar: { + zIndex: 120 + }, + search: { + width: theme.spacing(9), + height: '100%', + position: 'absolute', + pointerEvents: 'none', + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + }, + input: { + font: 'inherit', + padding: `${theme.spacing(1)}px ${theme.spacing(1)}px ${theme.spacing(1)}px ${theme.spacing(9)}px`, + border: 0, + display: 'block', + verticalAlign: 'middle', + whiteSpace: 'normal', + background: 'none', + margin: 0, // Reset for Safari + color: 'inherit', + width: '100%', + '&:focus': { + outline: 0, + }, + }, + drawerPaper: { + [theme.breakpoints.up('md')]: { + position: 'relative', + }, + width: drawerWidth, + background: theme.palette.grey[50], + border: 'none', + padding: 10 + }, + selected: { + background: theme.palette.secondary.light, + borderLeft: `2px solid ${theme.palette.secondary.main}`, + paddingLeft: 22, + '& h3': { + color: theme.palette.secondary.dark + } + }, + content: { + flexGrow: 1, + backgroundColor: theme.palette.background.default, + zIndex: 120, + marginBottom: theme.spacing(8), + [theme.breakpoints.up('md')]: { + padding: theme.spacing(3), + marginBottom: theme.spacing(4), + paddingLeft: 0, + }, + position: 'relative', + minWidth: 0, // So the Typography noWrap works + }, + toolbar: { + minHeight: 32 + }, + title: { + width: 205 + }, + divider: { + margin: '0 20px 0 10px' + }, + /* Email List */ + column: { + flexBasis: '33.33%', + overflow: 'hidden', + paddingRight: '0 !important', + paddingTop: 5, + marginLeft: 20 + }, + secondaryHeading: { + fontSize: 14, + color: theme.palette.text.secondary, + }, + icon: { + verticalAlign: 'bottom', + height: 20, + width: 20, + }, + details: { + alignItems: 'center', + [theme.breakpoints.down('sm')]: { + padding: `${theme.spacing(1)}px ${theme.spacing(1)}px ${theme.spacing(3)}px` + }, + '& section': { + width: '100%' + } + }, + link: { + color: theme.palette.secondary.main, + textDecoration: 'none', + '&:hover': { + textDecoration: 'underline', + }, + }, + avatar: {}, + fromHeading: { + overflow: 'hidden', + display: 'flex', + alignItems: 'center', + '& $avatar': { + width: 30, + height: 30, + marginRight: 20 + } + }, + topAction: { + display: 'flex', + background: theme.palette.grey[100], + marginBottom: 20, + alignItems: 'center', + padding: '0 20px', + borderRadius: 2, + }, + category: { + fontSize: 12, + textTransform: 'uppercase', + display: 'flex', + '& svg': { + fontSize: 16, + marginRight: 5 + } + }, + markMenu: { + '& svg': { + marginRight: 10 + } + }, + headMail: { + flex: 1 + }, + field: { + width: '100%', + marginBottom: 20, + '& svg': { + color: theme.palette.grey[400], + fontSize: 18, + } + }, + hiddenDropzone: { + display: 'none' + }, + sendIcon: { + marginLeft: 10 + }, + item: {}, + preview: { + display: 'flex', + marginBottom: 20, + '& $item': { + maxWidth: 160, + marginBottom: 5, + marginRight: 5 + } + }, + emailSummary: { + paddingLeft: 0, + '& > div': { + [theme.breakpoints.down('sm')]: { + flexDirection: 'column' + }, + } + }, + emailContent: { + padding: theme.spacing(2), + [theme.breakpoints.down('sm')]: { + padding: `${theme.spacing(2)}px ${theme.spacing(2)}px`, + }, + }, + starBtn: { + marginRight: 10 + }, + navIconHide: { + [theme.breakpoints.up('md')]: { + display: 'none', + }, + }, +}); + +export default styles; |
