From 551bfc4f591698add9069973e7f7f2aad03087f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Madis=20Va=CC=88in?= Date: Sun, 16 Feb 2020 20:39:28 +0200 Subject: [PATCH] * Order by invoice number desc * Allow ordering by number asc / desc * Allow to delete invoices * Confirm invoice delete by modal --- package-lock.json | 26 +++++++-------- package.json | 6 ++-- src/components/invoices/state-tag.js | 6 +++- src/models/invoices.js | 47 +++++++++++++++++----------- src/pages/invoices/$id/_layout.js | 45 ++++++++++++++++++++------ src/pages/invoices/index.js | 1 + src/services/invoices.js | 8 ++++- 7 files changed, 93 insertions(+), 46 deletions(-) diff --git a/package-lock.json b/package-lock.json index e9368bb..aaa0f9a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "upcount", - "version": "0.2.1", + "version": "0.3.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -4502,9 +4502,9 @@ "dev": true }, "antd": { - "version": "3.26.8", - "resolved": "https://registry.npmjs.org/antd/-/antd-3.26.8.tgz", - "integrity": "sha512-Cz9VVGXG3e2qVAfBwC9SfYGe8bhsD/fQr5tiuRWXkQGSJe4FPJEd04u+6QgBCuQ8Y36kBZr1xDiWky6dwoJvsA==", + "version": "3.26.9", + "resolved": "https://registry.npmjs.org/antd/-/antd-3.26.9.tgz", + "integrity": "sha512-youf+hBJHB4nuhV7yEbm2VQSMtX9RxrNQvjlc+iIPj4FeJsuTQXIfSSAc5GhwDeVAI4+nuapCv7XLFIQ+f2ZFg==", "requires": { "@ant-design/create-react-context": "^0.2.4", "@ant-design/icons": "~2.1.1", @@ -16467,9 +16467,9 @@ } }, "libphonenumber-js": { - "version": "1.7.38", - "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.7.38.tgz", - "integrity": "sha512-3NMPjWl15E51vWtXYdhVXo+DtZcR35OmXfJQWcwQ28XEbpSWOnQXbkaIZq8RmMv5jiY4fMQxBY7MUXvioApOHg==", + "version": "1.7.41", + "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.7.41.tgz", + "integrity": "sha512-imrgnCqJmfHMLaW3E3l1VlwEEvN91n4m1wtZdfeBPYtz/k3B48089c6jlM3++jNRSHD9GkNTNzDhzbo/X4m8TQ==", "requires": { "minimist": "^1.2.0", "xml2js": "^0.4.17" @@ -22957,9 +22957,9 @@ } }, "rc-input-number": { - "version": "4.5.3", - "resolved": "https://registry.npmjs.org/rc-input-number/-/rc-input-number-4.5.3.tgz", - "integrity": "sha512-jBwxX5KDkp2nHOaEoMQ1mZBwWpmmGUuHXF/qralpmN+wDp8rlB6Xvr9d7AHgmzGZhbWIMyLeq6ET6HDDCCjvAA==", + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/rc-input-number/-/rc-input-number-4.5.4.tgz", + "integrity": "sha512-lHk4o+vXv9l7Ku4jz4iCuzwG7PsOimdlPpIdIEX9TqnBWVa4QMjwkqin7ILlS2Dy/DBYrLnymtPrIXEGOll7KA==", "requires": { "babel-runtime": "6.x", "classnames": "^2.2.0", @@ -23010,9 +23010,9 @@ } }, "rc-pagination": { - "version": "1.20.13", - "resolved": "https://registry.npmjs.org/rc-pagination/-/rc-pagination-1.20.13.tgz", - "integrity": "sha512-oocyyzx0pye957e3iARFg377hafdUc3oC13faGgmopGX/A8rn7tXCdOwVIJthhI6dHVfAcFLgnYQAlcpGXh+Uw==", + "version": "1.20.14", + "resolved": "https://registry.npmjs.org/rc-pagination/-/rc-pagination-1.20.14.tgz", + "integrity": "sha512-sNKwbFrxiqATqcIIShfrFs8BT03n4UUwTAMYae+JhHTmILQmXdvimEnZbVuWcno6G02DAJcLrFpmkn1h2tmEJw==", "requires": { "babel-runtime": "6.x", "classnames": "^2.2.6", diff --git a/package.json b/package.json index c2d6886..3ff023f 100644 --- a/package.json +++ b/package.json @@ -20,13 +20,13 @@ "postinstall": "electron-builder install-app-deps" }, "dependencies": { - "antd": "^3.26.8", + "antd": "^3.26.9", "bootstrap": "^4.4.1", "countries-list": "^2.5.1", "currency-symbol-map": "^4.0.4", "currency.js": "^1.2.2", "electron-updater": "^4.2.0", - "libphonenumber-js": "^1.7.38", + "libphonenumber-js": "^1.7.41", "pouchdb": "^7.1.1", "pouchdb-find": "^7.1.1", "react": "^16.12.0", @@ -81,4 +81,4 @@ "pre-commit": "lint-staged" } } -} \ No newline at end of file +} diff --git a/src/components/invoices/state-tag.js b/src/components/invoices/state-tag.js index eff15aa..3d7efab 100644 --- a/src/components/invoices/state-tag.js +++ b/src/components/invoices/state-tag.js @@ -21,7 +21,11 @@ const StateTag = props => { color = null; } return ( - + {state} ); diff --git a/src/models/invoices.js b/src/models/invoices.js index 2164850..c4864f1 100644 --- a/src/models/invoices.js +++ b/src/models/invoices.js @@ -1,6 +1,7 @@ import { initialize } from 'redux-form'; import { message } from 'antd'; import { keyBy } from 'lodash'; +import { push } from 'connected-react-router'; import * as invoicesService from '../services/invoices'; @@ -12,7 +13,7 @@ export default { }, effects: { - *list({ payload: { sort = ['number'] } = {} }, { put, call }) { + *list({ payload: { sort = [{ number: 'desc' }] } = {} }, { put, call }) { try { const response = yield call(invoicesService.list, sort); yield put({ type: 'listSuccess', data: response.docs }); @@ -21,12 +22,7 @@ export default { } }, - *details( - { - payload: { id }, - }, - { put, call } - ) { + *details({ payload: { id } }, { put, call }) { try { const response = yield call(invoicesService.details, id); yield put({ type: 'detailsSuccess', data: response }); @@ -35,12 +31,7 @@ export default { } }, - *initialize( - { - payload: { id }, - }, - { put, call } - ) { + *initialize({ payload: { id } }, { put, call }) { try { const response = yield call(invoicesService.details, id); yield put({ type: 'detailsSuccess', data: response }); @@ -50,12 +41,7 @@ export default { } }, - *state( - { - payload: { _id, _rev, state }, - }, - { put, call } - ) { + *state({ payload: { _id, _rev, state } }, { put, call }) { try { const response = yield call(invoicesService.save, { _id, _rev, state }); yield put({ type: 'detailsSuccess', data: response }); @@ -75,6 +61,17 @@ export default { message.error('Error saving invoice!', 5); } }, + + *remove({ data, resolve, reject }, { put, call }) { + try { + const response = yield call(invoicesService.remove, data); + yield put({ type: 'removeSuccess', data: response }); + message.success('Invoice deleted!', 5); + yield put(push('/invoices')); + } catch (e) { + message.error('Error deleting invoice!', 5); + } + }, }, reducers: { @@ -98,5 +95,17 @@ export default { }, }; }, + + removeSuccess(state, payload) { + const { data } = payload; + + let items = { ...state.items }; + delete items[data._id]; + + return { + ...state, + items: items, + }; + }, }, }; diff --git a/src/pages/invoices/$id/_layout.js b/src/pages/invoices/$id/_layout.js index 6d5083c..623dc5d 100644 --- a/src/pages/invoices/$id/_layout.js +++ b/src/pages/invoices/$id/_layout.js @@ -2,7 +2,7 @@ import { Component } from 'react'; import { compose } from 'redux'; import { connect } from 'dva'; import { Field, FieldArray, formValueSelector, reduxForm } from 'redux-form'; -import { Button, Col, Form, Icon, Layout, Row, Select, Menu, Dropdown } from 'antd'; +import { Button, Col, Form, Icon, Layout, Row, Select, Menu, Dropdown, Modal } from 'antd'; import { forEach, get, isString, includes, has, lowerCase, map } from 'lodash'; import moment from 'moment'; @@ -84,6 +84,24 @@ class InvoiceForm extends Component { }); }; + deleteConfirm = (_id, _rev) => { + Modal.confirm({ + title: 'Are you sure delete this invoice?', + okText: 'Yes', + okType: 'danger', + cancelText: 'No', + onOk: () => { + this.props.dispatch({ + type: 'invoices/remove', + data: { + _id, + _rev, + }, + }); + }, + }); + }; + printPDF = invoiceId => { const { ipcRenderer } = window.require('electron'); @@ -256,20 +274,29 @@ class InvoiceForm extends Component { - {!this.isNew() && invoice && ( - - - +
+ {!this.isNew() && ( + )} - +
} > + {!this.isNew() && invoice && ( + + + + )} {!this.isNew() && ( )} @@ -290,7 +317,7 @@ class InvoiceForm extends Component { style={{ marginTop: 10 }} > - Save invoice + Save
diff --git a/src/pages/invoices/index.js b/src/pages/invoices/index.js index 727674d..35c82bd 100644 --- a/src/pages/invoices/index.js +++ b/src/pages/invoices/index.js @@ -120,6 +120,7 @@ class Invoices extends Component { (a < b ? -1 : a === b ? 0 : 1)} render={invoice => ( diff --git a/src/services/invoices.js b/src/services/invoices.js index 451e708..78ab561 100644 --- a/src/services/invoices.js +++ b/src/services/invoices.js @@ -59,4 +59,10 @@ export async function save(data) { } } -export async function remove(id) {} +export async function remove(data) { + try { + return db.remove(data._id, data._rev); + } catch (error) { + console.log(error); + } +}