Finalized read only job. Logic to detmerine what is read only outstanding. BOD-409

This commit is contained in:
Patrick Fic
2020-09-28 14:45:31 -07:00
parent 3ee003000d
commit cb412f377e
6 changed files with 107 additions and 79 deletions

View File

@@ -1,18 +1,17 @@
import { SyncOutlined } from "@ant-design/icons"; 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 React, { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { connect } from "react-redux"; 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 { setModalContext } from "../../redux/modals/modals.actions";
import CurrencyFormatter from "../../utils/CurrencyFormatter"; import CurrencyFormatter from "../../utils/CurrencyFormatter";
import { DateFormatter } from "../../utils/DateFormatter"; import { DateFormatter } from "../../utils/DateFormatter";
import { alphaSort } from "../../utils/sorters"; 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({ const mapStateToProps = createStructuredSelector({
jobRO: selectJobReadOnly, jobRO: selectJobReadOnly,
}); });
@@ -376,4 +375,7 @@ export function BillsListTableComponent({
</div> </div>
); );
} }
export default connect(null, mapDispatchToProps)(BillsListTableComponent); export default connect(
mapStateToProps,
mapDispatchToProps
)(BillsListTableComponent);

View File

@@ -6,7 +6,7 @@ import { TimePicker } from "antd";
import moment from "moment"; import moment from "moment";
//To be used as a form element only. //To be used as a form element only.
const DateTimePicker = ({ value, onChange, onBlur }, ref) => { const DateTimePicker = ({ value, onChange, onBlur, ...restProps }, ref) => {
// const handleChange = (newDate) => { // const handleChange = (newDate) => {
// if (value !== newDate && onChange) { // if (value !== newDate && onChange) {
// onChange(newDate); // onChange(newDate);
@@ -15,9 +15,15 @@ const DateTimePicker = ({ value, onChange, onBlur }, ref) => {
return ( return (
<div> <div>
<FormDatePicker value={value} onBlur={onBlur} onChange={onChange} /> <FormDatePicker
{...restProps}
value={value}
onBlur={onBlur}
onChange={onChange}
/>
<TimePicker <TimePicker
{...restProps}
value={value ? moment(value) : null} value={value ? moment(value) : null}
onChange={onChange} onChange={onChange}
showSecond={false} showSecond={false}

View File

@@ -1,11 +1,18 @@
import { Form } from "antd"; import { Form } from "antd";
import React from "react"; import React from "react";
import { useTranslation } from "react-i18next"; 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 DateTimePicker from "../form-date-time-picker/form-date-time-picker.component";
import FormRow from "../layout-form-row/layout-form-row.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(); const { t } = useTranslation();
return ( return (
@@ -15,10 +22,10 @@ export default function JobsDetailDatesComponent({ job }) {
label={t("jobs.fields.date_estimated")} label={t("jobs.fields.date_estimated")}
name="date_estimated" name="date_estimated"
> >
<DateTimePicker /> <DateTimePicker disabled={jobRO} />
</Form.Item> </Form.Item>
<Form.Item label={t("jobs.fields.date_open")} name="date_open"> <Form.Item label={t("jobs.fields.date_open")} name="date_open">
<DateTimePicker /> <DateTimePicker disabled={jobRO} />
</Form.Item> </Form.Item>
</FormRow> </FormRow>
@@ -27,13 +34,13 @@ export default function JobsDetailDatesComponent({ job }) {
label={t("jobs.fields.date_scheduled")} label={t("jobs.fields.date_scheduled")}
name="date_scheduled" name="date_scheduled"
> >
<FormDatePicker /> <FormDatePicker disabled={jobRO} />
</Form.Item> </Form.Item>
<Form.Item label={t("jobs.fields.scheduled_in")} name="scheduled_in"> <Form.Item label={t("jobs.fields.scheduled_in")} name="scheduled_in">
<DateTimePicker /> <DateTimePicker disabled={jobRO} />
</Form.Item> </Form.Item>
<Form.Item label={t("jobs.fields.actual_in")} name="actual_in"> <Form.Item label={t("jobs.fields.actual_in")} name="actual_in">
<DateTimePicker /> <DateTimePicker disabled={jobRO} />
</Form.Item> </Form.Item>
</FormRow> </FormRow>
<FormRow header={t("jobs.forms.repairdates")}> <FormRow header={t("jobs.forms.repairdates")}>
@@ -41,38 +48,39 @@ export default function JobsDetailDatesComponent({ job }) {
label={t("jobs.fields.scheduled_completion")} label={t("jobs.fields.scheduled_completion")}
name="scheduled_completion" name="scheduled_completion"
> >
<DateTimePicker /> <DateTimePicker disabled={jobRO} />
</Form.Item> </Form.Item>
<Form.Item <Form.Item
label={t("jobs.fields.actual_completion")} label={t("jobs.fields.actual_completion")}
name="actual_completion" name="actual_completion"
> >
<DateTimePicker /> <DateTimePicker disabled={jobRO} />
</Form.Item> </Form.Item>
<Form.Item <Form.Item
label={t("jobs.fields.scheduled_delivery")} label={t("jobs.fields.scheduled_delivery")}
name="scheduled_delivery" name="scheduled_delivery"
> >
<DateTimePicker /> <DateTimePicker disabled={jobRO} />
</Form.Item> </Form.Item>
<Form.Item <Form.Item
label={t("jobs.fields.actual_delivery")} label={t("jobs.fields.actual_delivery")}
name="actual_delivery" name="actual_delivery"
> >
<DateTimePicker /> <DateTimePicker disabled={jobRO} />
</Form.Item> </Form.Item>
</FormRow> </FormRow>
<FormRow header={t("jobs.forms.admindates")}> <FormRow header={t("jobs.forms.admindates")}>
<Form.Item label={t("jobs.fields.date_invoiced")} name="date_invoiced"> <Form.Item label={t("jobs.fields.date_invoiced")} name="date_invoiced">
<DateTimePicker /> <DateTimePicker disabled={jobRO} />
</Form.Item> </Form.Item>
<Form.Item label={t("jobs.fields.date_closed")} name="date_closed"> <Form.Item label={t("jobs.fields.date_closed")} name="date_closed">
<DateTimePicker /> <DateTimePicker />
</Form.Item> </Form.Item>
<Form.Item label={t("jobs.fields.date_exported")} name="date_exported"> <Form.Item label={t("jobs.fields.date_exported")} name="date_exported">
<DateTimePicker /> <DateTimePicker disabled={jobRO} />
</Form.Item> </Form.Item>
</FormRow> </FormRow>
</div> </div>
); );
} }
export default connect(mapStateToProps, null)(JobsDetailDatesComponent);

View File

@@ -1,10 +1,20 @@
import React from "react"; 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 LaborAllocationsTableComponent from "../labor-allocations-table/labor-allocations-table.component";
import TimeTicketEnterButton from "../time-ticket-enter-button/time-ticket-enter-button.component"; import TimeTicketEnterButton from "../time-ticket-enter-button/time-ticket-enter-button.component";
import TimeTicketList from "../time-ticket-list/time-ticket-list.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, jobId,
joblines, joblines,
timetickets, timetickets,
@@ -16,7 +26,11 @@ export default function JobsDetailLaborContainer({
return ( return (
<div> <div>
{techConsole ? null : ( {techConsole ? null : (
<TimeTicketEnterButton actions={{ refetch }} context={{ jobId: jobId }}> <TimeTicketEnterButton
disabled={jobRO}
actions={{ refetch }}
context={{ jobId: jobId }}
>
{t("timetickets.actions.enter")} {t("timetickets.actions.enter")}
</TimeTicketEnterButton> </TimeTicketEnterButton>
)} )}
@@ -29,6 +43,7 @@ export default function JobsDetailLaborContainer({
timetickets={timetickets} timetickets={timetickets}
refetch={refetch} refetch={refetch}
techConsole={techConsole} techConsole={techConsole}
disabled={jobRO}
/> />
</div> </div>
); );

View File

@@ -10,6 +10,7 @@ import moment from "moment";
import { onlyUnique } from "../../utils/arrayHelper"; import { onlyUnique } from "../../utils/arrayHelper";
export default function TimeTicketList({ export default function TimeTicketList({
disabled,
loading, loading,
timetickets, timetickets,
refetch, refetch,
@@ -40,7 +41,8 @@ export default function TimeTicketList({
sortOrder: state.sortedInfo.columnKey === "vin" && state.sortedInfo.order, sortOrder: state.sortedInfo.columnKey === "vin" && state.sortedInfo.order,
render: (text, record) => ( render: (text, record) => (
<Link <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({
} }
}, },
}, },
{ !!techConsole
title: t("general.labels.actions"), ? {
dataIndex: "actions", title: t("general.labels.actions"),
key: "actions", dataIndex: "actions",
render: (text, record) => { key: "actions",
if (techConsole) return null; render: (text, record) => (
return ( <TimeTicketEnterButton
<TimeTicketEnterButton actions={{ refetch }}
actions={{ refetch }} context={{ id: record.id, timeticket: record }}
context={{ id: record.id, timeticket: record }} disabled={!!!record.job || disabled}
disabled={!!!record.job}> >
{t("general.actions.edit")} {t("general.actions.edit")}
</TimeTicketEnterButton> </TimeTicketEnterButton>
); ),
}, }
}, : null,
]; ];
const handleTableChange = (pagination, filters, sorter) => { const handleTableChange = (pagination, filters, sorter) => {
@@ -151,10 +153,10 @@ export default function TimeTicketList({
return ( return (
<Table <Table
loading={loading} loading={loading}
size='small' size="small"
pagination={{ position: "top" }} pagination={{ position: "top" }}
columns={columns.map((item) => ({ ...item }))} columns={columns.map((item) => ({ ...item }))}
rowKey='id' rowKey="id"
dataSource={timetickets} dataSource={timetickets}
onChange={handleTableChange} onChange={handleTableChange}
/> />

View File

@@ -4,7 +4,6 @@ import Icon, {
DollarCircleOutlined, DollarCircleOutlined,
FileImageFilled, FileImageFilled,
ToolFilled, ToolFilled,
CheckSquareFilled,
} from "@ant-design/icons"; } from "@ant-design/icons";
import { Form, notification, Tabs } from "antd"; import { Form, notification, Tabs } from "antd";
import Axios from "axios"; import Axios from "axios";
@@ -13,20 +12,15 @@ import moment from "moment";
import queryString from "query-string"; import queryString from "query-string";
import React, { lazy, Suspense, useState } from "react"; import React, { lazy, Suspense, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { import { FaHardHat, FaRegStickyNote, FaShieldAlt } from "react-icons/fa";
FaHardHat,
FaHistory,
FaRegStickyNote,
FaShieldAlt,
} from "react-icons/fa";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { useHistory, useLocation } from "react-router-dom"; import { useHistory, useLocation } from "react-router-dom";
import { createStructuredSelector } from "reselect"; import { createStructuredSelector } from "reselect";
import FormFieldsChanged from "../../components/form-fields-changed-alert/form-fields-changed-alert.component"; import FormFieldsChanged from "../../components/form-fields-changed-alert/form-fields-changed-alert.component";
import LoadingSpinner from "../../components/loading-spinner/loading-spinner.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 { selectJobReadOnly } from "../../redux/application/application.selectors";
import { selectBodyshop } from "../../redux/user/user.selectors";
const JobsLinesContainer = lazy(() => const JobsLinesContainer = lazy(() =>
import("../../components/job-detail-lines/job-lines.container") import("../../components/job-detail-lines/job-lines.container")
@@ -66,9 +60,9 @@ const JobLineUpsertModalContainer = lazy(() =>
const JobsDetailPliContainer = lazy(() => const JobsDetailPliContainer = lazy(() =>
import("../../components/jobs-detail-pli/jobs-detail-pli.container") import("../../components/jobs-detail-pli/jobs-detail-pli.container")
); );
const JobsDetailAuditContainer = lazy(() => // const JobsDetailAuditContainer = lazy(() =>
import("../../components/audit-trail-list/audit-trail-list.container") // import("../../components/audit-trail-list/audit-trail-list.container")
); // );
const JobsDetailLaborContainer = lazy(() => const JobsDetailLaborContainer = lazy(() =>
import("../../components/jobs-detail-labor/jobs-detail-labor.container") import("../../components/jobs-detail-labor/jobs-detail-labor.container")
); );
@@ -268,29 +262,30 @@ export function JobsDetailPage({
> >
<JobNotesContainer jobId={job.id} /> <JobNotesContainer jobId={job.id} />
</Tabs.TabPane> </Tabs.TabPane>
{
<Tabs.TabPane // <Tabs.TabPane
tab={ // tab={
<span> // <span>
<Icon component={FaHistory} /> // <Icon component={FaHistory} />
{t("jobs.labels.audit")} // {t("jobs.labels.audit")}
</span> // </span>
} // }
key="audit" // key="audit"
> // >
<JobsDetailAuditContainer recordId={job.id} /> // <JobsDetailAuditContainer recordId={job.id} />
</Tabs.TabPane> // </Tabs.TabPane>
<Tabs.TabPane // <Tabs.TabPane
tab={ // tab={
<span> // <span>
<CheckSquareFilled /> // <CheckSquareFilled />
{t("jobs.labels.checklists")} // {t("jobs.labels.checklists")}
</span> // </span>
} // }
key="checklists" // key="checklists"
> // >
<JobsDetailChecklists job={job} /> // <JobsDetailChecklists job={job} />
</Tabs.TabPane> // </Tabs.TabPane>
}
</Tabs> </Tabs>
</Form> </Form>
</Suspense> </Suspense>