From 1a810858a78cb7b22de9b9e1a79137bac5da6429 Mon Sep 17 00:00:00 2001 From: "Hung Q. Le" Date: Fri, 16 Feb 2018 22:36:20 +0700 Subject: [PATCH 01/17] Happy Lunar New Year! Also, removed namespaces from translate HOCs --- app/components/form/ItemsList.jsx | 2 +- app/components/form/Recipient.jsx | 2 +- app/containers/Contacts.jsx | 2 +- app/containers/Form.jsx | 2 +- app/containers/Invoices.jsx | 2 +- app/containers/Settings.jsx | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/components/form/ItemsList.jsx b/app/components/form/ItemsList.jsx index 277d03ca..d0d923d0 100644 --- a/app/components/form/ItemsList.jsx +++ b/app/components/form/ItemsList.jsx @@ -125,6 +125,6 @@ const mapDispatchToProps = dispatch => ({ // Export export default compose( connect(mapStateToProps, mapDispatchToProps), - translate('form'), + translate(), _withDragNDrop )(ItemsList); diff --git a/app/components/form/Recipient.jsx b/app/components/form/Recipient.jsx index 28e85f6e..30e652fc 100644 --- a/app/components/form/Recipient.jsx +++ b/app/components/form/Recipient.jsx @@ -173,5 +173,5 @@ const mapStateToProps = state => ({ export default compose( connect(mapStateToProps), - translate('form'), + translate(), )(Recipient); diff --git a/app/containers/Contacts.jsx b/app/containers/Contacts.jsx index 17738a70..6c93f699 100644 --- a/app/containers/Contacts.jsx +++ b/app/containers/Contacts.jsx @@ -124,6 +124,6 @@ const mapStateToProps = state => ({ export default compose( connect(mapStateToProps), - translate(['common', 'form']), + translate(), _withFadeInAnimation )(Contacts); diff --git a/app/containers/Form.jsx b/app/containers/Form.jsx index efc37fd8..ad4e8c0c 100644 --- a/app/containers/Form.jsx +++ b/app/containers/Form.jsx @@ -184,6 +184,6 @@ const mapDispatchToProps = dispatch => ({ // Export export default compose( connect(mapStateToProps, mapDispatchToProps), - translate(['common', 'form']), + translate(), _withFadeInAnimation )(Form); diff --git a/app/containers/Invoices.jsx b/app/containers/Invoices.jsx index a4b34578..b942b78f 100644 --- a/app/containers/Invoices.jsx +++ b/app/containers/Invoices.jsx @@ -130,6 +130,6 @@ const mapStateToProps = state => ({ export default compose( connect(mapStateToProps), - translate(['common', 'form', 'invoices']), + translate(), _withFadeInAnimation )(Invoices); diff --git a/app/containers/Settings.jsx b/app/containers/Settings.jsx index 337e6595..8448acb3 100644 --- a/app/containers/Settings.jsx +++ b/app/containers/Settings.jsx @@ -147,6 +147,6 @@ const mapStateToProps = state => ({ export default compose( connect(mapStateToProps, mapDispatchToProps), - translate(['common', 'form', 'settings']), + translate(), _withFadeInAnimation )(Settings); From e8413d4251057b86e98eda79cb8dee010623de73 Mon Sep 17 00:00:00 2001 From: "Hung Q. Le" Date: Fri, 16 Feb 2018 22:49:04 +0700 Subject: [PATCH 02/17] Refactored previewWindow components - Merged Invoice component into mainContent component - Move all event handlers from mainContent to Viewer - Viewer now connect to translate HOC and pass props down to sideBar and mainContent --- preview/Viewer.jsx | 100 +++++++++++++++++++++++++--- preview/components/main/Invoice.jsx | 52 --------------- preview/containers/MainContent.jsx | 89 ++++++++++--------------- preview/containers/SideBar.jsx | 82 +++++++++++++---------- 4 files changed, 171 insertions(+), 152 deletions(-) delete mode 100644 preview/components/main/Invoice.jsx diff --git a/preview/Viewer.jsx b/preview/Viewer.jsx index 314b9041..284bc20e 100644 --- a/preview/Viewer.jsx +++ b/preview/Viewer.jsx @@ -1,5 +1,11 @@ // Libs -import React from 'react'; +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import { translate } from 'react-i18next'; +import { Notify } from '../helpers/notify'; +import { connect } from 'react-redux'; +import { compose } from 'recompose'; +const ipc = require('electron').ipcRenderer; // Style import styled from 'styled-components'; @@ -12,14 +18,90 @@ const Wrapper = styled.div` import SideBar from './containers/SideBar'; import MainContent from './containers/MainContent'; +// Actions +import * as ActionsCreator from './actions'; + +// Selectors +import { getConfigs, getInvoice, getProfile, getUILang } from './reducers'; + // Components -function Viewer() { - return ( - - - - - ); +class Viewer extends Component { + constructor(props) { + super(props); + this.updateConfigs = this.updateConfigs.bind(this); + } + + componentDidMount() { + const { dispatch } = this.props; + ipc.on('update-preview', (event, invoiceData) => { + dispatch(ActionsCreator.updateInvoice(invoiceData)); + }); + ipc.on('change-preview-window-language', (event, newLang) => { + dispatch(ActionsCreator.changeUILanguage(newLang)); + }); + ipc.on('pfd-exported', (event, options) => { + const noti = Notify(options); + // Handle click on notification + noti.onclick = () => { + ipc.send('reveal-file', options.location); + }; + }); + } + + componentWillUnmount() { + ipc.removeAllListeners([ + 'pfd-exported', + 'update-preview', + 'update-preview-window', + ]); + } + + updateConfigs(config) { + const { dispatch } = this.props; + dispatch( + ActionsCreator.updateConfigs({ name: config.name, value: config.value }) + ); + } + + render() { + const { t, invoice, configs, profile, UILang } = this.props; + return ( + + + + + ); + } } -export default Viewer; +Viewer.propTypes = { + configs: PropTypes.object.isRequired, + profile: PropTypes.object.isRequired, + dispatch: PropTypes.func.isRequired, + invoice: PropTypes.object.isRequired, + t: PropTypes.func.isRequired, +}; + +const mapStateToProps = state => ({ + configs: getConfigs(state), + invoice: getInvoice(state), + profile: getProfile(state), + UILang: getUILang(state), +}); + +export default compose( + connect(mapStateToProps), + translate() +)(Viewer); diff --git a/preview/components/main/Invoice.jsx b/preview/components/main/Invoice.jsx deleted file mode 100644 index 00b55053..00000000 --- a/preview/components/main/Invoice.jsx +++ /dev/null @@ -1,52 +0,0 @@ -// Libraries -import React, { PureComponent } from 'react'; -import PropTypes from 'prop-types'; - -// Style -import styled from 'styled-components'; - -const Page = styled.div` - position: relative; - width: 21cm; - height: 29.7cm; - min-height: 29.7cm; - min-width: 21cm; - margin-left: auto; - margin-right: auto; - background: #FFFFFF; - box-shadow: 0 0 10px rgba(0,0,0,.1); - display: flex; - border-radius: 4px; -} -`; - -// Templates -import Minimal from '../../templates/minimal'; -import Business from '../../templates/business'; - -// Component -class Invoice extends PureComponent { - renderTemplate() { - switch (this.props.configs.template) { - case 'business': { - return ; - } - default: { - return ; - } - } - } - - render() { - return {this.renderTemplate()}; - } -} - -Invoice.propTypes = { - configs: PropTypes.object.isRequired, - invoice: PropTypes.object.isRequired, - profile: PropTypes.object.isRequired, - t: PropTypes.func.isRequired, -}; - -export default Invoice; diff --git a/preview/containers/MainContent.jsx b/preview/containers/MainContent.jsx index 49653502..44a6b600 100644 --- a/preview/containers/MainContent.jsx +++ b/preview/containers/MainContent.jsx @@ -1,20 +1,10 @@ // Libs -import React, { PureComponent } from 'react'; +import React, { Component } from 'react'; import PropTypes from 'prop-types'; -import { connect } from 'react-redux'; -import { compose } from 'recompose'; -import { translate } from 'react-i18next'; -const ipc = require('electron').ipcRenderer; -import { Notify } from '../../helpers/notify'; - -// Actions -import * as ActionsCreator from '../actions'; - -// Selectors -import { getConfigs, getInvoice, getProfile } from '../reducers'; // Styles import styled from 'styled-components'; + const Wrapper = styled.div` display: flex; width: 100%; @@ -35,47 +25,45 @@ const Message = styled.p` margin: 0; `; -// Components -import Invoice from '../components/main/Invoice'; +const Page = styled.div` + position: relative; + width: 21cm; + height: 29.7cm; + min-height: 29.7cm; + min-width: 21cm; + margin-left: auto; + margin-right: auto; + background: #FFFFFF; + box-shadow: 0 0 10px rgba(0,0,0,.1); + display: flex; + border-radius: 4px; +`; -class MainContent extends PureComponent { - componentDidMount() { - const { dispatch } = this.props; - ipc.on('update-preview', (event, invoiceData) => { - dispatch(ActionsCreator.updateInvoice(invoiceData)); - }); - ipc.on('update-preview-window', (event, newConfigs) => { - dispatch(ActionsCreator.reloadConfigs(newConfigs)); - }); - ipc.on('pfd-exported', (event, options) => { - const noti = Notify(options); - // Handle click on notification - noti.onclick = () => { - ipc.send('reveal-file', options.location); - }; - }); - } +// Components +import Minimal from '../templates/minimal'; +import Business from '../templates/business'; - componentWillUnmount() { - ipc.removeAllListeners([ - 'pfd-exported', - 'update-preview', - 'update-preview-window', - ]); +class MainContent extends Component { + renderTemplate() { + switch (this.props.configs.template) { + case 'business': { + return ; + } + default: { + return ; + } + } } render() { - const { t, invoice, configs, profile } = this.props; + const { t, invoice } = this.props; return ( {invoice._id ? (
- + + {this.renderTemplate()} +
) : ( {t('preview:common:chooseInvoiceToPreview')} @@ -87,19 +75,10 @@ class MainContent extends PureComponent { MainContent.propTypes = { configs: PropTypes.object.isRequired, - dispatch: PropTypes.func.isRequired, invoice: PropTypes.object.isRequired, profile: PropTypes.object.isRequired, + UILang: PropTypes.string.isRequired, t: PropTypes.func.isRequired, }; -const mapStateToProps = state => ({ - configs: getConfigs(state), - invoice: getInvoice(state), - profile: getProfile(state), -}); - -export default compose( - connect(mapStateToProps), - translate(['common', 'preview']) -)(MainContent); +export default MainContent; diff --git a/preview/containers/SideBar.jsx b/preview/containers/SideBar.jsx index e5820c0f..de7ca7b5 100644 --- a/preview/containers/SideBar.jsx +++ b/preview/containers/SideBar.jsx @@ -1,17 +1,10 @@ // Libs -import React, { PureComponent } from 'react'; +import React, { Component } from 'react'; import PropTypes from 'prop-types'; -import { connect } from 'react-redux'; -import { compose } from 'recompose'; -import { translate } from 'react-i18next'; const ipc = require('electron').ipcRenderer; +import i18n from '../../i18n/i18n'; -// Actions -import * as ActionsCreator from '../actions'; - -// Selector -import { getConfigs, getInvoice } from '../reducers'; - +// Style import styled from 'styled-components'; const Wrapper = styled.div` flex: 1; @@ -30,55 +23,76 @@ const Wrapper = styled.div` `; // Components -import Template from '../components/sidebar/Template'; +import AccentColor from '../components/sidebar/AccentColor'; +import Actions from '../components/sidebar/Actions'; import Alignment from '../components/sidebar/Alignment'; +import DateFormat from '../components/sidebar/DateFormat'; import FontSize from '../components/sidebar/FontSize'; +import Language from '../components/sidebar/Language'; +import Template from '../components/sidebar/Template'; import Toggler from '../components/sidebar/Toggler'; -import AccentColor from '../components/sidebar/AccentColor'; -import Actions from '../components/sidebar/Actions'; -class SideBar extends PureComponent { +class SideBar extends Component { constructor(props) { super(props); this.savePDF = this.savePDF.bind(this); + this.saveConfigs = this.saveConfigs.bind(this); this.handleInputChange = this.handleInputChange.bind(this); this.handleAccentColorChange = this.handleAccentColorChange.bind(this); - this.updateConfigs = this.updateConfigs.bind(this); } handleInputChange(event) { const target = event.target; const value = target.type === 'checkbox' ? target.checked : target.value; const name = target.name; - this.updateConfigs({ name, value }); + this.props.updateConfigs({ name, value }); } handleAccentColorChange(color) { - this.updateConfigs({ name: 'accentColor', value: color }); - } - - updateConfigs(config) { - const { dispatch } = this.props; - dispatch( - ActionsCreator.updateConfigs({ name: config.name, value: config.value }) - ); + this.props.updateConfigs({ name: 'accentColor', value: color }); } savePDF() { const invoiceID = this.props.invoice._id; ipc.send('save-pdf', invoiceID); + // Always save template configs to invocie when export to PDF + this.saveConfigs(); + } + + saveConfigs() { + const { configs, invoice } = this.props; + const { _id: invoiceID } = invoice; + ipc.send('save-configs-to-invoice', invoiceID, configs); } render() { const { t, configs } = this.props; - const { template, alignItems, fontSize, accentColor } = configs; + const { + dateFormat, + template, + language, + alignItems, + fontSize, + accentColor + } = configs; return ( +