From e13e630cd6e4fc0b1ff92098a28a770794c7bb9a Mon Sep 17 00:00:00 2001 From: gabrhr <73925454+gabrhr@users.noreply.github.com> Date: Wed, 20 Apr 2022 10:19:29 -0500 Subject: =?UTF-8?q?A=C3=B1adir=20plantilla?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Base para front --- .../app/components/Email/ComposeEmail.js | 65 +++++ .../app/components/Email/ComposeEmailForm.js | 262 +++++++++++++++++ .../odiparpack/app/components/Email/EmailHeader.js | 49 ++++ front/odiparpack/app/components/Email/EmailList.js | 314 +++++++++++++++++++++ .../app/components/Email/EmailSidebar.js | 162 +++++++++++ front/odiparpack/app/components/Email/email-jss.js | 238 ++++++++++++++++ 6 files changed, 1090 insertions(+) create mode 100644 front/odiparpack/app/components/Email/ComposeEmail.js create mode 100644 front/odiparpack/app/components/Email/ComposeEmailForm.js create mode 100644 front/odiparpack/app/components/Email/EmailHeader.js create mode 100644 front/odiparpack/app/components/Email/EmailList.js create mode 100644 front/odiparpack/app/components/Email/EmailSidebar.js create mode 100644 front/odiparpack/app/components/Email/email-jss.js (limited to 'front/odiparpack/app/components/Email') 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 ( +
+ + compose()} className={classes.addBtn}> + + + + + + +
+ ); + } +} + +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) => ( +
+ this.handleRemove(file, index)}> + + +
+ ); + const previews = filesArray => filesArray.map((file, index) => { + if (isImage(file)) { + const base64Img = URL.createObjectURL(file); + return ( +
+
+
preview
+ {deleteBtn(file, index)} +
+ {file.name} +
+ ); + } + return ( +
+
+
+ + {deleteBtn(file, index)} +
+
+ {file.name} +
+ ); + }); + const fileSizeLimit = 3000000; + return ( +
+
+
+
+ inputChange(event, 'to')} + margin="normal" + /> +
+
+ inputChange(event, 'subject')} + margin="normal" + /> +
+ + { dropzoneRef = node; }} + > + {({ getRootProps, getInputProps }) => ( +
+ +
+ )} +
+ +   + (Max 3MB) +
+
+ {previews(files)} +
+
+ +
+
+
+ + +
+
+ +
+ ); + } +} + +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 ( + + + + + Email + + + handleDrawerToggle()} + className={classes.navIconHide} + > + + +
+
+
+ +
+ search(event)} placeholder="Search Email" /> +
+
+
+
+ ); + } +} + +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 ( + + + {' '} +Updates + + ); + case 'social': + return ( + + + {' '} +Social + + ); + case 'promos': + return ( + + + {' '} +Promos + + ); + case 'forums': + return ( + + + {' '} +Forums + + ); + default: + return false; + } + }; + const attachmentPreview = filesArray => filesArray.map((file, index) => { + const base64File = URL.createObjectURL(file); + if (isImage(file)) { + return ( +
+
+
+ + + +
+
preview
+
+ {file.name} +
+ ); + } + return ( +
+
+
+
+ + + +
+ +
+
+ {file.name} +
+ ); + }); + const getEmail = dataArray => dataArray.map(mail => { + const renderHTML = { __html: mail.get('content') }; + if (mail.get('subject').toLowerCase().indexOf(keyword) === -1) { + return false; + } + return ( + openMail(mail)}> + }> +
+ + toggleStar(mail)} className={classes.starBtn}>{mail.get('stared') ? () : () } + + {mail.get('category') !== 'spam' + ? () + : () + } + + {mail.get('category') === 'sent' && ('To ')} + {mail.get('name')} + {mail.get('date')} + +
+
+ {mail.get('subject')} + {getCategory(mail.get('category'))} +
+
+ +
+
+ + {mail.get('category') !== 'sent' && ( + +From + {mail.get('name')} + {' '} +to me + + )} + +
+ + toggleStar(mail)}>{mail.get('stared') ? () : () } + + + this.handleClickOpt(event, mail)} + > + + + + + remove(mail)}> + +
+
+
+ {mail.get('subject')} +
+
+
+ {attachmentPreview(mail.get('attachment'))} +
+
+
+ + +
+ + +
+
+
+ ); + }); + 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 ( +
+
+ + Mark to... } + /> + this.handleMoveTo(itemToMove, 'updates')}> + + {' '} +Updates + + this.handleMoveTo(itemToMove, 'social')}> + + {' '} +Social + + this.handleMoveTo(itemToMove, 'promos')}> + + {' '} +Promos + + this.handleMoveTo(itemToMove, 'forums')}> + + {' '} +Forums + + + this.handleMoveTo(itemToMove, 'spam')}> + + {' '} +Spam + + + {showEmail(filterPage)} +
+ ); + } +} + +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 ( + + + + + + goto('inbox')}> + + + + + + goto('stared')}> + + + + + + goto('sent')}> + + + + + + goto('spam')}> + + + + + + + + + goto('updates')}> + + + + + + goto('social')}> + + + + + + goto('promos')}> + + + + + + goto('forums')}> + + + + + + + + ); +}; + +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 ( + + + +
+ + + + + +
+ + + + + ); + } +} + +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; -- cgit v1.2.3