Added base jobline edit modal. To be confirmed if required.

This commit is contained in:
Patrick Fic
2020-02-21 09:27:05 -08:00
parent a51915c0ea
commit 1476781fa8
14 changed files with 211 additions and 29 deletions

View File

@@ -1,4 +1,4 @@
<babeledit_project version="1.2" be_version="2.6.1">
<babeledit_project be_version="2.6.1" version="1.2">
<!--
BabelEdit project file
@@ -1701,6 +1701,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>line_ind</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>mod_lb_hrs</name>
<definition_loaded>false</definition_loaded>

View File

@@ -13,6 +13,7 @@ export default connect(
mapStateToProps,
null
)(function AllocationsBulkAssignmentComponent({
disabled,
bodyshop,
handleAssignment,
assignment,
@@ -58,7 +59,7 @@ export default connect(
return (
<Popover content={popContent} visible={visibility}>
<Button onClick={() => setVisibility(true)}>
<Button disabled={disabled} onClick={() => setVisibility(true)}>
{t("allocations.actions.assign")}
</Button>
</Popover>

View File

@@ -37,6 +37,7 @@ export default function AllocationsBulkAssignmentContainer({
return (
<AllocationsBulkAssignment
disabled={jobLines.length > 0 ? false : true}
handleAssignment={handleAssignment}
assignment={assignment}
setAssignment={setAssignment}

View File

@@ -2,18 +2,14 @@ import { Button, Modal, notification } from "antd";
import axios from "axios";
import React, { useEffect, useState } from "react";
import { useLazyQuery } from "react-apollo";
import { renderEmail } from "react-html-email";
import ReactDOMServer from "react-dom/server";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { toggleEmailOverlayVisible } from "../../redux/email/email.actions";
import {
selectEmailConfig,
selectEmailVisible
} from "../../redux/email/email.selectors.js";
import { selectEmailConfig, selectEmailVisible } from "../../redux/email/email.selectors.js";
import LoadingSpinner from "../loading-spinner/loading-spinner.component";
import EmailOverlayComponent from "./email-overlay.component";
import ReactDOMServer from "react-dom/server";
const mapStateToProps = createStructuredSelector({
modalVisible: selectEmailVisible,

View File

@@ -8,6 +8,7 @@ import { Link } from "react-router-dom";
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";
import JobLineUpsertModalContainer from "../job-lines-upsert-modal/job-lines-upsert-modal.container";
export default function JobLinesComponent({
loading,
refetch,
@@ -16,7 +17,9 @@ export default function JobLinesComponent({
selectedLines,
setSelectedLines,
partsOrderModalVisible,
jobId
jobId,
editLineModalVisible,
lineToEdit
}) {
const [state, setState] = useState({
sortedInfo: {}
@@ -45,7 +48,8 @@ export default function JobLinesComponent({
sortOrder:
state.sortedInfo.columnKey === "line_desc" && state.sortedInfo.order,
ellipsis: true,
editable: true
editable: true,
width: "20%"
},
{
title: t("joblines.fields.oem_partno"),
@@ -60,7 +64,7 @@ export default function JobLinesComponent({
state.sortedInfo.columnKey === "oem_partno" && state.sortedInfo.order,
ellipsis: true,
editable: true,
width: "20%",
width: "10%",
render: (text, record) => (
<span>
{record.oem_partno ? record.oem_partno : record.op_code_desc}
@@ -76,7 +80,15 @@ export default function JobLinesComponent({
state.sortedInfo.columnKey === "part_type" && state.sortedInfo.order,
ellipsis: true,
editable: true,
width: "10%"
width: "7%"
},
{
title: t("joblines.fields.line_ind"),
dataIndex: "line_ind",
key: "line_ind",
sorter: (a, b) => alphaSort(a.line_ind, b.line_ind),
sortOrder:
state.sortedInfo.columnKey === "line_ind" && state.sortedInfo.order
},
{
title: t("joblines.fields.db_price"),
@@ -86,7 +98,7 @@ export default function JobLinesComponent({
sortOrder:
state.sortedInfo.columnKey === "db_price" && state.sortedInfo.order,
ellipsis: true,
width: "10%",
width: "8%",
render: (text, record) => (
<CurrencyFormatter>{record.db_price}</CurrencyFormatter>
)
@@ -99,7 +111,7 @@ export default function JobLinesComponent({
sortOrder:
state.sortedInfo.columnKey === "act_price" && state.sortedInfo.order,
ellipsis: true,
width: "10%",
width: "8%",
render: (text, record) => (
<CurrencyFormatter>{record.act_price}</CurrencyFormatter>
)
@@ -124,6 +136,7 @@ export default function JobLinesComponent({
title: t("allocations.fields.employee"),
dataIndex: "employee",
key: "employee",
width: "10%",
sorter: (a, b) => a.act_price - b.act_price, //TODO Fix employee sorting.
sortOrder:
state.sortedInfo.columnKey === "employee" && state.sortedInfo.order,
@@ -152,7 +165,13 @@ export default function JobLinesComponent({
key: "actions",
render: (text, record) => (
<span>
<Button>{t("general.actions.edit")}</Button>
<Button
onClick={() => {
lineToEdit[1](record);
editLineModalVisible[1](true);
}}>
{t("general.actions.edit")}
</Button>
</span>
)
}
@@ -175,14 +194,20 @@ export default function JobLinesComponent({
return (
<div>
{partsOrderModalVisible[0] ? (
<PartsOrderModalContainer
partsOrderModalVisible={partsOrderModalVisible}
linesToOrder={selectedLines}
refetch={refetch}
jobId={jobId}
/>
) : null}
<PartsOrderModalContainer
partsOrderModalVisible={partsOrderModalVisible}
linesToOrder={selectedLines}
refetch={refetch}
jobId={jobId}
/>
<JobLineUpsertModalContainer
jobId={jobId}
visible={editLineModalVisible[0]}
changeVisibility={editLineModalVisible[1]}
refetch={refetch}
existingLine={lineToEdit[0]}
/>
<Table
title={() => {

View File

@@ -16,6 +16,9 @@ export default function JobLinesContainer({ jobId }) {
const [searchText, setSearchText] = useState("");
const [selectedLines, setSelectedLines] = useState([]);
const partsOrderModalVisible = useState(false);
const editLineModalVisible = useState(false);
const lineToEdit = useState({});
if (error) return <AlertComponent message={error.message} type='error' />;
return (
@@ -58,6 +61,8 @@ export default function JobLinesContainer({ jobId }) {
setSelectedLines={setSelectedLines}
partsOrderModalVisible={partsOrderModalVisible}
jobId={jobId}
editLineModalVisible={editLineModalVisible}
lineToEdit={lineToEdit}
/>
);
}

View File

@@ -0,0 +1,33 @@
import { Input, Modal } from "antd";
import React from "react";
import { useTranslation } from "react-i18next";
export default function JobLinesUpsertModalComponent({
visible,
changeVisibility,
lineState,
setLineState,
updateExistingLine,
insertNewLine
}) {
const { t } = useTranslation();
const handleChange = e => {
setLineState({ ...lineState, [e.target.name]: e.target.value });
};
return (
<Modal
title={
lineState.id ? t("joblines.actions.edit") : t("joblines.actions.new")
}
visible={visible}
okText={t("general.labels.save")}
onOk={() => {
lineState.id ? updateExistingLine() : insertNewLine();
}}
onCancel={() => {
changeVisibility(false);
}}>
<Input.TextArea rows={8} value={lineState.text} onChange={handleChange} />
</Modal>
);
}

View File

@@ -0,0 +1,72 @@
import { notification } from "antd";
import React, { useEffect, useState } from "react";
import { useMutation } from "react-apollo";
import { useTranslation } from "react-i18next";
import {
INSERT_NEW_JOB_LINE,
UPDATE_JOB_LINE
} from "../../graphql/jobs-lines.queries";
import JobLinesUpdsertModal from "./job-lines-upsert-modal.component";
export default function JobLinesUpsertModalContainer({
jobId,
visible,
changeVisibility,
refetch,
existingLine
}) {
const { t } = useTranslation();
const [insertJobLine] = useMutation(INSERT_NEW_JOB_LINE);
const [updateJobLine] = useMutation(UPDATE_JOB_LINE);
const [lineState, setLineState] = useState({});
useEffect(() => {
//Required to prevent infinite looping.
if (existingLine) {
setLineState(existingLine);
}
}, [existingLine]);
const insertNewLine = () => {
insertJobLine({
variables: {
lineInput: [{ ...lineState, jobid: jobId }]
}
}).then(r => {
refetch();
changeVisibility(!visible);
notification["success"]({
message: t("joblines.successes.create")
});
});
};
const updateExistingLine = () => {
//Required, otherwise unable to spread in new note prop.
delete lineState.__typename;
updateJobLine({
variables: {
lineId: lineState.id,
line: lineState
}
}).then(r => {
notification["success"]({
message: t("joblines.successes.updated")
});
});
refetch();
changeVisibility(!visible);
};
console.log("lineSTate", lineState);
return (
<JobLinesUpdsertModal
visible={visible}
changeVisibility={changeVisibility}
updateExistingLine={updateExistingLine}
insertNewLine={insertNewLine}
lineState={lineState}
setLineState={setLineState}
/>
);
}

View File

@@ -5,12 +5,20 @@ import { useTranslation } from "react-i18next";
import { INSERT_NEW_NOTE, UPDATE_NOTE } from "../../graphql/notes.queries";
import NoteUpsertModalComponent from "./note-upsert-modal.component";
export default function NoteUpsertModalContainer({
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { selectCurrentUser } from "../../redux/user/user.selectors";
const mapStateToProps = createStructuredSelector({
currentUser: selectCurrentUser
});
export default connect (mapStateToProps,null)( function NoteUpsertModalContainer({
jobId,
visible,
changeVisibility,
refetch,
existingNote
existingNote,currentUser
}) {
const { t } = useTranslation();
const [insertNote] = useMutation(INSERT_NEW_NOTE);
@@ -33,7 +41,7 @@ export default function NoteUpsertModalContainer({
insertNote({
variables: {
noteInput: [
{ ...noteState, jobid: jobId, created_by: "patrick@bodyshop.app" } //TODO Fix the created by.
{ ...noteState, jobid: jobId, created_by: currentUser.email }
]
}
}).then(r => {
@@ -73,3 +81,4 @@ export default function NoteUpsertModalContainer({
/>
);
}
);

View File

@@ -52,3 +52,22 @@ export const UPDATE_JOB_LINE_STATUS = gql`
}
}
`;
export const INSERT_NEW_JOB_LINE = gql`
mutation INSERT_NEW_JOB_LINE($lineInput: [joblines_insert_input!]!) {
insert_joblines(objects: $lineInput) {
returning {
id
}
}
}
`;
export const UPDATE_JOB_LINE = gql`
mutation UPDATE_JOB_LINE($lineId: uuid!, $line: joblines_set_input!) {
update_joblines(where: { id: { _eq: $lineId } }, _set: $line) {
returning {
id
}
}
}
`;

View File

@@ -140,6 +140,7 @@
"act_price": "Actual Price",
"db_price": "Database Price",
"line_desc": "Line Description",
"line_ind": "S#",
"mod_lb_hrs": "Labor Hours",
"oem_partno": "OEM Part #",
"part_type": "Part Type",

View File

@@ -140,6 +140,7 @@
"act_price": "Precio actual",
"db_price": "Precio de base de datos",
"line_desc": "Descripción de línea",
"line_ind": "S#",
"mod_lb_hrs": "Horas laborales",
"oem_partno": "OEM parte #",
"part_type": "Tipo de parte",

View File

@@ -140,6 +140,7 @@
"act_price": "Prix actuel",
"db_price": "Prix de la base de données",
"line_desc": "Description de la ligne",
"line_ind": "S#",
"mod_lb_hrs": "Heures de travail",
"oem_partno": "Pièce OEM #",
"part_type": "Type de pièce",

View File

@@ -2,10 +2,7 @@ export function alphaSort(a, b) {
let A;
let B;
A = a ? a.toLowerCase() : "";
B = b ? b.toLowerCase() : "";
console.log("Objects", A, B, A < B, A > B);
if (A < B)
//sort string ascending
return -1;