From ecec2c0368b64a89f55ce142f2d26bd6fa3ac43f Mon Sep 17 00:00:00 2001 From: Patrick Fic Date: Wed, 1 Apr 2020 17:47:27 -0700 Subject: [PATCH] BOD-17 Added return car modal. --- .elasticbeanstalk/config.yml | 0 bodyshop_translations.babel | 89 +++++++++++++++++++ .../courtesy-car-contract-list.component.jsx | 12 +-- .../courtesy-car-return-modal.component.jsx | 49 ++++++++++ .../courtesy-car-return-modal.container.jsx | 86 ++++++++++++++++++ .../components/header/header.component.jsx | 2 +- .../vehicle-tag-popover.component.jsx | 2 +- client/src/graphql/cccontracts.queries.js | 22 +++++ client/src/graphql/jobs.queries.js | 1 + .../contract-detail.page.component.jsx | 38 +++++++- .../contract-detail.page.container.jsx | 74 ++++++++------- client/src/redux/modals/modals.reducer.js | 3 +- client/src/redux/modals/modals.selectors.js | 5 ++ client/src/translations/en_us/common.json | 6 ++ client/src/translations/es/common.json | 6 ++ client/src/translations/fr/common.json | 6 ++ .../down.yaml | 5 ++ .../up.yaml | 6 ++ .../down.yaml | 51 +++++++++++ .../up.yaml | 52 +++++++++++ .../down.yaml | 49 ++++++++++ .../up.yaml | 50 +++++++++++ .../down.yaml | 51 +++++++++++ .../up.yaml | 52 +++++++++++ package.json | 3 +- 25 files changed, 672 insertions(+), 48 deletions(-) create mode 100644 .elasticbeanstalk/config.yml create mode 100644 client/src/components/courtesy-car-return-modal/courtesy-car-return-modal.component.jsx create mode 100644 client/src/components/courtesy-car-return-modal/courtesy-car-return-modal.container.jsx create mode 100644 hasura/migrations/1585767116722_alter_table_public_courtesycars_add_column_mileage/down.yaml create mode 100644 hasura/migrations/1585767116722_alter_table_public_courtesycars_add_column_mileage/up.yaml create mode 100644 hasura/migrations/1585767133843_update_permission_user_public_table_courtesycars/down.yaml create mode 100644 hasura/migrations/1585767133843_update_permission_user_public_table_courtesycars/up.yaml create mode 100644 hasura/migrations/1585767138926_update_permission_user_public_table_courtesycars/down.yaml create mode 100644 hasura/migrations/1585767138926_update_permission_user_public_table_courtesycars/up.yaml create mode 100644 hasura/migrations/1585767144286_update_permission_user_public_table_courtesycars/down.yaml create mode 100644 hasura/migrations/1585767144286_update_permission_user_public_table_courtesycars/up.yaml diff --git a/.elasticbeanstalk/config.yml b/.elasticbeanstalk/config.yml new file mode 100644 index 000000000..e69de29bb diff --git a/bodyshop_translations.babel b/bodyshop_translations.babel index 7a2e7ce18..883a4e1d3 100644 --- a/bodyshop_translations.babel +++ b/bodyshop_translations.babel @@ -1981,6 +1981,27 @@ errors + + returning + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + saving false @@ -2133,6 +2154,27 @@ + + driver + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + driver_addr1 false @@ -2591,6 +2633,32 @@ courtesycars + + actions + + + return + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + errors @@ -3260,6 +3328,27 @@ + + return + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + vehicle false diff --git a/client/src/components/courtesy-car-contract-list/courtesy-car-contract-list.component.jsx b/client/src/components/courtesy-car-contract-list/courtesy-car-contract-list.component.jsx index 5a9e6b87d..c3f499686 100644 --- a/client/src/components/courtesy-car-contract-list/courtesy-car-contract-list.component.jsx +++ b/client/src/components/courtesy-car-contract-list/courtesy-car-contract-list.component.jsx @@ -16,13 +16,15 @@ export default function CourtesyCarContractListComponent({ contracts }) { const columns = [ { title: t("contracts.fields.agreementnumber"), - dataIndex: "id", - key: "id", - sorter: (a, b) => alphaSort(a.id, b.id), - sortOrder: state.sortedInfo.columnKey === "id" && state.sortedInfo.order, + dataIndex: "agreementnumber", + key: "agreementnumber", + sorter: (a, b) => a.agreementnumber - b.agreementnumber, + sortOrder: + state.sortedInfo.columnKey === "agreementnumber" && + state.sortedInfo.order, render: (text, record) => ( - {record.id || ""} + {record.agreementnumber || ""} ) }, diff --git a/client/src/components/courtesy-car-return-modal/courtesy-car-return-modal.component.jsx b/client/src/components/courtesy-car-return-modal/courtesy-car-return-modal.component.jsx new file mode 100644 index 000000000..1a516a9ad --- /dev/null +++ b/client/src/components/courtesy-car-return-modal/courtesy-car-return-modal.component.jsx @@ -0,0 +1,49 @@ +import { Form, DatePicker, InputNumber } from "antd"; +import React from "react"; +import { useTranslation } from "react-i18next"; +import CourtesyCarFuelSlider from "../courtesy-car-fuel-select/courtesy-car-fuel-select.component"; + +export default function CourtesyCarReturnModalComponent() { + const { t } = useTranslation(); + + return ( +
+ + + + + + + + + +
+ ); +} diff --git a/client/src/components/courtesy-car-return-modal/courtesy-car-return-modal.container.jsx b/client/src/components/courtesy-car-return-modal/courtesy-car-return-modal.container.jsx new file mode 100644 index 000000000..15c97b824 --- /dev/null +++ b/client/src/components/courtesy-car-return-modal/courtesy-car-return-modal.container.jsx @@ -0,0 +1,86 @@ +import { Form, Modal, notification } from "antd"; +import React from "react"; +import { useTranslation } from "react-i18next"; +import { connect } from "react-redux"; +import { createStructuredSelector } from "reselect"; +import { toggleModalVisible } from "../../redux/modals/modals.actions"; +import { selectCourtesyCarReturn } from "../../redux/modals/modals.selectors"; +import { selectBodyshop } from "../../redux/user/user.selectors"; +import CourtesyCarReturnModalComponent from "./courtesy-car-return-modal.component"; +import moment from "moment"; +import { RETURN_CONTRACT } from "../../graphql/cccontracts.queries"; +import { useMutation } from "@apollo/react-hooks"; + +const mapStateToProps = createStructuredSelector({ + courtesyCarReturnModal: selectCourtesyCarReturn, + bodyshop: selectBodyshop +}); + +const mapDispatchToProps = dispatch => ({ + toggleModalVisible: () => dispatch(toggleModalVisible("courtesyCarReturn")) +}); + +export function InvoiceEnterModalContainer({ + courtesyCarReturnModal, + toggleModalVisible, + bodyshop +}) { + const { visible, context, actions } = courtesyCarReturnModal; + const { t } = useTranslation(); + const [form] = Form.useForm(); + const [updateContract] = useMutation(RETURN_CONTRACT); + const handleFinish = values => { + console.log("Finish", values); + + updateContract({ + variables: { + contractId: context.contractId, + cccontract: { + kmend: values.kmend, + actualreturn: values.actualreturn, + status: "contracts.status.returned" + }, + courtesycarid: context.courtesyCarId, + courtesycar: { + status: "courtesycars.status.in", + fuel: values.fuel, + mileage: values.kmend + } + } + }) + .then(r => { + if (actions.refetch) actions.refetch(); + toggleModalVisible(); + }) + .catch(error => { + notification["error"]({ + message: t("contracts.errors.returning", { error: error }) + }); + }); + }; + + return ( + toggleModalVisible()} + width={"90%"} + okText={t("general.actions.save")} + onOk={() => form.submit()} + okButtonProps={{ htmlType: "submit" }} + > +
+ + +
+ ); +} + +export default connect( + mapStateToProps, + mapDispatchToProps +)(InvoiceEnterModalContainer); diff --git a/client/src/components/header/header.component.jsx b/client/src/components/header/header.component.jsx index c5bd6216a..b00ea95ea 100644 --- a/client/src/components/header/header.component.jsx +++ b/client/src/components/header/header.component.jsx @@ -25,7 +25,7 @@ export default ({ Shop Logo ) : null} - + {landingHeader ? ( - + ); diff --git a/client/src/graphql/cccontracts.queries.js b/client/src/graphql/cccontracts.queries.js index 5cc47d328..b180359f3 100644 --- a/client/src/graphql/cccontracts.queries.js +++ b/client/src/graphql/cccontracts.queries.js @@ -22,6 +22,28 @@ export const UPDATE_CONTRACT = gql` } } `; +export const RETURN_CONTRACT = gql` + mutation RETURN_CONTRACT( + $contractId: uuid! + $cccontract: cccontracts_set_input! + $courtesycarid: uuid! + $courtesycar: courtesycars_set_input! + ) { + update_cccontracts(where: { id: { _eq: $contractId } }, _set: $cccontract) { + returning { + id + } + } + update_courtesycars( + where: { id: { _eq: $courtesycarid } } + _set: $courtesycar + ) { + returning { + id + } + } + } +`; export const QUERY_CONTRACT_BY_PK = gql` query QUERY_CONTRACT_BY_PK($id: uuid!) { diff --git a/client/src/graphql/jobs.queries.js b/client/src/graphql/jobs.queries.js index 6e18f1e83..3dde172f1 100644 --- a/client/src/graphql/jobs.queries.js +++ b/client/src/graphql/jobs.queries.js @@ -231,6 +231,7 @@ export const GET_JOB_BY_PK = gql` status start scheduledreturn + agreementnumber } appointments_aggregate { aggregate { diff --git a/client/src/pages/contract-detail/contract-detail.page.component.jsx b/client/src/pages/contract-detail/contract-detail.page.component.jsx index 9f36f3b6b..83b803681 100644 --- a/client/src/pages/contract-detail/contract-detail.page.component.jsx +++ b/client/src/pages/contract-detail/contract-detail.page.component.jsx @@ -1,20 +1,50 @@ +import { Button, Typography } from "antd"; import React from "react"; -import ContractFormComponent from "../../components/contract-form/contract-form.component"; import { useTranslation } from "react-i18next"; -import { Button } from "antd"; -import ContractJobBlock from "../../components/contract-job-block/contract-job-block.component"; +import { connect } from "react-redux"; import ContractCourtesyCarBlock from "../../components/contract-courtesy-car-block/contract-courtesy-car-block.component"; +import ContractFormComponent from "../../components/contract-form/contract-form.component"; +import ContractJobBlock from "../../components/contract-job-block/contract-job-block.component"; +import { setModalContext } from "../../redux/modals/modals.actions"; -export default function ContractDetailPage({ job, courtesyCar }) { +const mapDispatchToProps = dispatch => ({ + setCourtesyCarReturnModalContext: context => + dispatch(setModalContext({ context: context, modal: "courtesyCarReturn" })) +}); + +export function ContractDetailPage({ + contract, + job, + courtesyCar, + setCourtesyCarReturnModalContext, + refetch +}) { const { t } = useTranslation(); return (
+ {`Agreement ${(contract && contract.agreementnumber) || + ""}`} +
); } +export default connect(null, mapDispatchToProps)(ContractDetailPage); diff --git a/client/src/pages/contract-detail/contract-detail.page.container.jsx b/client/src/pages/contract-detail/contract-detail.page.container.jsx index 6842fd67c..fb8278739 100644 --- a/client/src/pages/contract-detail/contract-detail.page.container.jsx +++ b/client/src/pages/contract-detail/contract-detail.page.container.jsx @@ -10,6 +10,7 @@ import { UPDATE_CONTRACT } from "../../graphql/cccontracts.queries"; import ContractDetailPageComponent from "./contract-detail.page.component"; +import CourtesyCarReturnModalContainer from "../../components/courtesy-car-return-modal/courtesy-car-return-modal.container"; export default function ContractDetailPageContainer() { const { t } = useTranslation(); @@ -17,7 +18,7 @@ export default function ContractDetailPageContainer() { const [form] = Form.useForm(); const { contractId } = useParams(); - const { loading, error, data } = useQuery(QUERY_CONTRACT_BY_PK, { + const { loading, error, data, refetch } = useQuery(QUERY_CONTRACT_BY_PK, { variables: { id: contractId } }); @@ -27,7 +28,7 @@ export default function ContractDetailPageContainer() { : error ? t("titles.app") : t("titles.contracts-detail", { - id: (data && data.cccontracts_by_pk.id) || "" + id: (data && data.cccontracts_by_pk.agreementnumber) || "" }); }, [t, data, error, loading]); @@ -51,37 +52,42 @@ export default function ContractDetailPageContainer() { if (error) return ; return ( -
- - +
+ +
+ + +
); } diff --git a/client/src/redux/modals/modals.reducer.js b/client/src/redux/modals/modals.reducer.js index 7e79e844b..bb3913f49 100644 --- a/client/src/redux/modals/modals.reducer.js +++ b/client/src/redux/modals/modals.reducer.js @@ -10,7 +10,8 @@ const baseModal = { const INITIAL_STATE = { jobLineEdit: { ...baseModal }, - invoiceEnter: { ...baseModal } + invoiceEnter: { ...baseModal }, + courtesyCarReturn: { ...baseModal } }; const modalsReducer = (state = INITIAL_STATE, action) => { diff --git a/client/src/redux/modals/modals.selectors.js b/client/src/redux/modals/modals.selectors.js index 7634faf2b..7c9c3daf4 100644 --- a/client/src/redux/modals/modals.selectors.js +++ b/client/src/redux/modals/modals.selectors.js @@ -12,3 +12,8 @@ export const selectInvoiceEnterModal = createSelector( modals => modals.invoiceEnter ); +export const selectCourtesyCarReturn = createSelector( + [selectModals], + modals => modals.courtesyCarReturn +); + diff --git a/client/src/translations/en_us/common.json b/client/src/translations/en_us/common.json index 2f1cf27e8..32c8cea3a 100644 --- a/client/src/translations/en_us/common.json +++ b/client/src/translations/en_us/common.json @@ -141,6 +141,7 @@ }, "contracts": { "errors": { + "returning": "Error returning courtesy car. {{error}}", "saving": "Error saving contract. {{error}}", "selectjobandcar": "Please ensure both a car and job are selected." }, @@ -150,6 +151,7 @@ "cc_cardholder": "Cardholder Name", "cc_expiry": "Credit Card Expiry Date", "cc_num": "Credit Card Number", + "driver": "Driver", "driver_addr1": "Driver Address 1", "driver_addr2": "Driver Address 2", "driver_city": "Driver City", @@ -178,6 +180,9 @@ } }, "courtesycars": { + "actions": { + "return": "Return Car" + }, "errors": { "saving": "Error saving courtesy card. {{error}}" }, @@ -216,6 +221,7 @@ "empty": "Empty", "full": "Full" }, + "return": "Return Courtesy Car", "vehicle": "Vehicle Description" }, "status": { diff --git a/client/src/translations/es/common.json b/client/src/translations/es/common.json index c211b5b21..6ef9e3687 100644 --- a/client/src/translations/es/common.json +++ b/client/src/translations/es/common.json @@ -141,6 +141,7 @@ }, "contracts": { "errors": { + "returning": "", "saving": "", "selectjobandcar": "" }, @@ -150,6 +151,7 @@ "cc_cardholder": "", "cc_expiry": "", "cc_num": "", + "driver": "", "driver_addr1": "", "driver_addr2": "", "driver_city": "", @@ -178,6 +180,9 @@ } }, "courtesycars": { + "actions": { + "return": "" + }, "errors": { "saving": "" }, @@ -216,6 +221,7 @@ "empty": "", "full": "" }, + "return": "", "vehicle": "" }, "status": { diff --git a/client/src/translations/fr/common.json b/client/src/translations/fr/common.json index 2a867a2b4..6118fb29e 100644 --- a/client/src/translations/fr/common.json +++ b/client/src/translations/fr/common.json @@ -141,6 +141,7 @@ }, "contracts": { "errors": { + "returning": "", "saving": "", "selectjobandcar": "" }, @@ -150,6 +151,7 @@ "cc_cardholder": "", "cc_expiry": "", "cc_num": "", + "driver": "", "driver_addr1": "", "driver_addr2": "", "driver_city": "", @@ -178,6 +180,9 @@ } }, "courtesycars": { + "actions": { + "return": "" + }, "errors": { "saving": "" }, @@ -216,6 +221,7 @@ "empty": "", "full": "" }, + "return": "", "vehicle": "" }, "status": { diff --git a/hasura/migrations/1585767116722_alter_table_public_courtesycars_add_column_mileage/down.yaml b/hasura/migrations/1585767116722_alter_table_public_courtesycars_add_column_mileage/down.yaml new file mode 100644 index 000000000..9ba2124c5 --- /dev/null +++ b/hasura/migrations/1585767116722_alter_table_public_courtesycars_add_column_mileage/down.yaml @@ -0,0 +1,5 @@ +- args: + cascade: false + read_only: false + sql: ALTER TABLE "public"."courtesycars" DROP COLUMN "mileage"; + type: run_sql diff --git a/hasura/migrations/1585767116722_alter_table_public_courtesycars_add_column_mileage/up.yaml b/hasura/migrations/1585767116722_alter_table_public_courtesycars_add_column_mileage/up.yaml new file mode 100644 index 000000000..126709423 --- /dev/null +++ b/hasura/migrations/1585767116722_alter_table_public_courtesycars_add_column_mileage/up.yaml @@ -0,0 +1,6 @@ +- args: + cascade: false + read_only: false + sql: ALTER TABLE "public"."courtesycars" ADD COLUMN "mileage" numeric NOT NULL + DEFAULT 0; + type: run_sql diff --git a/hasura/migrations/1585767133843_update_permission_user_public_table_courtesycars/down.yaml b/hasura/migrations/1585767133843_update_permission_user_public_table_courtesycars/down.yaml new file mode 100644 index 000000000..b835778b0 --- /dev/null +++ b/hasura/migrations/1585767133843_update_permission_user_public_table_courtesycars/down.yaml @@ -0,0 +1,51 @@ +- args: + role: user + table: + name: courtesycars + schema: public + type: drop_insert_permission +- args: + permission: + check: + bodyshop: + associations: + _and: + - user: + authid: + _eq: X-Hasura-User-Id + - active: + _eq: true + columns: + - id + - created_at + - updated_at + - bodyshopid + - make + - model + - year + - plate + - color + - vin + - fleetnumber + - purchasedate + - servicestartdate + - serviceenddate + - leaseenddate + - status + - nextservicekm + - nextservicedate + - damage + - notes + - fuel + - registrationexpires + - insuranceexpires + - dailycost + localPresets: + - key: "" + value: "" + set: {} + role: user + table: + name: courtesycars + schema: public + type: create_insert_permission diff --git a/hasura/migrations/1585767133843_update_permission_user_public_table_courtesycars/up.yaml b/hasura/migrations/1585767133843_update_permission_user_public_table_courtesycars/up.yaml new file mode 100644 index 000000000..fe762dd69 --- /dev/null +++ b/hasura/migrations/1585767133843_update_permission_user_public_table_courtesycars/up.yaml @@ -0,0 +1,52 @@ +- args: + role: user + table: + name: courtesycars + schema: public + type: drop_insert_permission +- args: + permission: + check: + bodyshop: + associations: + _and: + - user: + authid: + _eq: X-Hasura-User-Id + - active: + _eq: true + columns: + - id + - created_at + - updated_at + - bodyshopid + - make + - model + - year + - plate + - color + - vin + - fleetnumber + - purchasedate + - servicestartdate + - serviceenddate + - leaseenddate + - status + - nextservicekm + - nextservicedate + - damage + - notes + - fuel + - registrationexpires + - insuranceexpires + - dailycost + - mileage + localPresets: + - key: "" + value: "" + set: {} + role: user + table: + name: courtesycars + schema: public + type: create_insert_permission diff --git a/hasura/migrations/1585767138926_update_permission_user_public_table_courtesycars/down.yaml b/hasura/migrations/1585767138926_update_permission_user_public_table_courtesycars/down.yaml new file mode 100644 index 000000000..06a3bc23c --- /dev/null +++ b/hasura/migrations/1585767138926_update_permission_user_public_table_courtesycars/down.yaml @@ -0,0 +1,49 @@ +- args: + role: user + table: + name: courtesycars + schema: public + type: drop_select_permission +- args: + permission: + allow_aggregations: false + columns: + - insuranceexpires + - leaseenddate + - nextservicedate + - purchasedate + - registrationexpires + - serviceenddate + - servicestartdate + - dailycost + - fuel + - nextservicekm + - color + - damage + - fleetnumber + - make + - model + - notes + - plate + - status + - vin + - year + - created_at + - updated_at + - bodyshopid + - id + computed_fields: [] + filter: + bodyshop: + associations: + _and: + - user: + authid: + _eq: X-Hasura-User-Id + - active: + _eq: true + role: user + table: + name: courtesycars + schema: public + type: create_select_permission diff --git a/hasura/migrations/1585767138926_update_permission_user_public_table_courtesycars/up.yaml b/hasura/migrations/1585767138926_update_permission_user_public_table_courtesycars/up.yaml new file mode 100644 index 000000000..b0294a184 --- /dev/null +++ b/hasura/migrations/1585767138926_update_permission_user_public_table_courtesycars/up.yaml @@ -0,0 +1,50 @@ +- args: + role: user + table: + name: courtesycars + schema: public + type: drop_select_permission +- args: + permission: + allow_aggregations: false + columns: + - insuranceexpires + - leaseenddate + - nextservicedate + - purchasedate + - registrationexpires + - serviceenddate + - servicestartdate + - dailycost + - fuel + - mileage + - nextservicekm + - color + - damage + - fleetnumber + - make + - model + - notes + - plate + - status + - vin + - year + - created_at + - updated_at + - bodyshopid + - id + computed_fields: [] + filter: + bodyshop: + associations: + _and: + - user: + authid: + _eq: X-Hasura-User-Id + - active: + _eq: true + role: user + table: + name: courtesycars + schema: public + type: create_select_permission diff --git a/hasura/migrations/1585767144286_update_permission_user_public_table_courtesycars/down.yaml b/hasura/migrations/1585767144286_update_permission_user_public_table_courtesycars/down.yaml new file mode 100644 index 000000000..b2f45d67c --- /dev/null +++ b/hasura/migrations/1585767144286_update_permission_user_public_table_courtesycars/down.yaml @@ -0,0 +1,51 @@ +- args: + role: user + table: + name: courtesycars + schema: public + type: drop_update_permission +- args: + permission: + columns: + - insuranceexpires + - leaseenddate + - nextservicedate + - purchasedate + - registrationexpires + - serviceenddate + - servicestartdate + - dailycost + - fuel + - nextservicekm + - color + - damage + - fleetnumber + - make + - model + - notes + - plate + - status + - vin + - year + - created_at + - updated_at + - bodyshopid + - id + filter: + bodyshop: + associations: + _and: + - user: + authid: + _eq: X-Hasura-User-Id + - active: + _eq: true + localPresets: + - key: "" + value: "" + set: {} + role: user + table: + name: courtesycars + schema: public + type: create_update_permission diff --git a/hasura/migrations/1585767144286_update_permission_user_public_table_courtesycars/up.yaml b/hasura/migrations/1585767144286_update_permission_user_public_table_courtesycars/up.yaml new file mode 100644 index 000000000..86620f18d --- /dev/null +++ b/hasura/migrations/1585767144286_update_permission_user_public_table_courtesycars/up.yaml @@ -0,0 +1,52 @@ +- args: + role: user + table: + name: courtesycars + schema: public + type: drop_update_permission +- args: + permission: + columns: + - insuranceexpires + - leaseenddate + - nextservicedate + - purchasedate + - registrationexpires + - serviceenddate + - servicestartdate + - dailycost + - fuel + - mileage + - nextservicekm + - color + - damage + - fleetnumber + - make + - model + - notes + - plate + - status + - vin + - year + - created_at + - updated_at + - bodyshopid + - id + filter: + bodyshop: + associations: + _and: + - user: + authid: + _eq: X-Hasura-User-Id + - active: + _eq: true + localPresets: + - key: "" + value: "" + set: {} + role: user + table: + name: courtesycars + schema: public + type: create_update_permission diff --git a/package.json b/package.json index 6c64a81ec..7579353ea 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,6 @@ "devDependencies": { "concurrently": "^5.1.0", "eslint": "^6.8.0", - "eslint-plugin-promise": "^4.2.1", - "hasura-cli": "^1.1.0" + "eslint-plugin-promise": "^4.2.1" } }