diff --git a/bodyshop_translations.babel b/bodyshop_translations.babel index 0a097dcfb..268434fa7 100644 --- a/bodyshop_translations.babel +++ b/bodyshop_translations.babel @@ -5979,6 +5979,27 @@ + + lineremarks + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + @@ -6005,6 +6026,27 @@ + + inthisorder + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + print false diff --git a/client/src/components/allocations-assignment/allocations-assignment.container.jsx b/client/src/components/allocations-assignment/allocations-assignment.container.jsx index 434f71ecb..914312109 100644 --- a/client/src/components/allocations-assignment/allocations-assignment.container.jsx +++ b/client/src/components/allocations-assignment/allocations-assignment.container.jsx @@ -24,7 +24,6 @@ export default function AllocationsAssignmentContainer({ notification["success"]({ message: t("employees.successes.save") }); - //TODO Better way to reset the field decorators? visibilityState[1](false); if (refetch) refetch(); }); diff --git a/client/src/components/allocations-bulk-assignment/allocations-bulk-assignment.component.jsx b/client/src/components/allocations-bulk-assignment/allocations-bulk-assignment.component.jsx new file mode 100644 index 000000000..5a926cd79 --- /dev/null +++ b/client/src/components/allocations-bulk-assignment/allocations-bulk-assignment.component.jsx @@ -0,0 +1,66 @@ +import { Button, Popover, Select } from "antd"; +import React from "react"; +import { useTranslation } from "react-i18next"; +import { connect } from "react-redux"; +import { createStructuredSelector } from "reselect"; +import { selectBodyshop } from "../../redux/user/user.selectors"; + +const mapStateToProps = createStructuredSelector({ + bodyshop: selectBodyshop +}); + +export default connect( + mapStateToProps, + null +)(function AllocationsBulkAssignmentComponent({ + bodyshop, + handleAssignment, + assignment, + setAssignment, + visibilityState +}) { + const { t } = useTranslation(); + + const onChange = e => { + console.log("e", e); + setAssignment({ ...assignment, employeeid: e }); + }; + + const [visibility, setVisibility] = visibilityState; + + const popContent = ( +
+ + + + +
+ ); + + return ( + + + + ); +}); diff --git a/client/src/components/allocations-bulk-assignment/allocations-bulk-assignment.container.jsx b/client/src/components/allocations-bulk-assignment/allocations-bulk-assignment.container.jsx new file mode 100644 index 000000000..0b73b2cb0 --- /dev/null +++ b/client/src/components/allocations-bulk-assignment/allocations-bulk-assignment.container.jsx @@ -0,0 +1,46 @@ +import React, { useState } from "react"; +import AllocationsBulkAssignment from "./allocations-bulk-assignment.component"; +import { useMutation } from "react-apollo"; +import { INSERT_ALLOCATION } from "../../graphql/allocations.queries"; +import { useTranslation } from "react-i18next"; +import { notification } from "antd"; + +export default function AllocationsBulkAssignmentContainer({ + jobLines, + refetch +}) { + const visibilityState = useState(false); + const { t } = useTranslation(); + const [assignment, setAssignment] = useState({ + employeeid: null + }); + const [insertAllocation] = useMutation(INSERT_ALLOCATION); + + const handleAssignment = () => { + const allocs = jobLines.reduce((acc, value) => { + acc.push({ + joblineid: value.id, + hours: parseFloat(value.mod_lb_hrs) || 0, + employeeid: assignment.employeeid + }); + return acc; + }, []); + + insertAllocation({ variables: { alloc: allocs } }).then(r => { + notification["success"]({ + message: t("employees.successes.save") + }); + visibilityState[1](false); + if (refetch) refetch(); + }); + }; + + return ( + + ); +} diff --git a/client/src/components/chat-window/chat-window.styles.scss b/client/src/components/chat-window/chat-window.styles.scss index 1b68074fb..a7e128649 100644 --- a/client/src/components/chat-window/chat-window.styles.scss +++ b/client/src/components/chat-window/chat-window.styles.scss @@ -20,7 +20,7 @@ .messages ul li { display: inline-block; clear: both; - float: left; + //float: left; margin: 5px 15px 5px 15px; width: calc(100% - 25px); font-size: 0.9em; diff --git a/client/src/components/job-detail-lines/job-lines.component.jsx b/client/src/components/job-detail-lines/job-lines.component.jsx index 0b11301b3..9ff03410f 100644 --- a/client/src/components/job-detail-lines/job-lines.component.jsx +++ b/client/src/components/job-detail-lines/job-lines.component.jsx @@ -6,7 +6,7 @@ import { alphaSort } from "../../utils/sorters"; //import EditableCell from "./job-lines-cell.component"; import AllocationsAssignmentContainer from "../allocations-assignment/allocations-assignment.container"; import PartsOrderModalContainer from "../parts-order-modal/parts-order-modal.container"; - +import AllocationsBulkAssignmentContainer from "../allocations-bulk-assignment/allocations-bulk-assignment.container"; export default function JobLinesComponent({ loading, refetch, @@ -166,11 +166,13 @@ export default function JobLinesComponent({ return (
- + {partsOrderModalVisible[0] ? ( + + ) : null} { @@ -188,13 +190,17 @@ export default function JobLinesComponent({ onClick={() => setPartsModalVisible(true)}> {t("parts.actions.order")} + ); }} {...formItemLayout} loading={loading} size='small' - pagination={{ position: "bottom", defaultPageSize: 50 }} + pagination={{ position: "top", defaultPageSize: 25 }} rowSelection={{ // selectedRowKeys: selectedLines, onSelect: (record, selected, selectedRows, nativeEvent) => diff --git a/client/src/components/jobs-available-supplement/jobs-available-supplement.container.jsx b/client/src/components/jobs-available-supplement/jobs-available-supplement.container.jsx index e9c189aa0..5f0469cdb 100644 --- a/client/src/components/jobs-available-supplement/jobs-available-supplement.container.jsx +++ b/client/src/components/jobs-available-supplement/jobs-available-supplement.container.jsx @@ -54,12 +54,13 @@ export default withRouter(function JobsAvailableSupplementContainer({ //create upsert job let supp = estData.data.available_jobs_by_pk.est_data; delete supp.joblines; + //TODO How to update the estimate lines. delete supp.owner; delete supp.vehicle; if (!importOptions.overrideHeaders) { delete supp["ins_ea"]; - //Strip out the header options + //TODO Remove all required fields. } updateJob({ @@ -101,12 +102,11 @@ export default withRouter(function JobsAvailableSupplementContainer({ setSelectedJob(null); }; - if (error) return ; + if (error) return ; return ( + message={t("jobs.labels.creating_new_job")}> { - console.log("value", value); - console.log("option", option); setPartsOrder({ ...partsOrder, vendorid: option.key }); }; @@ -52,6 +52,33 @@ export default function PartsOrderModalComponent({ }} /> + {t("parts_orders.labels.inthisorder")} + + ( + + //TODO Editable table/adding line remarks to the order. + ]}> + { + // + // } + // title={{item.name.last}} + // description='Ant Design, a design language for background applications, is refined by Ant UED Team' + // /> + } +
{`${item.line_desc}${ + item.oem_partno ? " | " + item.oem_partno : "" + }`}
+
+ )} + /> + setSendType(e.target.value)}> diff --git a/client/src/components/parts-order-modal/parts-order-modal.container.jsx b/client/src/components/parts-order-modal/parts-order-modal.container.jsx index 06cccf380..bd775f8f4 100644 --- a/client/src/components/parts-order-modal/parts-order-modal.container.jsx +++ b/client/src/components/parts-order-modal/parts-order-modal.container.jsx @@ -1,18 +1,18 @@ import { Modal, notification } from "antd"; import React, { useState } from "react"; -import { useQuery, useMutation } from "react-apollo"; +import { useMutation, useQuery } from "react-apollo"; +import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; import { createStructuredSelector } from "reselect"; -import { QUERY_ALL_VENDORS_FOR_ORDER } from "../../graphql/vendors.queries"; import { INSERT_NEW_PARTS_ORDERS } from "../../graphql/parts-orders.queries"; +import { QUERY_ALL_VENDORS_FOR_ORDER } from "../../graphql/vendors.queries"; import { - selectCurrentUser, - selectBodyshop + selectBodyshop, + selectCurrentUser } from "../../redux/user/user.selectors"; import AlertComponent from "../alert/alert.component"; import LoadingSpinner from "../loading-spinner/loading-spinner.component"; import PartsOrderModalComponent from "./parts-order-modal.component"; -import { useTranslation } from "react-i18next"; const mapStateToProps = createStructuredSelector({ currentUser: selectCurrentUser, @@ -28,23 +28,40 @@ export default connect( currentUser, bodyshop }) { - const [modalVisible, setModalVisible] = partsOrderModalVisible; - const { loading, error, data } = useQuery(QUERY_ALL_VENDORS_FOR_ORDER, { - fetchPolicy: "network-only", - skip: !modalVisible - }); const { t } = useTranslation(); - const [insertPartOrder] = useMutation(INSERT_NEW_PARTS_ORDERS); - const sendTypeState = useState("e"); + const [modalVisible, setModalVisible] = partsOrderModalVisible; + //set order lines to be a version of the incoming lines. + const orderLinesState = useState( + linesToOrder.reduce((acc, value) => { + acc.push({ + line_desc: value.line_desc, + oem_partno: value.oem_partno, + db_price: value.db_price, + act_price: value.act_price, + line_remarks: "Alalala", + joblineid: value.joblineid, + status: bodyshop.md_order_statuses.default_ordered || "Ordered*" + }); + return acc; + }, []) + ); + const orderLines = orderLinesState[0]; + + const sendTypeState = useState("e"); const partsOrderState = useState({ vendorid: null, jobid: jobId, user_email: currentUser.email }); - - console.log("sendTypeState[0]", sendTypeState[0]); const partsOrder = partsOrderState[0]; + + const { loading, error, data } = useQuery(QUERY_ALL_VENDORS_FOR_ORDER, { + fetchPolicy: "network-only", + skip: !modalVisible + }); + const [insertPartOrder] = useMutation(INSERT_NEW_PARTS_ORDERS); + const handleOk = () => { insertPartOrder({ variables: { @@ -53,19 +70,7 @@ export default connect( ...partsOrder, status: bodyshop.md_order_statuses.default_ordered || "Ordered*", parts_order_lines: { - data: linesToOrder.reduce((acc, value) => { - acc.push({ - line_desc: value.line_desc, - oem_partno: value.oem_partno, - db_price: value.db_price, - act_price: value.act_price, - line_remarks: "Alalala", - joblineid: value.joblineid, - status: - bodyshop.md_order_statuses.default_ordered || "Ordered*" - }); - return acc; - }, []) + data: orderLines } } ] @@ -96,6 +101,7 @@ export default connect( vendorList={(data && data.vendors) || []} state={partsOrderState} sendTypeState={sendTypeState} + orderLinesState={orderLinesState} />
diff --git a/client/src/translations/en_us/common.json b/client/src/translations/en_us/common.json index 70a7a1959..f8df11c07 100644 --- a/client/src/translations/en_us/common.json +++ b/client/src/translations/en_us/common.json @@ -385,10 +385,12 @@ "creating": "Error encountered when creating parts order. " }, "fields": { - "deliver_by": "Deliver By" + "deliver_by": "Deliver By", + "lineremarks": "Line Remarks" }, "labels": { "email": "Send by Email", + "inthisorder": "Parts in this Order", "print": "Show Printed Form" }, "successes": { diff --git a/client/src/translations/es/common.json b/client/src/translations/es/common.json index 270442c45..e93c6be9e 100644 --- a/client/src/translations/es/common.json +++ b/client/src/translations/es/common.json @@ -385,10 +385,12 @@ "creating": "Se encontró un error al crear el pedido de piezas." }, "fields": { - "deliver_by": "Entregado por" + "deliver_by": "Entregado por", + "lineremarks": "Comentarios de línea" }, "labels": { "email": "Enviar por correo electrónico", + "inthisorder": "Partes en este pedido", "print": "Mostrar formulario impreso" }, "successes": { diff --git a/client/src/translations/fr/common.json b/client/src/translations/fr/common.json index e64421219..e37f04001 100644 --- a/client/src/translations/fr/common.json +++ b/client/src/translations/fr/common.json @@ -385,10 +385,12 @@ "creating": "Erreur rencontrée lors de la création de la commande de pièces." }, "fields": { - "deliver_by": "Livrer par" + "deliver_by": "Livrer par", + "lineremarks": "Remarques sur la ligne" }, "labels": { "email": "Envoyé par email", + "inthisorder": "Pièces dans cette commande", "print": "Afficher le formulaire imprimé" }, "successes": {