Finalized read only job. Logic to detmerine what is read only outstanding. BOD-409
This commit is contained in:
@@ -1,18 +1,17 @@
|
||||
import { SyncOutlined } from "@ant-design/icons";
|
||||
import { Button, Checkbox, Descriptions, Table, Input, Typography } from "antd";
|
||||
import { Button, Checkbox, Descriptions, Input, Table, Typography } from "antd";
|
||||
import queryString from "query-string";
|
||||
import React, { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
import { Link } from "react-router-dom";
|
||||
import { Link, useLocation } from "react-router-dom";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { selectJobReadOnly } from "../../redux/application/application.selectors";
|
||||
import { setModalContext } from "../../redux/modals/modals.actions";
|
||||
import CurrencyFormatter from "../../utils/CurrencyFormatter";
|
||||
import { DateFormatter } from "../../utils/DateFormatter";
|
||||
import { alphaSort } from "../../utils/sorters";
|
||||
import queryString from "query-string";
|
||||
import { useLocation } from "react-router-dom";
|
||||
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { selectJobReadOnly } from "../../redux/application/application.selectors";
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
jobRO: selectJobReadOnly,
|
||||
});
|
||||
@@ -376,4 +375,7 @@ export function BillsListTableComponent({
|
||||
</div>
|
||||
);
|
||||
}
|
||||
export default connect(null, mapDispatchToProps)(BillsListTableComponent);
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(BillsListTableComponent);
|
||||
|
||||
@@ -6,7 +6,7 @@ import { TimePicker } from "antd";
|
||||
import moment from "moment";
|
||||
//To be used as a form element only.
|
||||
|
||||
const DateTimePicker = ({ value, onChange, onBlur }, ref) => {
|
||||
const DateTimePicker = ({ value, onChange, onBlur, ...restProps }, ref) => {
|
||||
// const handleChange = (newDate) => {
|
||||
// if (value !== newDate && onChange) {
|
||||
// onChange(newDate);
|
||||
@@ -15,9 +15,15 @@ const DateTimePicker = ({ value, onChange, onBlur }, ref) => {
|
||||
|
||||
return (
|
||||
<div>
|
||||
<FormDatePicker value={value} onBlur={onBlur} onChange={onChange} />
|
||||
<FormDatePicker
|
||||
{...restProps}
|
||||
value={value}
|
||||
onBlur={onBlur}
|
||||
onChange={onChange}
|
||||
/>
|
||||
|
||||
<TimePicker
|
||||
{...restProps}
|
||||
value={value ? moment(value) : null}
|
||||
onChange={onChange}
|
||||
showSecond={false}
|
||||
|
||||
@@ -1,11 +1,18 @@
|
||||
import { Form } from "antd";
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { selectJobReadOnly } from "../../redux/application/application.selectors";
|
||||
import FormDatePicker from "../form-date-picker/form-date-picker.component";
|
||||
import DateTimePicker from "../form-date-time-picker/form-date-time-picker.component";
|
||||
import FormRow from "../layout-form-row/layout-form-row.component";
|
||||
import FormDatePicker from "../form-date-picker/form-date-picker.component";
|
||||
|
||||
export default function JobsDetailDatesComponent({ job }) {
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
jobRO: selectJobReadOnly,
|
||||
});
|
||||
|
||||
export function JobsDetailDatesComponent({ jobRO, job }) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
@@ -15,10 +22,10 @@ export default function JobsDetailDatesComponent({ job }) {
|
||||
label={t("jobs.fields.date_estimated")}
|
||||
name="date_estimated"
|
||||
>
|
||||
<DateTimePicker />
|
||||
<DateTimePicker disabled={jobRO} />
|
||||
</Form.Item>
|
||||
<Form.Item label={t("jobs.fields.date_open")} name="date_open">
|
||||
<DateTimePicker />
|
||||
<DateTimePicker disabled={jobRO} />
|
||||
</Form.Item>
|
||||
</FormRow>
|
||||
|
||||
@@ -27,13 +34,13 @@ export default function JobsDetailDatesComponent({ job }) {
|
||||
label={t("jobs.fields.date_scheduled")}
|
||||
name="date_scheduled"
|
||||
>
|
||||
<FormDatePicker />
|
||||
<FormDatePicker disabled={jobRO} />
|
||||
</Form.Item>
|
||||
<Form.Item label={t("jobs.fields.scheduled_in")} name="scheduled_in">
|
||||
<DateTimePicker />
|
||||
<DateTimePicker disabled={jobRO} />
|
||||
</Form.Item>
|
||||
<Form.Item label={t("jobs.fields.actual_in")} name="actual_in">
|
||||
<DateTimePicker />
|
||||
<DateTimePicker disabled={jobRO} />
|
||||
</Form.Item>
|
||||
</FormRow>
|
||||
<FormRow header={t("jobs.forms.repairdates")}>
|
||||
@@ -41,38 +48,39 @@ export default function JobsDetailDatesComponent({ job }) {
|
||||
label={t("jobs.fields.scheduled_completion")}
|
||||
name="scheduled_completion"
|
||||
>
|
||||
<DateTimePicker />
|
||||
<DateTimePicker disabled={jobRO} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.actual_completion")}
|
||||
name="actual_completion"
|
||||
>
|
||||
<DateTimePicker />
|
||||
<DateTimePicker disabled={jobRO} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.scheduled_delivery")}
|
||||
name="scheduled_delivery"
|
||||
>
|
||||
<DateTimePicker />
|
||||
<DateTimePicker disabled={jobRO} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.actual_delivery")}
|
||||
name="actual_delivery"
|
||||
>
|
||||
<DateTimePicker />
|
||||
<DateTimePicker disabled={jobRO} />
|
||||
</Form.Item>
|
||||
</FormRow>
|
||||
<FormRow header={t("jobs.forms.admindates")}>
|
||||
<Form.Item label={t("jobs.fields.date_invoiced")} name="date_invoiced">
|
||||
<DateTimePicker />
|
||||
<DateTimePicker disabled={jobRO} />
|
||||
</Form.Item>
|
||||
<Form.Item label={t("jobs.fields.date_closed")} name="date_closed">
|
||||
<DateTimePicker />
|
||||
</Form.Item>
|
||||
<Form.Item label={t("jobs.fields.date_exported")} name="date_exported">
|
||||
<DateTimePicker />
|
||||
<DateTimePicker disabled={jobRO} />
|
||||
</Form.Item>
|
||||
</FormRow>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
export default connect(mapStateToProps, null)(JobsDetailDatesComponent);
|
||||
|
||||
@@ -1,10 +1,20 @@
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { selectJobReadOnly } from "../../redux/application/application.selectors";
|
||||
import LaborAllocationsTableComponent from "../labor-allocations-table/labor-allocations-table.component";
|
||||
import TimeTicketEnterButton from "../time-ticket-enter-button/time-ticket-enter-button.component";
|
||||
import TimeTicketList from "../time-ticket-list/time-ticket-list.component";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
export default function JobsDetailLaborContainer({
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
jobRO: selectJobReadOnly,
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps, null)(JobsDetailLaborContainer);
|
||||
|
||||
export function JobsDetailLaborContainer({
|
||||
jobRO,
|
||||
jobId,
|
||||
joblines,
|
||||
timetickets,
|
||||
@@ -16,7 +26,11 @@ export default function JobsDetailLaborContainer({
|
||||
return (
|
||||
<div>
|
||||
{techConsole ? null : (
|
||||
<TimeTicketEnterButton actions={{ refetch }} context={{ jobId: jobId }}>
|
||||
<TimeTicketEnterButton
|
||||
disabled={jobRO}
|
||||
actions={{ refetch }}
|
||||
context={{ jobId: jobId }}
|
||||
>
|
||||
{t("timetickets.actions.enter")}
|
||||
</TimeTicketEnterButton>
|
||||
)}
|
||||
@@ -29,6 +43,7 @@ export default function JobsDetailLaborContainer({
|
||||
timetickets={timetickets}
|
||||
refetch={refetch}
|
||||
techConsole={techConsole}
|
||||
disabled={jobRO}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -10,6 +10,7 @@ import moment from "moment";
|
||||
import { onlyUnique } from "../../utils/arrayHelper";
|
||||
|
||||
export default function TimeTicketList({
|
||||
disabled,
|
||||
loading,
|
||||
timetickets,
|
||||
refetch,
|
||||
@@ -40,7 +41,8 @@ export default function TimeTicketList({
|
||||
sortOrder: state.sortedInfo.columnKey === "vin" && state.sortedInfo.order,
|
||||
render: (text, record) => (
|
||||
<Link
|
||||
to={`/manage/employees/${record.employee.id}`}>{`${record.employee.first_name} ${record.employee.last_name}`}</Link>
|
||||
to={`/manage/employees/${record.employee.id}`}
|
||||
>{`${record.employee.first_name} ${record.employee.last_name}`}</Link>
|
||||
),
|
||||
},
|
||||
{
|
||||
@@ -126,22 +128,22 @@ export default function TimeTicketList({
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
title: t("general.labels.actions"),
|
||||
dataIndex: "actions",
|
||||
key: "actions",
|
||||
render: (text, record) => {
|
||||
if (techConsole) return null;
|
||||
return (
|
||||
<TimeTicketEnterButton
|
||||
actions={{ refetch }}
|
||||
context={{ id: record.id, timeticket: record }}
|
||||
disabled={!!!record.job}>
|
||||
{t("general.actions.edit")}
|
||||
</TimeTicketEnterButton>
|
||||
);
|
||||
},
|
||||
},
|
||||
!!techConsole
|
||||
? {
|
||||
title: t("general.labels.actions"),
|
||||
dataIndex: "actions",
|
||||
key: "actions",
|
||||
render: (text, record) => (
|
||||
<TimeTicketEnterButton
|
||||
actions={{ refetch }}
|
||||
context={{ id: record.id, timeticket: record }}
|
||||
disabled={!!!record.job || disabled}
|
||||
>
|
||||
{t("general.actions.edit")}
|
||||
</TimeTicketEnterButton>
|
||||
),
|
||||
}
|
||||
: null,
|
||||
];
|
||||
|
||||
const handleTableChange = (pagination, filters, sorter) => {
|
||||
@@ -151,10 +153,10 @@ export default function TimeTicketList({
|
||||
return (
|
||||
<Table
|
||||
loading={loading}
|
||||
size='small'
|
||||
size="small"
|
||||
pagination={{ position: "top" }}
|
||||
columns={columns.map((item) => ({ ...item }))}
|
||||
rowKey='id'
|
||||
rowKey="id"
|
||||
dataSource={timetickets}
|
||||
onChange={handleTableChange}
|
||||
/>
|
||||
|
||||
@@ -4,7 +4,6 @@ import Icon, {
|
||||
DollarCircleOutlined,
|
||||
FileImageFilled,
|
||||
ToolFilled,
|
||||
CheckSquareFilled,
|
||||
} from "@ant-design/icons";
|
||||
import { Form, notification, Tabs } from "antd";
|
||||
import Axios from "axios";
|
||||
@@ -13,20 +12,15 @@ import moment from "moment";
|
||||
import queryString from "query-string";
|
||||
import React, { lazy, Suspense, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import {
|
||||
FaHardHat,
|
||||
FaHistory,
|
||||
FaRegStickyNote,
|
||||
FaShieldAlt,
|
||||
} from "react-icons/fa";
|
||||
import { FaHardHat, FaRegStickyNote, FaShieldAlt } from "react-icons/fa";
|
||||
import { connect } from "react-redux";
|
||||
import { useHistory, useLocation } from "react-router-dom";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import FormFieldsChanged from "../../components/form-fields-changed-alert/form-fields-changed-alert.component";
|
||||
import LoadingSpinner from "../../components/loading-spinner/loading-spinner.component";
|
||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||
import JobsDetailChecklists from "../../components/jobs-detail-checklists/jobs-detail-checklists.component";
|
||||
//import JobsDetailChecklists from "../../components/jobs-detail-checklists/jobs-detail-checklists.component";
|
||||
import { selectJobReadOnly } from "../../redux/application/application.selectors";
|
||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||
|
||||
const JobsLinesContainer = lazy(() =>
|
||||
import("../../components/job-detail-lines/job-lines.container")
|
||||
@@ -66,9 +60,9 @@ const JobLineUpsertModalContainer = lazy(() =>
|
||||
const JobsDetailPliContainer = lazy(() =>
|
||||
import("../../components/jobs-detail-pli/jobs-detail-pli.container")
|
||||
);
|
||||
const JobsDetailAuditContainer = lazy(() =>
|
||||
import("../../components/audit-trail-list/audit-trail-list.container")
|
||||
);
|
||||
// const JobsDetailAuditContainer = lazy(() =>
|
||||
// import("../../components/audit-trail-list/audit-trail-list.container")
|
||||
// );
|
||||
const JobsDetailLaborContainer = lazy(() =>
|
||||
import("../../components/jobs-detail-labor/jobs-detail-labor.container")
|
||||
);
|
||||
@@ -268,29 +262,30 @@ export function JobsDetailPage({
|
||||
>
|
||||
<JobNotesContainer jobId={job.id} />
|
||||
</Tabs.TabPane>
|
||||
|
||||
<Tabs.TabPane
|
||||
tab={
|
||||
<span>
|
||||
<Icon component={FaHistory} />
|
||||
{t("jobs.labels.audit")}
|
||||
</span>
|
||||
}
|
||||
key="audit"
|
||||
>
|
||||
<JobsDetailAuditContainer recordId={job.id} />
|
||||
</Tabs.TabPane>
|
||||
<Tabs.TabPane
|
||||
tab={
|
||||
<span>
|
||||
<CheckSquareFilled />
|
||||
{t("jobs.labels.checklists")}
|
||||
</span>
|
||||
}
|
||||
key="checklists"
|
||||
>
|
||||
<JobsDetailChecklists job={job} />
|
||||
</Tabs.TabPane>
|
||||
{
|
||||
// <Tabs.TabPane
|
||||
// tab={
|
||||
// <span>
|
||||
// <Icon component={FaHistory} />
|
||||
// {t("jobs.labels.audit")}
|
||||
// </span>
|
||||
// }
|
||||
// key="audit"
|
||||
// >
|
||||
// <JobsDetailAuditContainer recordId={job.id} />
|
||||
// </Tabs.TabPane>
|
||||
// <Tabs.TabPane
|
||||
// tab={
|
||||
// <span>
|
||||
// <CheckSquareFilled />
|
||||
// {t("jobs.labels.checklists")}
|
||||
// </span>
|
||||
// }
|
||||
// key="checklists"
|
||||
// >
|
||||
// <JobsDetailChecklists job={job} />
|
||||
// </Tabs.TabPane>
|
||||
}
|
||||
</Tabs>
|
||||
</Form>
|
||||
</Suspense>
|
||||
|
||||
Reference in New Issue
Block a user