Added file scanning module.

This commit is contained in:
Patrick Fic
2020-10-21 14:33:45 -07:00
parent ee3136a3ac
commit 34e244783c
24 changed files with 435 additions and 61 deletions

View File

@@ -0,0 +1,23 @@
import { Typography } from "antd";
import React from "react";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { selectScanLastScanned } from "../../../redux/scan/scan.selectors";
import TimeAgoFormatter from "../../atoms/time-ago-formatter/time-ago-formatter.atom";
const mapStateToProps = createStructuredSelector({
lastScanned: selectScanLastScanned,
});
const mapDispatchToProps = (dispatch) => ({});
export function LastScannedAtom({ lastScanned }) {
return (
lastScanned && (
<Typography.Title level={5}>
<span>Last scanned </span>
<TimeAgoFormatter>{lastScanned}</TimeAgoFormatter>
</Typography.Title>
)
);
}
export default connect(mapStateToProps, mapDispatchToProps)(LastScannedAtom);

View File

@@ -0,0 +1,22 @@
import { Button } from "antd";
import React from "react";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { scanStart } from "../../../redux/scan/scan.actions";
import { selectScanLoading } from "../../../redux/scan/scan.selectors";
const mapStateToProps = createStructuredSelector({
scanLoading: selectScanLoading,
});
const mapDispatchToProps = (dispatch) => ({
scanStart: () => dispatch(scanStart()),
});
export function ScanRefreshAtom({ scanLoading, scanStart }) {
return (
<Button onClick={() => scanStart()} loading={scanLoading}>
Refresh
</Button>
);
}
export default connect(mapStateToProps, mapDispatchToProps)(ScanRefreshAtom);

View File

@@ -1,12 +1,19 @@
import { Tooltip } from "antd";
import moment from "moment";
import React from "react";
import React, { useEffect, useState } from "react";
export default function TimeAgoFormatter(props) {
const [timestampString, setTimestampString] = useState("");
const m = moment(props.children);
useEffect(() => {
const timer = setInterval(() => setTimestampString(m.fromNow()), 15000);
setTimestampString(m.fromNow());
return () => clearInterval(timer);
}, [m]);
return props.children ? (
<Tooltip placement="top" title={m.format("MM/DD/YYY hh:mm A")}>
{m.fromNow()}
{timestampString}
</Tooltip>
) : null;
}

View File

