Removed all todos from code and created corresponding JIRA tickets.
This commit is contained in:
@@ -48,7 +48,6 @@ export function BillFormComponent({
|
|||||||
setDiscount(opt.discount);
|
setDiscount(opt.discount);
|
||||||
};
|
};
|
||||||
|
|
||||||
//TODO: Test this further. Required to set discount when viewing an invoice.
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (form.getFieldValue("vendorid") && vendorAutoCompleteOptions) {
|
if (form.getFieldValue("vendorid") && vendorAutoCompleteOptions) {
|
||||||
const vendorId = form.getFieldValue("vendorid");
|
const vendorId = form.getFieldValue("vendorid");
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ export const CalculateBillTotal = (invoice) => {
|
|||||||
local_tax_rate,
|
local_tax_rate,
|
||||||
state_tax_rate,
|
state_tax_rate,
|
||||||
} = invoice;
|
} = invoice;
|
||||||
|
|
||||||
//TODO Determine why this recalculates so many times.
|
//TODO Determine why this recalculates so many times.
|
||||||
let subtotal = Dinero({ amount: 0 });
|
let subtotal = Dinero({ amount: 0 });
|
||||||
let federalTax = Dinero({ amount: 0 });
|
let federalTax = Dinero({ amount: 0 });
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ export function ContractConvertToRo({ bodyshop, currentUser, contract }) {
|
|||||||
state_tax_rate: bodyshop.bill_tax_rates.state_tax_rate / 100,
|
state_tax_rate: bodyshop.bill_tax_rates.state_tax_rate / 100,
|
||||||
local_tax_rate: bodyshop.bill_tax_rates.local_tax_rate / 100,
|
local_tax_rate: bodyshop.bill_tax_rates.local_tax_rate / 100,
|
||||||
clm_no: `${contract.job.clm_no}-CC`,
|
clm_no: `${contract.job.clm_no}-CC`,
|
||||||
clm_total: 1234, //TODO
|
clm_total: 1234,
|
||||||
ownr_fn: contract.job.owner.ownr_fn,
|
ownr_fn: contract.job.owner.ownr_fn,
|
||||||
ownr_ln: contract.job.owner.ownr_ln,
|
ownr_ln: contract.job.owner.ownr_ln,
|
||||||
ownr_co_nm: contract.job.owner.ownr_co_nm,
|
ownr_co_nm: contract.job.owner.ownr_co_nm,
|
||||||
|
|||||||
@@ -20,7 +20,6 @@
|
|||||||
// .add(otherTotals.rates.subtotal)
|
// .add(otherTotals.rates.subtotal)
|
||||||
// .add(Dinero({ amount: (job.towing_payable || 0) * 100 }))
|
// .add(Dinero({ amount: (job.towing_payable || 0) * 100 }))
|
||||||
// .add(Dinero({ amount: (job.storage_payable || 0) * 100 }));
|
// .add(Dinero({ amount: (job.storage_payable || 0) * 100 }));
|
||||||
// //TODO Levies should be included??
|
|
||||||
|
|
||||||
// const statePartsTax = job.joblines.reduce((acc, val) => {
|
// const statePartsTax = job.joblines.reduce((acc, val) => {
|
||||||
// if (!!!val.tax_part) return acc;
|
// if (!!!val.tax_part) return acc;
|
||||||
@@ -227,7 +226,7 @@
|
|||||||
// subtotal: acc.sublets.subtotal.add(
|
// subtotal: acc.sublets.subtotal.add(
|
||||||
// Dinero({ amount: Math.round(value.act_price * 100) })
|
// Dinero({ amount: Math.round(value.act_price * 100) })
|
||||||
// ),
|
// ),
|
||||||
// //TODO Add Adjustments in
|
//
|
||||||
// },
|
// },
|
||||||
// };
|
// };
|
||||||
// // case "PAA":
|
// // case "PAA":
|
||||||
@@ -268,7 +267,7 @@
|
|||||||
// value.part_qty
|
// value.part_qty
|
||||||
// )
|
// )
|
||||||
// ),
|
// ),
|
||||||
// //TODO Add Adjustments in
|
//
|
||||||
// },
|
// },
|
||||||
// };
|
// };
|
||||||
// // default:
|
// // default:
|
||||||
@@ -305,7 +304,7 @@
|
|||||||
// function CalculateCustPayable(job) {
|
// function CalculateCustPayable(job) {
|
||||||
// let ret = {
|
// let ret = {
|
||||||
// deductible: Dinero({ amount: (job.ded_amt || 0) * 100 }) || 0,
|
// deductible: Dinero({ amount: (job.ded_amt || 0) * 100 }) || 0,
|
||||||
// federal_tax: Dinero({ amount: (job.federal_tax_payable || 0) * 100 }), //TODO Should this be renamed to make it more clear this is customer GST?
|
// federal_tax: Dinero({ amount: (job.federal_tax_payable || 0) * 100 }),
|
||||||
// other_customer_amount: Dinero({
|
// other_customer_amount: Dinero({
|
||||||
// amount: (job.other_amount_payable || 0) * 100,
|
// amount: (job.other_amount_payable || 0) * 100,
|
||||||
// }),
|
// }),
|
||||||
|
|||||||
@@ -193,14 +193,6 @@ export function JobsCreateJobsInfo({ bodyshop, form, selected }) {
|
|||||||
</Select>
|
</Select>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</LayoutFormRow>
|
</LayoutFormRow>
|
||||||
TODO How to handle different taxes and marking them as exempt?
|
|
||||||
{
|
|
||||||
// <Form.Item label={t("jobs.fields.exempt")}>
|
|
||||||
// {getFieldDecorator("exempt", {
|
|
||||||
// initialValue: job.exempt
|
|
||||||
// })(<Input name='exempt' />)}
|
|
||||||
// </Form.Item>
|
|
||||||
}
|
|
||||||
</Collapse.Panel>
|
</Collapse.Panel>
|
||||||
<Collapse.Panel
|
<Collapse.Panel
|
||||||
key="financial"
|
key="financial"
|
||||||
|
|||||||
@@ -96,7 +96,8 @@ export function JobsDetailHeaderCsi({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
if (e.key === "text") console.log("TODO Handling texting"); //TODO Implement texting.
|
if (e.key === "text") {
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
notification["error"]({
|
notification["error"]({
|
||||||
message: t("csi.errors.notconfigured"),
|
message: t("csi.errors.notconfigured"),
|
||||||
|
|||||||
@@ -27,9 +27,6 @@ export default function OwnerTagPopoverComponent({ job }) {
|
|||||||
</Descriptions.Item>
|
</Descriptions.Item>
|
||||||
<Descriptions.Item key="4" label={t("owners.fields.ownr_ea")}>
|
<Descriptions.Item key="4" label={t("owners.fields.ownr_ea")}>
|
||||||
{job.ownr_ea || ""}
|
{job.ownr_ea || ""}
|
||||||
{
|
|
||||||
//TODO Should add an email formatter.
|
|
||||||
}
|
|
||||||
</Descriptions.Item>
|
</Descriptions.Item>
|
||||||
</Descriptions>
|
</Descriptions>
|
||||||
</Col>
|
</Col>
|
||||||
@@ -56,9 +53,6 @@ export default function OwnerTagPopoverComponent({ job }) {
|
|||||||
</Descriptions.Item>
|
</Descriptions.Item>
|
||||||
<Descriptions.Item key="4" label={t("owners.fields.ownr_ea")}>
|
<Descriptions.Item key="4" label={t("owners.fields.ownr_ea")}>
|
||||||
{job.owner.ownr_ea || ""}
|
{job.owner.ownr_ea || ""}
|
||||||
{
|
|
||||||
//TODO Should add an email formatter.
|
|
||||||
}
|
|
||||||
</Descriptions.Item>
|
</Descriptions.Item>
|
||||||
</Descriptions>
|
</Descriptions>
|
||||||
</Col>
|
</Col>
|
||||||
|
|||||||
@@ -35,16 +35,16 @@ export function PrintCenterItemComponent({
|
|||||||
displayTemplateInWindow(html);
|
displayTemplateInWindow(html);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (disabled) return <li className='print-center-item'>{item.title} </li>;
|
if (disabled) return <li className="print-center-item">{item.title} </li>;
|
||||||
return (
|
return (
|
||||||
<li className='print-center-item'>
|
<li className="print-center-item">
|
||||||
{item.title}
|
{item.title}
|
||||||
<PrinterOutlined onClick={renderToNewWindow} />
|
<PrinterOutlined onClick={renderToNewWindow} />
|
||||||
<MailOutlined
|
<MailOutlined
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setEmailOptions({
|
setEmailOptions({
|
||||||
messageOptions: {
|
messageOptions: {
|
||||||
Subject: "//TODO FIX ME",
|
Subject: "",
|
||||||
},
|
},
|
||||||
template: {
|
template: {
|
||||||
name: item.key,
|
name: item.key,
|
||||||
|
|||||||
@@ -8,15 +8,12 @@ import { alphaSort } from "../../utils/sorters";
|
|||||||
import ProductionSubletsManageComponent from "../production-sublets-manage/production-sublets-manage.component";
|
import ProductionSubletsManageComponent from "../production-sublets-manage/production-sublets-manage.component";
|
||||||
import ProductionListColumnAlert from "./production-list-columns.alert.component";
|
import ProductionListColumnAlert from "./production-list-columns.alert.component";
|
||||||
import ProductionListColumnBodyPriority from "./production-list-columns.bodypriority.component";
|
import ProductionListColumnBodyPriority from "./production-list-columns.bodypriority.component";
|
||||||
|
import ProductionListDate from "./production-list-columns.date.component";
|
||||||
import ProductionListColumnPaintPriority from "./production-list-columns.paintpriority.component";
|
import ProductionListColumnPaintPriority from "./production-list-columns.paintpriority.component";
|
||||||
import ProductionListColumnNote from "./production-list-columns.productionnote.component";
|
import ProductionListColumnNote from "./production-list-columns.productionnote.component";
|
||||||
import ProductionListDate from "./production-list-columns.date.component";
|
|
||||||
import ProductionListColumnStatus from "./production-list-columns.status.component";
|
import ProductionListColumnStatus from "./production-list-columns.status.component";
|
||||||
import ProductionlistColumnTouchTime from "./prodution-list-columns.touchtime.component";
|
import ProductionlistColumnTouchTime from "./prodution-list-columns.touchtime.component";
|
||||||
|
|
||||||
const OneCalendarDay = 60 * 60 * 24 * 1000;
|
|
||||||
const Now = new Date();
|
|
||||||
|
|
||||||
const r = [
|
const r = [
|
||||||
{
|
{
|
||||||
title: i18n.t("jobs.actions.viewdetail"),
|
title: i18n.t("jobs.actions.viewdetail"),
|
||||||
|
|||||||
@@ -1,19 +1,15 @@
|
|||||||
import { ExclamationCircleFilled } from "@ant-design/icons";
|
|
||||||
import { DatePicker, Dropdown, Menu } from "antd";
|
|
||||||
import React from "react";
|
|
||||||
import { useTranslation } from "react-i18next";
|
|
||||||
import { useMutation } from "@apollo/react-hooks";
|
import { useMutation } from "@apollo/react-hooks";
|
||||||
import { UPDATE_JOB } from "../../graphql/jobs.queries";
|
import { DatePicker, Dropdown } from "antd";
|
||||||
import { logImEXEvent } from "../../firebase/firebase.utils";
|
|
||||||
import { DateFormatter } from "../../utils/DateFormatter";
|
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
|
import React from "react";
|
||||||
|
import { logImEXEvent } from "../../firebase/firebase.utils";
|
||||||
|
import { UPDATE_JOB } from "../../graphql/jobs.queries";
|
||||||
|
import { DateFormatter } from "../../utils/DateFormatter";
|
||||||
|
|
||||||
const OneCalendarDay = 60 * 60 * 24 * 1000;
|
const OneCalendarDay = 60 * 60 * 24 * 1000;
|
||||||
const Now = new Date();
|
const Now = new Date();
|
||||||
|
|
||||||
export default function ProductionListDate({ record, field }) {
|
export default function ProductionListDate({ record, field }) {
|
||||||
const { t } = useTranslation();
|
|
||||||
|
|
||||||
const [updateAlert] = useMutation(UPDATE_JOB);
|
const [updateAlert] = useMutation(UPDATE_JOB);
|
||||||
|
|
||||||
const handleChange = (date) => {
|
const handleChange = (date) => {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { SyncOutlined } from "@ant-design/icons";
|
import { SyncOutlined } from "@ant-design/icons";
|
||||||
import { Button, Dropdown, Input, Menu, Table } from "antd";
|
import { Button, Dropdown, Input, Menu, Table } from "antd";
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import ReactDragListView from "react-drag-listview"; //TODO Is there a better way? This library is too big.
|
import ReactDragListView from "react-drag-listview";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import { createStructuredSelector } from "reselect";
|
import { createStructuredSelector } from "reselect";
|
||||||
@@ -170,14 +170,14 @@ export function ProductionListTable({
|
|||||||
loading={loading}
|
loading={loading}
|
||||||
dataSource={dataSource}
|
dataSource={dataSource}
|
||||||
onChange={handleTableChange}
|
onChange={handleTableChange}
|
||||||
rowClassName={(record, index) => {
|
// rowClassName={(record, index) => {
|
||||||
// const classes = []; //TODO What could be good usage here?
|
// // const classes = [];
|
||||||
// if (!!record.scheduled_completion) {
|
// // if (!!record.scheduled_completion) {
|
||||||
// if (new Date(record.scheduled_completion) - Now < OneCalendarDay)
|
// // if (new Date(record.scheduled_completion) - Now < OneCalendarDay)
|
||||||
// classes.push("production-completion-1");
|
// // classes.push("production-completion-1");
|
||||||
// }
|
// // }
|
||||||
// return classes.join(" ");
|
// // return classes.join(" ");
|
||||||
}}
|
// }}
|
||||||
/>
|
/>
|
||||||
</ReactDragListView.DragColumn>
|
</ReactDragListView.DragColumn>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ export function ScheduleCalendarWrapperComponent({
|
|||||||
bodyshop.schedule_start_time
|
bodyshop.schedule_start_time
|
||||||
? new Date(bodyshop.schedule_start_time)
|
? new Date(bodyshop.schedule_start_time)
|
||||||
: new Date("2020-01-01T06:00:00")
|
: new Date("2020-01-01T06:00:00")
|
||||||
} //TODO Read from business settings.
|
}
|
||||||
max={
|
max={
|
||||||
bodyshop.schedule_end_time
|
bodyshop.schedule_end_time
|
||||||
? new Date(bodyshop.schedule_end_time)
|
? new Date(bodyshop.schedule_end_time)
|
||||||
|
|||||||
@@ -62,7 +62,6 @@ export function ScheduleJobModalComponent({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//TODO Existing appointments list only refreshes sometimes after modal close. May have to do with the container class.
|
|
||||||
return (
|
return (
|
||||||
<Row gutter={[32, 32]}>
|
<Row gutter={[32, 32]}>
|
||||||
<Col span={12}>
|
<Col span={12}>
|
||||||
|
|||||||
@@ -130,9 +130,7 @@ export function ShopEmployeesFormComponent({
|
|||||||
>
|
>
|
||||||
<FormDatePicker />
|
<FormDatePicker />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
{
|
|
||||||
//TODO Make this a picklist.
|
|
||||||
}
|
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("employees.fields.cost_center")}
|
label={t("employees.fields.cost_center")}
|
||||||
name="cost_center"
|
name="cost_center"
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
|
import { useMutation, useQuery } from "@apollo/react-hooks";
|
||||||
import { Form, notification } from "antd";
|
import { Form, notification } from "antd";
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { useMutation, useQuery } from "@apollo/react-hooks";
|
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import { createStructuredSelector } from "reselect";
|
import { createStructuredSelector } from "reselect";
|
||||||
|
import { logImEXEvent } from "../../firebase/firebase.utils";
|
||||||
import {
|
import {
|
||||||
DELETE_EMPLOYEE,
|
DELETE_EMPLOYEE,
|
||||||
INSERT_EMPLOYEES,
|
INSERT_EMPLOYEES,
|
||||||
@@ -13,7 +14,6 @@ import {
|
|||||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||||
import AlertComponent from "../alert/alert.component";
|
import AlertComponent from "../alert/alert.component";
|
||||||
import ShopEmployeeComponent from "./shop-employees.component";
|
import ShopEmployeeComponent from "./shop-employees.component";
|
||||||
import { logImEXEvent } from "../../firebase/firebase.utils";
|
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
bodyshop: selectBodyshop,
|
bodyshop: selectBodyshop,
|
||||||
@@ -38,7 +38,7 @@ function ShopEmployeesContainer({ bodyshop }) {
|
|||||||
notification["success"]({
|
notification["success"]({
|
||||||
message: t("employees.successes.delete"),
|
message: t("employees.successes.delete"),
|
||||||
});
|
});
|
||||||
//TODO Better way to reset the field decorators?
|
|
||||||
employeeState[1](null);
|
employeeState[1](null);
|
||||||
refetch().then((r) => form.resetFields());
|
refetch().then((r) => form.resetFields());
|
||||||
})
|
})
|
||||||
@@ -63,7 +63,7 @@ function ShopEmployeesContainer({ bodyshop }) {
|
|||||||
notification["success"]({
|
notification["success"]({
|
||||||
message: t("employees.successes.save"),
|
message: t("employees.successes.save"),
|
||||||
});
|
});
|
||||||
//TODO Better way to reset the field decorators?
|
|
||||||
employeeState[1](null);
|
employeeState[1](null);
|
||||||
refetch().then((r) => form.resetFields());
|
refetch().then((r) => form.resetFields());
|
||||||
})
|
})
|
||||||
@@ -84,7 +84,6 @@ function ShopEmployeesContainer({ bodyshop }) {
|
|||||||
notification["success"]({
|
notification["success"]({
|
||||||
message: t("employees.successes.save"),
|
message: t("employees.successes.save"),
|
||||||
});
|
});
|
||||||
//TODO Better way to reset the field decorators?
|
|
||||||
employeeState[1](null);
|
employeeState[1](null);
|
||||||
refetch().catch((error) => {
|
refetch().catch((error) => {
|
||||||
notification["error"]({
|
notification["error"]({
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ const SelectorDiv = styled.div`
|
|||||||
width: 200px;
|
width: 200px;
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
//TODO Fix up styles.
|
|
||||||
export default function ShopInfoIntakeChecklistComponent({ form }) {
|
export default function ShopInfoIntakeChecklistComponent({ form }) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { Button, Form, Input, Select, Row, Col } from "antd";
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import FormListMoveArrows from "../form-list-move-arrows/form-list-move-arrows.component";
|
import FormListMoveArrows from "../form-list-move-arrows/form-list-move-arrows.component";
|
||||||
//TODO Fix up styles.
|
|
||||||
export default function ShopInfoOrderStatusComponent({ form }) {
|
export default function ShopInfoOrderStatusComponent({ form }) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import { Form, InputNumber } from "antd";
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
|
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
|
||||||
//TODO Fix up styles.
|
|
||||||
export default function ShopInfoRbacComponent({ form }) {
|
export default function ShopInfoRbacComponent({ form }) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import { DeleteFilled } from "@ant-design/icons";
|
import { DeleteFilled } from "@ant-design/icons";
|
||||||
import { Button, Form, Input, Select, InputNumber } from "antd";
|
import { Button, Form, Input, InputNumber, Select } from "antd";
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
|
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
|
||||||
//TODO Fix up styles.
|
|
||||||
const SelectorDiv = styled.div`
|
const SelectorDiv = styled.div`
|
||||||
.ant-form-item .ant-select {
|
.ant-form-item .ant-select {
|
||||||
width: 125px;
|
width: 125px;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { DeleteFilled } from "@ant-design/icons";
|
import { DeleteFilled } from "@ant-design/icons";
|
||||||
import { Button, Form, Input, Select, Row, Col } from "antd";
|
import { Button, Col, Form, Input, Row, Select } from "antd";
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
@@ -9,7 +9,7 @@ const SelectorDiv = styled.div`
|
|||||||
width: 200px;
|
width: 200px;
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
//TODO Fix up styles.
|
|
||||||
export default function ShopInfoROStatusComponent({ form }) {
|
export default function ShopInfoROStatusComponent({ form }) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
|||||||
@@ -12,9 +12,9 @@ import {
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import ColorpickerFormItemComponent from "../form-items-formatted/colorpicker-form-item.component";
|
import ColorpickerFormItemComponent from "../form-items-formatted/colorpicker-form-item.component";
|
||||||
//TODO Fix up styles.
|
|
||||||
import FormListMoveArrows from "../form-list-move-arrows/form-list-move-arrows.component";
|
import FormListMoveArrows from "../form-list-move-arrows/form-list-move-arrows.component";
|
||||||
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
|
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
|
||||||
|
|
||||||
export default function ShopInfoSchedulingComponent({ form }) {
|
export default function ShopInfoSchedulingComponent({ form }) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import React from "react";
|
|||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { TemplateList } from "../../utils/TemplateConstants";
|
import { TemplateList } from "../../utils/TemplateConstants";
|
||||||
import FormListMoveArrows from "../form-list-move-arrows/form-list-move-arrows.component";
|
import FormListMoveArrows from "../form-list-move-arrows/form-list-move-arrows.component";
|
||||||
//TODO Fix up styles.
|
|
||||||
|
|
||||||
export default function ShopInfoSpeedPrint({ bodyshop, form }) {
|
export default function ShopInfoSpeedPrint({ bodyshop, form }) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|||||||
@@ -2,13 +2,11 @@ import { LockOutlined, UserOutlined } from "@ant-design/icons";
|
|||||||
import { Button, Form, Input, Typography } from "antd";
|
import { Button, Form, Input, Typography } from "antd";
|
||||||
import queryString from "query-string";
|
import queryString from "query-string";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { useApolloClient } from "react-apollo";
|
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import { Link, Redirect, useLocation } from "react-router-dom";
|
import { Link, Redirect, useLocation } from "react-router-dom";
|
||||||
import { createStructuredSelector } from "reselect";
|
import { createStructuredSelector } from "reselect";
|
||||||
import ImEXOnlineLogo from "../../assets/logo192.png";
|
import ImEXOnlineLogo from "../../assets/logo192.png";
|
||||||
import { UPSERT_USER } from "../../graphql/user.queries";
|
|
||||||
import {
|
import {
|
||||||
emailSignInStart,
|
emailSignInStart,
|
||||||
sendPasswordReset,
|
sendPasswordReset,
|
||||||
@@ -38,7 +36,7 @@ export function SignInComponent({
|
|||||||
sendPasswordReset,
|
sendPasswordReset,
|
||||||
}) {
|
}) {
|
||||||
const { redirect } = queryString.parse(useLocation().search);
|
const { redirect } = queryString.parse(useLocation().search);
|
||||||
const apolloClient = useApolloClient();
|
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const handleFinish = (values) => {
|
const handleFinish = (values) => {
|
||||||
const { email, password } = values;
|
const { email, password } = values;
|
||||||
@@ -46,22 +44,6 @@ export function SignInComponent({
|
|||||||
};
|
};
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
|
|
||||||
//TODO - may be able to run this only on new user creation.
|
|
||||||
if (currentUser.authorized === true) {
|
|
||||||
apolloClient
|
|
||||||
.mutate({
|
|
||||||
mutation: UPSERT_USER,
|
|
||||||
variables: {
|
|
||||||
authEmail: currentUser.email,
|
|
||||||
authToken: currentUser.uid,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.then()
|
|
||||||
.catch((error) => {
|
|
||||||
console.log("User login upsert error.", error);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currentUser.authorized === true)
|
if (currentUser.authorized === true)
|
||||||
return <Redirect to={redirect || "/manage"} />;
|
return <Redirect to={redirect || "/manage"} />;
|
||||||
|
|
||||||
|
|||||||
@@ -136,7 +136,7 @@ export default function VehicleDetailFormComponent({ form, loading }) {
|
|||||||
<FormDatePicker />
|
<FormDatePicker />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
{
|
{
|
||||||
//TODO Add handling for paint code json
|
|
||||||
//Removed as a part of IO-446.
|
//Removed as a part of IO-446.
|
||||||
//No values have been captured in this field as of yet.
|
//No values have been captured in this field as of yet.
|
||||||
// <Form.Item
|
// <Form.Item
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ function VehicleDetailFormContainer({ vehicle, refetch }) {
|
|||||||
notification["success"]({
|
notification["success"]({
|
||||||
message: t("vehicles.successes.save"),
|
message: t("vehicles.successes.save"),
|
||||||
});
|
});
|
||||||
//TODO Better way to reset the field decorators?
|
|
||||||
if (refetch) await refetch();
|
if (refetch) await refetch();
|
||||||
form.resetFields();
|
form.resetFields();
|
||||||
form.resetFields();
|
form.resetFields();
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ function VendorsFormContainer({ refetch, bodyshop }) {
|
|||||||
notification["success"]({
|
notification["success"]({
|
||||||
message: t("vendors.successes.deleted"),
|
message: t("vendors.successes.deleted"),
|
||||||
});
|
});
|
||||||
//TODO Better way to reset the field decorators?
|
|
||||||
if (refetch)
|
if (refetch)
|
||||||
refetch().then((r) => {
|
refetch().then((r) => {
|
||||||
form.resetFields();
|
form.resetFields();
|
||||||
@@ -74,7 +74,7 @@ function VendorsFormContainer({ refetch, bodyshop }) {
|
|||||||
notification["success"]({
|
notification["success"]({
|
||||||
message: t("vendors.successes.saved"),
|
message: t("vendors.successes.saved"),
|
||||||
});
|
});
|
||||||
//TODO Better way to reset the field decorators?
|
|
||||||
if (refetch)
|
if (refetch)
|
||||||
refetch().then(() => {
|
refetch().then(() => {
|
||||||
form.resetFields();
|
form.resetFields();
|
||||||
@@ -99,7 +99,7 @@ function VendorsFormContainer({ refetch, bodyshop }) {
|
|||||||
notification["success"]({
|
notification["success"]({
|
||||||
message: t("vendors.successes.saved"),
|
message: t("vendors.successes.saved"),
|
||||||
});
|
});
|
||||||
//TODO Better way to reset the field decorators?
|
|
||||||
if (refetch) refetch();
|
if (refetch) refetch();
|
||||||
form.resetFields();
|
form.resetFields();
|
||||||
setFormLoading(false);
|
setFormLoading(false);
|
||||||
|
|||||||
@@ -58,7 +58,6 @@ export default function VendorsListComponent({
|
|||||||
setState({ ...state, filteredInfo: filters, sortedInfo: sorter });
|
setState({ ...state, filteredInfo: filters, sortedInfo: sorter });
|
||||||
};
|
};
|
||||||
|
|
||||||
//TODO Implement search
|
|
||||||
return (
|
return (
|
||||||
<Table
|
<Table
|
||||||
loading={loading}
|
loading={loading}
|
||||||
@@ -71,10 +70,10 @@ export default function VendorsListComponent({
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
size='small'
|
size="small"
|
||||||
pagination={{ position: "top" }}
|
pagination={{ position: "top" }}
|
||||||
columns={columns.map((item) => ({ ...item }))}
|
columns={columns.map((item) => ({ ...item }))}
|
||||||
rowKey='id'
|
rowKey="id"
|
||||||
onChange={handleTableChange}
|
onChange={handleTableChange}
|
||||||
dataSource={vendors}
|
dataSource={vendors}
|
||||||
rowSelection={{
|
rowSelection={{
|
||||||
|
|||||||
@@ -837,7 +837,7 @@ export const SEARCH_FOR_JOBS = gql`
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
//TODO Ensure this is always up to date.
|
|
||||||
export const QUERY_ALL_JOB_FIELDS = gql`
|
export const QUERY_ALL_JOB_FIELDS = gql`
|
||||||
query QUERY_ALL_JOB_FIELDS($id: uuid!) {
|
query QUERY_ALL_JOB_FIELDS($id: uuid!) {
|
||||||
jobs_by_pk(id: $id) {
|
jobs_by_pk(id: $id) {
|
||||||
|
|||||||
@@ -1,19 +1,19 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
import { useLazyQuery, useMutation } from "@apollo/react-hooks";
|
||||||
import JobsCreateComponent from "./jobs-create.component";
|
|
||||||
import { Form, notification } from "antd";
|
import { Form, notification } from "antd";
|
||||||
import JobCreateContext from "./jobs-create.context";
|
import React, { useEffect, useState } from "react";
|
||||||
import { useMutation, useLazyQuery } from "@apollo/react-hooks";
|
import { useTranslation } from "react-i18next";
|
||||||
import { INSERT_NEW_JOB } from "../../graphql/jobs.queries";
|
|
||||||
import { QUERY_OWNER_FOR_JOB_CREATION } from "../../graphql/owners.queries";
|
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import { createStructuredSelector } from "reselect";
|
import { createStructuredSelector } from "reselect";
|
||||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
import RbacWrapper from "../../components/rbac-wrapper/rbac-wrapper.component";
|
||||||
import { useTranslation } from "react-i18next";
|
import { INSERT_NEW_JOB } from "../../graphql/jobs.queries";
|
||||||
|
import { QUERY_OWNER_FOR_JOB_CREATION } from "../../graphql/owners.queries";
|
||||||
import {
|
import {
|
||||||
setBreadcrumbs,
|
setBreadcrumbs,
|
||||||
setSelectedHeader,
|
setSelectedHeader,
|
||||||
} from "../../redux/application/application.actions";
|
} from "../../redux/application/application.actions";
|
||||||
import RbacWrapper from "../../components/rbac-wrapper/rbac-wrapper.component";
|
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||||
|
import JobsCreateComponent from "./jobs-create.component";
|
||||||
|
import JobCreateContext from "./jobs-create.context";
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
bodyshop: selectBodyshop,
|
bodyshop: selectBodyshop,
|
||||||
@@ -97,8 +97,7 @@ function JobsCreateContainer({ bodyshop, setBreadcrumbs, setSelectedHeader }) {
|
|||||||
shopid: bodyshop.id,
|
shopid: bodyshop.id,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
//TODO Logic to ensure the owner is actually fetched.
|
|
||||||
console.log("job", job);
|
|
||||||
let ownerData;
|
let ownerData;
|
||||||
if (!!!job.ownerid) {
|
if (!!!job.ownerid) {
|
||||||
ownerData = job.owner.data;
|
ownerData = job.owner.data;
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import phone from "phone";
|
import phone from "phone";
|
||||||
import { all, call, put, select, takeLatest } from "redux-saga/effects";
|
import { all, call, put, select, takeLatest } from "redux-saga/effects";
|
||||||
import client from "../../utils/GraphQLClient";
|
|
||||||
import { logImEXEvent } from "../../firebase/firebase.utils";
|
import { logImEXEvent } from "../../firebase/firebase.utils";
|
||||||
import {
|
import {
|
||||||
CONVERSATION_ID_BY_PHONE,
|
CONVERSATION_ID_BY_PHONE,
|
||||||
CREATE_CONVERSATION,
|
CREATE_CONVERSATION
|
||||||
} from "../../graphql/conversations.queries";
|
} from "../../graphql/conversations.queries";
|
||||||
import { INSERT_CONVERSATION_TAG } from "../../graphql/job-conversations.queries";
|
import { INSERT_CONVERSATION_TAG } from "../../graphql/job-conversations.queries";
|
||||||
|
import client from "../../utils/GraphQLClient";
|
||||||
import { selectBodyshop } from "../user/user.selectors";
|
import { selectBodyshop } from "../user/user.selectors";
|
||||||
import {
|
import {
|
||||||
sendMessageFailure,
|
sendMessageFailure,
|
||||||
sendMessageSuccess,
|
sendMessageSuccess,
|
||||||
setSelectedConversation,
|
setSelectedConversation
|
||||||
} from "./messaging.actions";
|
} from "./messaging.actions";
|
||||||
import MessagingActionTypes from "./messaging.types";
|
import MessagingActionTypes from "./messaging.types";
|
||||||
|
|
||||||
@@ -73,7 +73,7 @@ export function* openChatByPhone({ payload }) {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
console.log("ERROR: Multiple conversations found. "); //TODO Graceful handling of this situation
|
console.log("ERROR: Multiple conversations found. ");
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log("Error in sendMessage saga.", error);
|
console.log("Error in sendMessage saga.", error);
|
||||||
|
|||||||
@@ -10,6 +10,9 @@ import {
|
|||||||
} from "../../firebase/firebase.utils";
|
} from "../../firebase/firebase.utils";
|
||||||
import {
|
import {
|
||||||
checkInstanceId,
|
checkInstanceId,
|
||||||
|
sendPasswordResetFailure,
|
||||||
|
sendPasswordResetSuccess,
|
||||||
|
setAuthlevel,
|
||||||
setInstanceConflict,
|
setInstanceConflict,
|
||||||
setInstanceId,
|
setInstanceId,
|
||||||
setLocalFingerprint,
|
setLocalFingerprint,
|
||||||
@@ -19,11 +22,8 @@ import {
|
|||||||
signOutSuccess,
|
signOutSuccess,
|
||||||
unauthorizedUser,
|
unauthorizedUser,
|
||||||
updateUserDetailsSuccess,
|
updateUserDetailsSuccess,
|
||||||
sendPasswordResetFailure,
|
|
||||||
sendPasswordResetSuccess,
|
|
||||||
validatePasswordResetSuccess,
|
|
||||||
validatePasswordResetFailure,
|
validatePasswordResetFailure,
|
||||||
setAuthlevel,
|
validatePasswordResetSuccess,
|
||||||
} from "./user.actions";
|
} from "./user.actions";
|
||||||
import UserActionTypes from "./user.types";
|
import UserActionTypes from "./user.types";
|
||||||
|
|
||||||
@@ -102,7 +102,6 @@ export function* updateUserDetails(userDetails) {
|
|||||||
yield put(updateUserDetailsSuccess(userDetails.payload));
|
yield put(updateUserDetailsSuccess(userDetails.payload));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
//yield put(signOutFailure(error.message));
|
//yield put(signOutFailure(error.message));
|
||||||
//TODO error handling
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export function* onSetInstanceId() {
|
export function* onSetInstanceId() {
|
||||||
@@ -127,8 +126,6 @@ export function* setInstanceIdSaga({ payload: uid }) {
|
|||||||
if (process.env.NODE_ENV === "production") yield put(checkInstanceId(uid));
|
if (process.env.NODE_ENV === "production") yield put(checkInstanceId(uid));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log("error", error);
|
console.log("error", error);
|
||||||
//yield put(signOutFailure(error.message));
|
|
||||||
//TODO error handling
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,7 +149,6 @@ export function* checkInstanceIdSaga({ payload: uid }) {
|
|||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log("error", error);
|
console.log("error", error);
|
||||||
//TODO error handling
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,30 +2,6 @@ const functions = require("firebase-functions");
|
|||||||
const admin = require("firebase-admin");
|
const admin = require("firebase-admin");
|
||||||
admin.initializeApp(functions.config().firebase);
|
admin.initializeApp(functions.config().firebase);
|
||||||
|
|
||||||
// //TODO Move this to an environment parameter.
|
|
||||||
// const GRAPHQL_ENDPOINT = functions.config().auth.graphql_endpoint;
|
|
||||||
// const HASURA_SECRET_ADMIN_KEY = functions.config().auth.hasura_secret_admin_key;
|
|
||||||
// const UPSERT_USER = `
|
|
||||||
// mutation upsert_user($authEmail: String!, $authToken: String!) {
|
|
||||||
// insert_users(
|
|
||||||
// objects: [
|
|
||||||
// {
|
|
||||||
// email:$authEmail,
|
|
||||||
// authid:$authToken
|
|
||||||
// }
|
|
||||||
// ],
|
|
||||||
// on_conflict: {
|
|
||||||
// constraint: users_pkey,
|
|
||||||
// update_columns: [authid]
|
|
||||||
// }
|
|
||||||
// ) {
|
|
||||||
// returning {
|
|
||||||
// authid
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// `;
|
|
||||||
|
|
||||||
// On sign up.
|
// On sign up.
|
||||||
exports.processSignUp = functions.auth.user().onCreate((user) => {
|
exports.processSignUp = functions.auth.user().onCreate((user) => {
|
||||||
// Check if user meets role criteria:
|
// Check if user meets role criteria:
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ const { Headers } = require("cross-fetch");
|
|||||||
|
|
||||||
global.Headers = global.Headers || Headers;
|
global.Headers = global.Headers || Headers;
|
||||||
|
|
||||||
//TODO May need to use a different client that includes caching of resources.
|
|
||||||
exports.client = new GraphQLClient(process.env.GRAPHQL_ENDPOINT, {
|
exports.client = new GraphQLClient(process.env.GRAPHQL_ENDPOINT, {
|
||||||
headers: {
|
headers: {
|
||||||
"x-hasura-admin-secret": process.env.HASURA_ADMIN_SECRET,
|
"x-hasura-admin-secret": process.env.HASURA_ADMIN_SECRET,
|
||||||
|
|||||||
@@ -220,7 +220,6 @@ function CalculateTaxesTotals(job, otherTotals) {
|
|||||||
.add(otherTotals.additional)
|
.add(otherTotals.additional)
|
||||||
.add(Dinero({ amount: (job.towing_payable || 0) * 100 }))
|
.add(Dinero({ amount: (job.towing_payable || 0) * 100 }))
|
||||||
.add(Dinero({ amount: (job.storage_payable || 0) * 100 }));
|
.add(Dinero({ amount: (job.storage_payable || 0) * 100 }));
|
||||||
//TODO Levies should be included??
|
|
||||||
|
|
||||||
//Potential issue here with Sublet Calculation. Sublets are calculated under labor in Mitchell, but it's done in IO
|
//Potential issue here with Sublet Calculation. Sublets are calculated under labor in Mitchell, but it's done in IO
|
||||||
//Under the parts rates.
|
//Under the parts rates.
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ exports.receive = (req, res) => {
|
|||||||
phone: phone(req.body.From)[0],
|
phone: phone(req.body.From)[0],
|
||||||
})
|
})
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
//TODO Add logic for handling MMS.
|
|
||||||
let newMessage = {
|
let newMessage = {
|
||||||
msid: req.body.SmsMessageSid,
|
msid: req.body.SmsMessageSid,
|
||||||
text: req.body.Body,
|
text: req.body.Body,
|
||||||
|
|||||||
Reference in New Issue
Block a user