Added job searching, sider keys, formatting on settings

This commit is contained in:
Patrick Fic
2020-10-19 13:03:57 -07:00
parent 2c696425b6
commit a11c44e444
29 changed files with 357 additions and 61 deletions

View File

@@ -1,8 +1,8 @@
import { Skeleton, Typography } from "antd";
import Dinero from "dinero.js";
import React, { useMemo } from "react";
import { Cell, Pie, PieChart, ResponsiveContainer } from "recharts";
import ErrorResultAtom from "../error-result/error-result.atom";
import Dinero from "dinero.js";
import partTypeConverterAtom from "../part-type-converter/part-type-converter.atom";
export default function JobPartsGraphAtom({
job,
@@ -36,7 +36,7 @@ export default function JobPartsGraphAtom({
if (loading) return <Skeleton active />;
if (!job) return <ErrorResultAtom title="Error displaying job data." />;
console.log("data", data);
return (
<div
style={{

View File

@@ -14,8 +14,8 @@ const mapStateToProps = createStructuredSelector({
export function WatcherStatusAtom({ watcherStatus, watcherError }) {
return (
<div>
{watcherStatus}
<div style={{ color: watcherStatus === "Started" ? "green" : "tomato" }}>
<strong>{watcherStatus}</strong>
{watcherError && <Alert message={watcherError} />}
</div>
);

View File

@@ -0,0 +1,38 @@
import { SearchOutlined } from "@ant-design/icons";
import { Button, DatePicker, Form, Input } from "antd";
import React from "react";
export default function JobsSearchFieldsMolecule({ callSearchQuery }) {
const [form] = Form.useForm();
const handleFinish = (values) => {
callSearchQuery({
variables: {
search: values.search,
startDate: (values.dateRange && values.dateRange[0]) || null,
endDate: (values.dateRange && values.dateRange[1]) || null,
},
});
};
return (
<div>
<Form
autoComplete="new-password"
size="small"
onFinish={handleFinish}
form={form}
>
<Form.Item name="search">
<Input placeholder="Search by Claim # or Name" />
</Form.Item>
<Form.Item name="dateRange" rules={[{ type: "array" }]}>
<DatePicker.RangePicker />
</Form.Item>
<Button type="primary" htmlType="submit" onClick={() => form.submit()}>
<SearchOutlined />
Search
</Button>
</Form>
</div>
);
}

View File

@@ -1,4 +1,4 @@
import { Button, Input, Form, Select, InputNumber } from "antd";
import { Button, Input, Form, Select, InputNumber, Typography } from "antd";
import FormListMoveArrows from "../../atoms/form-list-move-arrows/form-list-move-arrows.atom";
import React from "react";
import LayoutFormRow from "../../atoms/layout-form-row/layout-form-row.atom";
@@ -7,6 +7,7 @@ import { DeleteFilled } from "@ant-design/icons";
export default function ShopSettingsFormMolecule({ form, saveLoading }) {
return (
<div>
<Typography.Title>Shop Settings</Typography.Title>
<Button
type="primary"
loading={saveLoading}
@@ -14,31 +15,33 @@ export default function ShopSettingsFormMolecule({ form, saveLoading }) {
>
Save
</Button>
<Form.Item
label="Shop Name"
name="shopname"
rules={[
{
required: true,
},
]}
>
<Input />
</Form.Item>
<Form.Item
name="accepted_ins_co"
label="Accepted Insurance Company Names (must be exactly as in estimating system)"
rules={[
{
required: true,
type: "array",
},
]}
>
<Select mode="tags" />
</Form.Item>
<LayoutFormRow grow>
<Form.Item
label="Shop Name"
name="shopname"
rules={[
{
required: true,
},
]}
>
<Input />
</Form.Item>
<Form.Item
name="accepted_ins_co"
label="Accepted Insurance Company Names (must be exactly as in estimating system)"
rules={[
{
required: true,
type: "array",
},
]}
>
<Select mode="tags" />
</Form.Item>
</LayoutFormRow>
<Typography.Title level={4}>Group Definitions</Typography.Title>
<Form.List name={["targets"]}>
{(fields, { add, remove, move }) => {
return (

View File

@@ -1,4 +1,4 @@
import { List } from "antd";
import { List, Typography } from "antd";
import React, { useEffect } from "react";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
@@ -24,7 +24,7 @@ export function FilePathsList({ watchedPaths }) {
console.log("watchedPaths", watchedPaths);
return (
<div>
File Paths
<Typography.Title>Watcher File Paths</Typography.Title>
<List dataSource={watchedPaths || []} renderItem={FilepathItemMolecule} />
<FilepathAddMolecule />
</div>

View File

@@ -3,24 +3,12 @@ import { useQuery } from "@apollo/client";
import { Dropdown, List, Menu, Spin } from "antd";
import React, { useState } from "react";
import InfiniteScroll from "react-infinite-scroller";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { QUERY_ALL_JOBS_PAGINATED } from "../../../graphql/jobs.queries";
import { setSelectedJobId } from "../../../redux/application/application.actions";
import { selectSelectedJobId } from "../../../redux/application/application.selectors";
import ErrorResultAtom from "../../atoms/error-result/error-result.atom";
import JobsListItemMolecule from "../../molecules/jobs-list-item/jobs-list-item.molecule";
import "./jobs-list-latest.organism.styles.scss";
const mapStateToProps = createStructuredSelector({
selectedJobId: selectSelectedJobId,
});
const mapDispatchToProps = (dispatch) => ({
setSelectedJobId: (jobId) => dispatch(setSelectedJobId(jobId)),
});
const limit = 20;
export function JobsTableOrganism({ selectedJobId, setSelectedJobId }) {
export default function JobsTableOrganism() {
const [state, setState] = useState({ hasMore: true });
const { loading, error, data, refetch, fetchMore } = useQuery(
@@ -110,4 +98,3 @@ export function JobsTableOrganism({ selectedJobId, setSelectedJobId }) {
</div>
);
}
export default connect(mapStateToProps, mapDispatchToProps)(JobsTableOrganism);

View File

@@ -1,9 +0,0 @@
.jobs-list-container {
height: 100%;
}
.jobs-list-infinite-container {
overflow-y: auto;
overflow-x: hidden;
height: 100%;
}

View File

@@ -0,0 +1,102 @@
import { SyncOutlined } from "@ant-design/icons";
import { useLazyQuery } from "@apollo/client";
import { Dropdown, List, Menu, Spin } from "antd";
import React, { useState } from "react";
import InfiniteScroll from "react-infinite-scroller";
import { SEARCH_JOBS_PAGINATED } from "../../../graphql/jobs.queries";
import ErrorResultAtom from "../../atoms/error-result/error-result.atom";
import JobsListItemMolecule from "../../molecules/jobs-list-item/jobs-list-item.molecule";
import JobsSearchFieldsMolecule from "../../molecules/jobs-search-fields/jobs-search-fields.molecule";
const limit = 20;
export default function JobsTableOrganism() {
const [state, setState] = useState({ hasMore: true });
const [
callSearch,
{ loading, error, data, refetch, fetchMore },
] = useLazyQuery(SEARCH_JOBS_PAGINATED, {
variables: {
offset: 0,
limit: limit,
},
});
const menu = (
<Menu>
<Menu.Item onClick={() => refetch()}>
<SyncOutlined />
Reload
</Menu.Item>
</Menu>
);
const handleInfiniteOnLoad = (page) => {
if (fetchMore)
fetchMore({
variables: {
offset: limit * page,
},
updateQuery: (prev, { fetchMoreResult }) => {
if (!fetchMoreResult) {
console.log("No more results. Fetch More was empty.");
setState({ ...state, hasMore: false });
return prev;
}
const newCache = Object.assign({}, prev, {
jobs: [...prev.search_jobs, ...fetchMoreResult.search_jobs],
});
if (
newCache.jobs.length >= data &&
data.search_jobs_aggregate.aggregate.count
) {
console.log("No more results.");
setState({ ...state, hasMore: false });
}
return newCache;
},
});
};
if (error)
return (
<ErrorResultAtom
title="Error fetching Jobs data."
errorMessage={JSON.stringify(error)}
/>
);
return (
<div className="jobs-list-container">
<JobsSearchFieldsMolecule callSearchQuery={callSearch} />
<div className="jobs-list-infinite-container">
<InfiniteScroll
pageStart={0}
loadMore={handleInfiniteOnLoad}
hasMore={!loading && state.hasMore}
useWindow={false}
>
<Dropdown overlay={menu} trigger={["contextMenu"]}>
<List
bordered
dataSource={data ? data.search_jobs : []}
renderItem={(item) => <JobsListItemMolecule item={item} />}
>
{loading && state.hasMore && (
<div>
<Spin />
</div>
)}
</List>
</Dropdown>
</InfiniteScroll>
</div>
{`${data ? data.search_jobs.length : 0} jobs loaded. ${
data ? data.search_jobs_aggregate.aggregate.count : 0
} total jobs.`}
</div>
);
}

View File

@@ -8,15 +8,18 @@ import React from "react";
import { Link } from "react-router-dom";
import ipcTypes from "../../../ipc.types";
import SiderSignOut from "../../molecules/sider-sign-out/sider-sign-out.molecule";
import { useLocation } from "react-router-dom";
const { ipcRenderer } = window;
export default function SiderMenuOrganism() {
const { pathname } = useLocation();
return (
<Menu defaultSelectedKeys={["1"]} mode="inline">
<Menu.Item key="1" icon={<PieChartOutlined />}>
<Menu defaultSelectedKeys={[`/`]} selectedKeys={[pathname]} mode="inline">
<Menu.Item key="/" icon={<PieChartOutlined />}>
<Link to="/">Jobs</Link>
</Menu.Item>
<Menu.Item key="2" icon={<SettingFilled />}>
<Menu.Item key="/settings" icon={<SettingFilled />}>
<Link to="/settings">Settings</Link>
</Menu.Item>
<SiderSignOut />

View File

@@ -1,3 +1,4 @@
import { Typography } from "antd";
import React from "react";
import WatcherStatusAtom from "../../atoms/watcher-status/watcher-status.atom";
import WatcherStartMolecule from "../../molecules/watcher-start/watcher-start.molecule";
@@ -6,6 +7,7 @@ import WatcherStopMolecule from "../../molecules/watcher-stop/watcher-stop.molec
export default function WatcherManagerOrganism() {
return (
<div>
<Typography.Title level={4}>Watcher Status</Typography.Title>
<WatcherStatusAtom />
<WatcherStartMolecule />
<WatcherStopMolecule />

View File

@@ -4,6 +4,7 @@ import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import JobsDetailOrganism from "../../organisms/jobs-detail/jobs-detail.organism";
import JobsListOrganism from "../../organisms/jobs-list-latest/jobs-list-latest.organism";
import JobsListSearchOrganism from "../../organisms/jobs-list-search/jobs-list-search.organism";
const mapStateToProps = createStructuredSelector({});
const mapDispatchToProps = (dispatch) => ({});
@@ -13,12 +14,12 @@ export function JobsPage() {
<div style={{ height: "100%" }}>
<Row gutter={[16, 16]} style={{ height: "100%" }}>
<Col span={6} style={{ height: "100%" }}>
<Tabs defaultActiveKey="search" style={{ height: "100%" }}>
<Tabs defaultActiveKey="latest" style={{ height: "100%" }}>
<Tabs.TabPane key="latest" tab="Latest" style={{ height: "100%" }}>
<JobsListOrganism />
</Tabs.TabPane>
<Tabs.TabPane key="search" tab="Search" style={{ height: "100%" }}>
Search
<JobsListSearchOrganism />
</Tabs.TabPane>
</Tabs>
</Col>

View File

@@ -1,12 +1,21 @@
import { Col, Row } from "antd";
import React from "react";
import FilePathsListOrganism from "../../organisms/filepaths-list/filepaths-list.organism";
import ShopSettingsOrganism from "../../organisms/shop-settings/shop-settings.organism";
import WatcherManagerOrganism from "../../organisms/watcher-manager/watcher-manager.organism";
export default function SettingsPage() {
return (
<div>
<FilePathsListOrganism />
<WatcherManagerOrganism />
<Row gutter={[16, 16]}>
<Col span={18}>
<FilePathsListOrganism />
</Col>
<Col span={6}>
<WatcherManagerOrganism />
</Col>
</Row>
<ShopSettingsOrganism />
</div>
);