Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support 2-Decimal Formatting & customizable decimal separator #192

Merged
merged 30 commits into from
Feb 11, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
dd3d16e
Closes hql287/Manta#190, Closes hql287/Manta#173
Jan 25, 2018
7e77648
Merge branch 'dev' into dev
DarkSmile92 Jan 29, 2018
1b8fd42
Preview and Invoices list
Jan 29, 2018
812f2ae
Merge branch 'dev' into dev
hql287 Feb 1, 2018
733ca44
#190 tests and other points
Feb 1, 2018
e0df73c
Merge branch 'dev' of https://github.com/DarkSmile92/Manta into dev
Feb 1, 2018
a7e196b
Removed console logs and eslint errors
Feb 1, 2018
4473f69
Use dialog instead of notification
Feb 1, 2018
3916e2f
Refactored Invoice setting component
hql287 Feb 2, 2018
4c157b0
Merge branch 'dev' into dev
hql287 Feb 2, 2018
9bc2ede
Added new definitions
hql287 Feb 2, 2018
7b8c458
Refactored Invoice settings tab
hql287 Feb 2, 2018
ac85c09
Merge branch 'dev' into dev
hql287 Feb 2, 2018
8167821
Merge branch 'dev' into dev
hql287 Feb 3, 2018
b70229d
Merge branch 'dev' into dev
hql287 Feb 4, 2018
0325b95
Reimplemented currency settings
hql287 Feb 5, 2018
ff5d8e8
Refactored InvoiceMW & Form helper
hql287 Feb 5, 2018
d7aeefe
Moved numer helper to application helpers folder
hql287 Feb 5, 2018
21db7a0
Updated Currency component in Form
hql287 Feb 5, 2018
015f2fa
Refactored Tax & Recipient Form with the shared Part component
hql287 Feb 5, 2018
a510844
Refactored components
hql287 Feb 5, 2018
5b25aab
Make sure numbers are displayed correctly in templates
hql287 Feb 5, 2018
171d18d
Send notification when saveAsDefault successfully
hql287 Feb 5, 2018
637b8d0
Updated translation
hql287 Feb 5, 2018
17d8343
Fixed tests
hql287 Feb 5, 2018
91284b0
Updated translation
hql287 Feb 5, 2018
c8b851c
Clear the form if the invoice is being editted
hql287 Feb 6, 2018
cfe6e41
Refactored validation rules, tests & added translation
hql287 Feb 7, 2018
a2de896
Updated migration for invoices
hql287 Feb 11, 2018
ae3a05d
Refactored formatNumber helper and added tests
hql287 Feb 11, 2018
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
30 changes: 28 additions & 2 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -192,13 +192,18 @@ function setInitialValues() {
invoice: {
exportDir: os.homedir(),
template: 'default',
currency: 'USD',
dateFormat: 'MM/DD/YYYY',
tax: {
tin: '123-456-789',
method: 'default',
amount: 0,
},
currency: {
code: 'USD',
placement: 'before',
separator: 'commaDot',
fraction: 2,
},
required_fields: {
invoiceID: false,
dueDate: false,
Expand All @@ -210,11 +215,14 @@ function setInitialValues() {
},
};

// Set initial values conditionally
// Set initial values conditionally work for 2 level depth key only,
// Changing anything deeper would need to be done with migration
for (const key in defaultOptions) {
// Add level 1 key if not exist
if (!appConfig.has(`${key}`)) {
appConfig.set(`${key}`, defaultOptions[key]);
}
// Add level 2 key if not exist
for (const childKey in defaultOptions[key]) {
if (!appConfig.has(`${key}.${childKey}`)) {
appConfig.set(`${key}.${childKey}`, defaultOptions[key][childKey]);
Expand Down Expand Up @@ -268,6 +276,24 @@ function migrateData() {
'test',
]);
},

2: configs => {
// Return current configs if this is the first time install
if ( configs.invoice.currency.placement !== undefined) {
return configs;
}
// Update current configs
return Object.assign({}, configs, {
invoice: Object.assign({}, configs.invoice, {
currency: {
code: configs.invoice.currency,
placement: 'before',
separator: 'commaDot',
fraction: 2,
}
})
});
},
};
// Get the current Config
const configs = appConfig.getAll();
Expand Down
108 changes: 90 additions & 18 deletions app/components/form/Currency.jsx
Original file line number Diff line number Diff line change
@@ -1,44 +1,65 @@
// Libs
import React, { Component } from 'react';
import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
const appConfig = require('electron').remote.require('electron-settings');
import currencies from '../../../libs/currencies.json';
import { keys, sortBy, isEqual } from 'lodash';

// Custom Components
import { Section, Header } from '../shared/Section';
import { Row, Field, Part } from '../shared/Part';

// Animation
import _withFadeInAnimation from '../shared/hoc/_withFadeInAnimation';

// Component
export class Currency extends Component {
export class Currency extends PureComponent {
constructor(props) {
super(props);
this.handleInputChange = this.handleInputChange.bind(this);
this.state = props.currency;
this.isSettingsSaved = this.isSettingsSaved.bind(this);
this.saveAsDefault = this.saveAsDefault.bind(this);
this.sortCurrencies = this.sortCurrencies.bind(this);
this.handleInputChange = this.handleInputChange.bind(this);
}

shouldComponentUpdate(nextProps) {
if (this.props.currency !== nextProps.currency) return true;
if (this.props.savedSettings !== nextProps.savedSettings) return true;
return true;
// Handle Form Clear
componentWillReceiveProps(nextProps) {
// Already made changes but not saved
if (this.state !== this.props.savedSettings) {
// Reset to savedSettings if the below confition is met
if (nextProps.currency === nextProps.savedSettings) {
this.setState(nextProps.savedSettings, () => {
this.updateCurrencyState();
});
}
}
}

handleInputChange(event) {
const value = event.target.value;
this.props.updateFieldData('currency', currencies[value]);
const target = event.target;
const name = target.name;
const value = name === 'fraction' ? parseInt(target.value, 10) : target.value;
this.setState({
[name]: value
}, () => {
this.updateCurrencyState();
}
);
}

updateCurrencyState() {
const { updateFieldData } = this.props;
updateFieldData('currency', this.state);
}

isSettingsSaved() {
return isEqual(this.props.currency.code, this.props.savedSettings);
return isEqual(this.props.currency, this.props.savedSettings);
}

saveAsDefault() {
const { updateSavedSettings } = this.props;
updateSavedSettings('currency', this.props.currency.code);
updateSavedSettings('currency', this.state);
}

sortCurrencies() {
Expand Down Expand Up @@ -79,20 +100,71 @@ export class Currency extends Component {
</a>
)}
</Header>
<select
value={this.props.currency.code}
onChange={this.handleInputChange}
>
{this.sortCurrencies()}
</select>
<Part>
<Row>
<Field>
<label className="itemLabel">
{t('form:fields:currency')}
</label>
<select
name="code"
value={this.state.code}
onChange={this.handleInputChange}
>
{this.sortCurrencies()}
</select>
</Field>
<Field>
<label className="itemLabel">{t('settings:fields:currency:separator')}</label>
<select
name="separator"
value={this.state.separator}
onChange={this.handleInputChange}
>
<option value="commaDot">
1,999.000 ({t('settings:fields:currency:commaDot')})
</option>
<option value="dotComma">
1.999,000 ({t('settings:fields:currency:dotComma')})
</option>
<option value="spaceDot">
1 999.000 ({t('settings:fields:currency:spaceDot')})
</option>
</select>
</Field>
</Row>
<Row>
<Field>
<label className="itemLabel">{t('settings:fields:currency:placement')}</label>
<select
name="placement"
value={this.state.placement}
onChange={this.handleInputChange}
>
<option value="before">{t('settings:fields:currency:beforeAmount')}</option>
<option value="after">{t('settings:fields:currency:afterAmount')}</option>
</select>
</Field>
<Field>
<label className="itemLabel">{t('settings:fields:currency:fraction')}</label>
<input
className="form-control"
name="fraction"
type="number"
value={this.state.fraction}
onChange={this.handleInputChange}
/>
</Field>
</Row>
</Part>
</Section>
);
}
}

Currency.propTypes = {
currency: PropTypes.object.isRequired,
savedSettings: PropTypes.string.isRequired,
savedSettings: PropTypes.object.isRequired,
t: PropTypes.func.isRequired,
updateFieldData: PropTypes.func.isRequired,
updateSavedSettings: PropTypes.func.isRequired,
Expand Down
22 changes: 3 additions & 19 deletions app/components/form/RecipientForm.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,28 +7,12 @@ import _withFadeInAnimation from '../../components/shared/hoc/_withFadeInAnimati

// Styles
import styled from 'styled-components';
const Form = styled.div`
padding: 20px;
background: #f9fafa;
border-radius: 4px;
margin-bottom: 20px;
border: 1px solid #f2f3f4;
`;

const Row = styled.div`
display: flex;
margin: 0 -15px;
`;

const Field = styled.div`
flex: 1;
margin: 0 15px 20px 15px;
`;
import { Part, Row, Field } from '../shared/Part';

export function RecipientForm({ t, formData, updateRecipientForm }) {
const { fullname, company, email, phone } = formData;
return (
<Form>
<Part>
<Row>
<Field>
<label className="itemLabel">{t('common:fields:fullname')} *</label>
Expand Down Expand Up @@ -69,7 +53,7 @@ export function RecipientForm({ t, formData, updateRecipientForm }) {
/>
</Field>
</Row>
</Form>
</Part>
);
}

Expand Down
38 changes: 6 additions & 32 deletions app/components/form/Tax.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Libraries
import React, { Component } from 'react';
import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import { isEqual } from 'lodash';
// Custom Components
Expand All @@ -8,31 +8,12 @@ import { Section, Header } from '../shared/Section';
import _withFadeInAnimation from '../shared/hoc/_withFadeInAnimation';
// Styles
import styled from 'styled-components';
import { Part, Row, Field } from '../shared/Part';
const TaxID = styled.div``;
const TaxAmount = styled.div`
flex: 1;
`;

const Form = styled.div`
padding: 20px;
background: #f9fafa;
border-radius: 4px;
margin-bottom: 20px;
border: 1px solid #f2f3f4;
`;

const Row = styled.div`
display: flex;
margin: 0 -15px;
`;

const Field = styled.div`
flex: 1;
margin: 0 15px 20px 15px;
`;
const TaxAmount = styled.div`flex: 1;`;

// Component
export class Tax extends Component {
export class Tax extends PureComponent {
constructor(props) {
super(props);
this.state = props.tax;
Expand All @@ -54,13 +35,6 @@ export class Tax extends Component {
}
}

shouldComponentUpdate(nextProps, nextState) {
if (this.state !== nextState) return true;
if (this.props.tax !== nextProps.tax) return true;
if (this.props.savedSettings !== nextProps.savedSettings) return true;
return false;
}

handleInputChange(event) {
const target = event.target;
const name = target.name;
Expand Down Expand Up @@ -101,7 +75,7 @@ export class Tax extends Component {
</a>
)}
</Header>
<Form>
<Part>
<Row>
<Field>
<label className="itemLabel">{t('form:fields:tax:id')}</label>
Expand Down Expand Up @@ -142,7 +116,7 @@ export class Tax extends Component {
</select>
</Field>
</Row>
</Form>
</Part>
</Section>
);
}
Expand Down
Loading