@@ -1,13 +1,13 @@
import { Input, Table } from "antd";
import React, { useState } from "react";
import { connect } from "react-redux";
import { Link } from "react-router-dom";
import { createStructuredSelector } from "reselect";
import { setSelectedJobId } from "../../../redux/application/application.actions";
import {
selectReportData,
selectReportLoading,
} from "../../../redux/reporting/reporting.selectors";
import { setSelectedJobId } from "../../../redux/application/application.actions";
import { Link } from "react-router-dom";
const mapStateToProps = createStructuredSelector({
reportingLoading: selectReportLoading,
reportData: selectReportData,
@@ -108,9 +108,11 @@ export function ReportingJobsListMolecule({
searchText !== ""
? reportData.filter(
(j) =>
j.v_makedesc.toLowerCase().includes(searchText.toLowerCase()) ||
j.v_model.toLowerCase().includes(searchText.toLowerCase()) ||
j.ownr_fn.toLowerCase().includes(searchText.toLowerCase()) ||
j.ownr_ln.toLowerCase().includes(searchText.toLowerCase()) ||
j.ownr_clm_no.toLowerCase().includes(searchText.toLowerCase())
j.clm_no.toLowerCase().includes(searchText.toLowerCase())
)
: reportData;

View File

@@ -0,0 +1,116 @@
import { Button, Input, Table } from "antd";
import React, { useState } from "react";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import ipcTypes from "../../../ipc.types";
import {
selectScanEstimates,
selectScanLoading,
} from "../../../redux/scan/scan.selectors";
import LastScannedAtom from "../../atoms/last-scanned/last-scanned.atom";
import ScanRefreshAtom from "../../atoms/scan-refresh/scan-refresh.atom";
const { ipcRenderer } = window;
const mapStateToProps = createStructuredSelector({
scanLoading: selectScanLoading,
estimates: selectScanEstimates,
});
const mapDispatchToProps = (dispatch) => ({});
export function ScanEstimateListMolecule({ scanLoading, estimates }) {
const [searchText, setSearchText] = useState("");
const columns = [
{
title: "Claim No.",
dataIndex: "clm_no",
key: "clm_no",
},
{
title: "Ins Co.",
dataIndex: "ins_co_nm",
key: "ins_co_nm",
},
{
title: "First Name",
dataIndex: "ownr_fn",
key: "ownr_fn",
},
{
title: "Last Name",
dataIndex: "ownr_ln",
key: "ownr_ln",
},
{
title: "Vehicle",
dataIndex: "vehicle",
key: "vehicle",
render: (text, record) =>
`${record.v_model_yr} ${record.v_makedesc} ${record.v_model} (${record.v_type})`,
},
{
title: "Import",
dataIndex: "import",
key: "import",
render: (text, record) => (
<Button
onClick={() =>
ipcRenderer.send(
ipcTypes.default.fileScan.toMain.importJob,
record.filepath
)
}
>
Import
</Button>
),
},
];
const data =
searchText !== ""
? estimates.filter(
(j) =>
j.v_makedesc.toLowerCase().includes(searchText.toLowerCase()) ||
j.v_model.toLowerCase().includes(searchText.toLowerCase()) ||
j.ownr_fn.toLowerCase().includes(searchText.toLowerCase()) ||
j.ownr_ln.toLowerCase().includes(searchText.toLowerCase()) ||
j.clm_no.toLowerCase().includes(searchText.toLowerCase())
)
: estimates;
return (
<div>
<Table
title={() => (
<div className="imex-table-header">
<ScanRefreshAtom />
<LastScannedAtom />
<Input.Search
className="imex-table-header__search"
placeholder="Search"
onSearch={(val) => {
setSearchText(val);
}}
enterButton
allowClear
/>
</div>
)}
columns={columns}
rowKey="filepath"
loading={scanLoading}
size="small"
pagination={false}
dataSource={data}
scroll={{
x: true,
}}
/>
</div>
);
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(ScanEstimateListMolecule);

View File

@@ -3,6 +3,7 @@ import {
SettingFilled,
CloseOutlined,
BarChartOutlined,
FileAddFilled,
} from "@ant-design/icons";
import { Menu } from "antd";
import React from "react";
@@ -20,6 +21,9 @@ export default function SiderMenuOrganism() {
<Menu.Item key="/" icon={<PieChartOutlined />}>
<Link to="/">Jobs</Link>
</Menu.Item>
<Menu.Item key="/scan" icon={<FileAddFilled />}>
<Link to="/scan">File Scan</Link>
</Menu.Item>
<Menu.Item key="/reporting" icon={<BarChartOutlined />}>
<Link to="/reporting">Reporting</Link>
</Menu.Item>

View File

@@ -8,6 +8,7 @@ import ErrorResultAtom from "../../atoms/error-result/error-result.atom";
import SiderMenuOrganism from "../../organisms/sider-menu/sider-menu.organism";
import JobsPage from "../jobs/jobs.page";
import ReportingPage from "../reporting/reporting.page";
import ScanPage from "../scan/scan.page";
import SettingsPage from "../settings/settings.page";
const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop });
@@ -35,6 +36,7 @@ export function RoutesPage({ bodyshop }) {
<Layout.Content style={{ margin: "1rem", height: "100%" }}>
<Route exact path="/settings" component={SettingsPage} />
<Route exact path="/reporting" component={ReportingPage} />
<Route exact path="/scan" component={ScanPage} />
<Route exact path="/" component={JobsPage} />
</Layout.Content>
</Layout>

View File

@@ -0,0 +1,10 @@
import React from "react";
import ScanEstimateListMolecule from "../../molecules/scan-estimate-list/scan-estimate-list.molecule";
export default function ScanPage() {
return (
<div>
<ScanEstimateListMolecule />
</div>
);
}