BOD-21 Further customization of components. Added remove to header. Altered colum adding to use button instead of transfer

This commit is contained in:
Patrick Fic
2020-04-22 14:43:37 -07:00
parent 400dfabcec
commit 678f09b47a
14 changed files with 340 additions and 102 deletions

View File

@@ -8184,27 +8184,6 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>bodyhours</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<folder_node>
<name>cards</name>
<children>
@@ -8871,27 +8850,6 @@
</concept_node>
</children>
</folder_node>
<concept_node>
<name>refinishhours</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>vehicle_info</name>
<definition_loaded>false</definition_loaded>
@@ -11074,6 +11032,27 @@
<folder_node>
<name>actions</name>
<children>
<concept_node>
<name>addcolumns</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>bodypriority-clear</name>
<definition_loaded>false</definition_loaded>
@@ -11158,6 +11137,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>removecolumn</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>saveconfig</name>
<definition_loaded>false</definition_loaded>
@@ -11247,6 +11247,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>bodyhours</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>bodypriority</name>
<definition_loaded>false</definition_loaded>
@@ -11331,6 +11352,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>refinishhours</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
</children>
</folder_node>
</children>

View File

@@ -4,7 +4,7 @@ import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { selectBreadcrumbs } from "../../redux/application/application.selectors";
import { Link } from "react-router-dom";
import { HomeFilled } from "@ant-design/icons";
const mapStateToProps = createStructuredSelector({
breadcrumbs: selectBreadcrumbs,
});
@@ -12,7 +12,11 @@ const mapStateToProps = createStructuredSelector({
export function BreadCrumbs({ breadcrumbs }) {
return (
<Breadcrumb>
<Breadcrumb.Item>Home</Breadcrumb.Item>
<Breadcrumb.Item>
<Link to={`/manage`}>
<HomeFilled />
</Link>
</Breadcrumb.Item>
{breadcrumbs.map((item) =>
item.link ? (
<Breadcrumb.Item key={item.label}>

View File

@@ -0,0 +1,41 @@
import React from "react";
import { Button, Dropdown, Menu } from "antd";
import dataSource from "./production-list-columns.data";
import { useTranslation } from "react-i18next";
export default function ProductionColumnsComponent({ columnState }) {
const [columns, setColumns] = columnState;
const { t } = useTranslation();
const handleAdd = (e) => {
setColumns([...columns, ...dataSource.filter((i) => i.key === e.key)]);
};
const columnKeys = columns.map((i) => i.key);
const menu = (
<Menu onClick={handleAdd}>
{dataSource
.filter((i) => !columnKeys.includes(i.key))
.map((item) => (
<Menu.Item key={item.key}>{item.title}</Menu.Item>
))}
</Menu>
);
return (
<div>
<Dropdown overlay={menu}>
<Button>{t("production.actions.addcolumns")}</Button>
</Dropdown>
</div>
);
}
// <Transfer
// dataSource={dataSource}
// titles={["Source", "Target"]}
// targetKeys={columns.map((c) => c.key)}
// render={(item) => item.title}
// onChange={(nextTargetKeys, direction, moveKeys) => {
// setColumns(dataSource.filter((i) => nextTargetKeys.includes(i.key)));
// }}
// />

View File

@@ -1,22 +0,0 @@
import React from "react";
import { Transfer } from "antd";
import dataSource from "./production-list-columns.data";
export default function ProductionColumnsComponent({ columnState }) {
const [columns, setColumns] = columnState;
return (
<div>
<Transfer
dataSource={dataSource}
titles={["Source", "Target"]}
targetKeys={columns.map((c) => c.key)}
render={(item) => item.title}
onChange={(nextTargetKeys, direction, moveKeys) => {
setColumns(dataSource.filter((i) => nextTargetKeys.includes(i.key)));
}}
/>
</div>
);
}

View File

@@ -8,6 +8,8 @@ import { alphaSort } from "../../utils/sorters";
import ProductionListColumnAlert from "./production-list-columns.alert.component";
import ProductionListColumnBodyPriority from "./production-list-columns.bodypriority.component";
import ProductionListColumnPaintPriority from "./production-list-columns.paintpriority.component";
import ProductionListColumnStatus from "./production-list-columns.status.component";
import ProductionListColumnNote from "./production-list-columns.productionnote.component";
export default [
{
@@ -135,15 +137,16 @@ export default [
key: "status",
ellipsis: true,
sorter: (a, b) => alphaSort(a.status, b.status),
render: (text, record) => <ProductionListColumnStatus record={record} />,
},
{
title: i18n.t("jobs.labels.bodyhours"),
title: i18n.t("production.labels.bodyhours"),
dataIndex: "labhrs",
key: "labhrs",
sorter: (a, b) => a.labhrs - b.labhrs,
},
{
title: i18n.t("jobs.labels.refinishhours"),
title: i18n.t("production.labels.refinishhours"),
dataIndex: "larhrs",
key: "larhrs",
sorter: (a, b) => a.larhrs - b.larhrs,
@@ -158,11 +161,8 @@ export default [
title: i18n.t("production.labels.note"),
dataIndex: "note",
key: "note",
render: (text, record) => (
<span>
{(record.production_vars && record.production_vars.note) || ""}
</span>
),
ellipsis: true,
render: (text, record) => <ProductionListColumnNote record={record} />,
},
{
title: i18n.t("production.labels.cycletime"),

View File

@@ -0,0 +1,72 @@
import { useMutation } from "@apollo/react-hooks";
import { Button, Input, Popover } from "antd";
import React, { useState } from "react";
import { useTranslation } from "react-i18next";
import { UPDATE_JOB } from "../../graphql/jobs.queries";
export default function ProductionListColumnProductionNote({ record }) {
const { t } = useTranslation();
const [note, setNote] = useState(
(record.production_vars && record.production_vars.note) || ""
);
const [visible, setVisible] = useState(false);
const [updateAlert] = useMutation(UPDATE_JOB);
const handleSaveNote = (e) => {
setVisible(false);
updateAlert({
variables: {
jobId: record.id,
job: {
production_vars: {
...record.production_vars,
note: note,
},
},
},
}).then(() => {
if (record.refetch) record.refetch();
});
};
const handleChange = (e) => {
setNote(e.target.value);
};
const handleVisibleChange = (flag) => {
setVisible(flag);
if (flag)
setNote((record.production_vars && record.production_vars.note) || "");
};
return (
<Popover
onVisibleChange={handleVisibleChange}
visible={visible}
content={
<div style={{ width: "30em" }}>
<Input.TextArea
rows={2}
value={note}
onChange={handleChange}
onPressEnter={handleSaveNote}
autoFocus
allowClear
/>
<div>
<Button onClick={handleSaveNote}>
{t("general.actions.save")}
</Button>
</div>
</div>
}
trigger={["contextMenu"]}>
<div style={{ width: "100%", height: "19px" }}>
{(record.production_vars && record.production_vars.note) || " "}
</div>
</Popover>
);
}

View File

@@ -0,0 +1,46 @@
import { useMutation } from "@apollo/react-hooks";
import { Dropdown, Menu } from "antd";
import React from "react";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { UPDATE_JOB } from "../../graphql/jobs.queries";
import { selectBodyshop } from "../../redux/user/user.selectors";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
});
export function ProductionListColumnStatus({ record, bodyshop }) {
const [updateJob] = useMutation(UPDATE_JOB);
const handleSetStatus = (e) => {
const { key } = e;
updateJob({
variables: {
jobId: record.id,
job: {
status: key,
},
},
}).then(() => {
if (record.refetch) record.refetch();
});
};
return (
<Dropdown
overlay={
<Menu
style={{ maxHeight: "200px", overflowY: "auto" }}
onClick={handleSetStatus}>
{bodyshop.md_ro_statuses.statuses.map((item) => (
<Menu.Item key={item}>{item}</Menu.Item>
))}
</Menu>
}
trigger={["contextMenu"]}>
<div style={{ width: "100%", height: "19px" }}>{record.status}</div>
</Dropdown>
);
}
export default connect(mapStateToProps, null)(ProductionListColumnStatus);

View File

@@ -1,4 +1,4 @@
import { Table, Button } from "antd";
import { Table, Button, Menu, Dropdown } from "antd";
import React, { useState } from "react";
import { SyncOutlined } from "@ant-design/icons";
import ProductionListSaveConfigButton from "../production-list-save-config-button/production-list-save-config-button.component";
@@ -7,6 +7,8 @@ import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import ReactDragListView from "react-drag-listview"; //TODO Is there a better way? This library is too big.
import "./production-list-table.styles.scss";
import { useTranslation } from "react-i18next";
import ProductionListColumnsAdd from "../production-list-columns/production-list-columns.add.component";
const mapStateToProps = createStructuredSelector({
//currentUser: selectCurrentUser
@@ -30,7 +32,7 @@ export function ProductionListTable({
filteredInfo: { text: "" },
}
);
const { t } = useTranslation();
const handleTableChange = (pagination, filters, sorter) => {
setState({ ...state, filteredInfo: filters, sortedInfo: sorter });
};
@@ -42,6 +44,24 @@ export function ProductionListTable({
setColumns(columnsCopy);
};
const removeColumn = (e) => {
const { key } = e;
setColumns(columns.filter((i) => i.key !== key));
};
const headerItem = (col) => (
<Dropdown
overlay={
<Menu onClick={removeColumn}>
<Menu.Item key={col.key}>
{t("production.actions.removecolumn")}
</Menu.Item>
</Menu>
}
trigger={["contextMenu"]}>
<span>{col.title}</span>
</Dropdown>
);
if (!!!columns) return <div>No columns found.</div>;
return (
@@ -50,22 +70,26 @@ export function ProductionListTable({
size='small'
pagination={false}
title={() => (
<div>
<div style={{ display: "flex" }}>
<ProductionListColumnsAdd columnState={columnState} />
<ProductionListSaveConfigButton
columns={columns}
tableState={state}
/>
<Button onClick={() => refetch()}>
<Button
onClick={() => {
if (refetch) refetch();
}}>
<SyncOutlined />
</Button>
</div>
)}
pagination={{ position: "top" }}
columns={columns.map((c) => {
return {
...c,
sortOrder:
state.sortedInfo.columnKey === c.key && state.sortedInfo.order,
title: headerItem(c),
};
})}
rowKey='id'

View File

@@ -1,21 +1,23 @@
import { useQuery } from "@apollo/react-hooks";
import { useSubscription } from "@apollo/react-hooks";
import React from "react";
import { QUERY_JOBS_IN_PRODUCTION } from "../../graphql/jobs.queries";
import { SUBSCRIPTION_JOBS_IN_PRODUCTION } from "../../graphql/jobs.queries";
import ProductionListTable from "./production-list-table.component";
export default function ProductionListTableContainer({ columnState }) {
const { loading, data, refetch } = useQuery(QUERY_JOBS_IN_PRODUCTION, {
pollInterval: 30000,
});
// const { loading, data, refetch } = useQuery(QUERY_JOBS_IN_PRODUCTION, {
// pollInterval: 30000,
// });
const { loading, data } = useSubscription(SUBSCRIPTION_JOBS_IN_PRODUCTION);
return (
<div>
<ProductionListTable
loading={loading}
data={data ? data.productionview : []}
refetch={refetch}
refetch={null}
columnState={columnState}
/>
</div>
);
}

View File

@@ -79,6 +79,35 @@ export const QUERY_JOBS_IN_PRODUCTION = gql`
}
`;
export const SUBSCRIPTION_JOBS_IN_PRODUCTION = gql`
subscription SUBSCRIPTION_JOBS_IN_PRODUCTION {
productionview {
id
status
ro_number
est_number
ownr_fn
ownr_ln
v_model_yr
v_model_desc
clm_no
v_make_desc
v_color
plate_no
actual_in
scheduled_completion
scheduled_delivery
ins_co_nm
clm_total
ownr_ph1
special_coverage_policy
production_vars
labhrs
larhrs
}
}
`;
export const GET_JOB_BY_PK = gql`
query GET_JOB_BY_PK($id: uuid!) {
jobs_by_pk(id: $id) {

View File

@@ -1,12 +1,6 @@
import React from "react";
import ProductionListColumns from "../../components/production-list-columns/production-list-columns.component";
import ProductionListTable from "../../components/production-list-table/production-list-table.container";
export default function ProductionListComponent({ columnState }) {
return (
<div>
<ProductionListColumns columnState={columnState} />
<ProductionListTable columnState={columnState} />
</div>
);
return <ProductionListTable columnState={columnState} />;
}

View File

@@ -528,7 +528,6 @@
"audit": "Audit Trail",
"availablenew": "Available New Jobs",
"availablesupplements": "Available Supplements",
"bodyhours": "Body Hrs",
"cards": {
"appraiser": "Appraiser",
"customer": "Customer Information",
@@ -566,7 +565,6 @@
"ratetotals": {
"lab": "Body Total"
},
"refinishhours": "Refinish Hrs",
"vehicle_info": "Vehicle"
},
"successes": {
@@ -722,20 +720,24 @@
},
"production": {
"actions": {
"addcolumns": "Add Columns",
"bodypriority-clear": "Clear Body Priority",
"bodypriority-set": "Set Body Priority",
"paintpriority-clear": "Clear Paint Priority",
"paintpriority-set": "Set Paint Priority",
"removecolumn": "Remove Column",
"saveconfig": "Save Configuration"
},
"labels": {
"alert": "Alert",
"alertoff": "Remove alert from job",
"alerton": "Add alert to job",
"bodyhours": "B",
"bodypriority": "B/P",
"cycletime": "C/T",
"note": "Production Note",
"paintpriority": "P/P"
"paintpriority": "P/P",
"refinishhours": "R"
}
},
"profile": {

View File

@@ -528,7 +528,6 @@
"audit": "",
"availablenew": "",
"availablesupplements": "",
"bodyhours": "",
"cards": {
"appraiser": "Tasador",
"customer": "Información al cliente",
@@ -566,7 +565,6 @@
"ratetotals": {
"lab": ""
},
"refinishhours": "",
"vehicle_info": "Vehículo"
},
"successes": {
@@ -722,20 +720,24 @@
},
"production": {
"actions": {
"addcolumns": "",
"bodypriority-clear": "",
"bodypriority-set": "",
"paintpriority-clear": "",
"paintpriority-set": "",
"removecolumn": "",
"saveconfig": ""
},
"labels": {
"alert": "",
"alertoff": "",
"alerton": "",
"bodyhours": "",
"bodypriority": "",
"cycletime": "",
"note": "",
"paintpriority": ""
"paintpriority": "",
"refinishhours": ""
}
},
"profile": {

View File

@@ -528,7 +528,6 @@
"audit": "",
"availablenew": "",
"availablesupplements": "",
"bodyhours": "",
"cards": {
"appraiser": "Expert",
"customer": "Informations client",
@@ -566,7 +565,6 @@
"ratetotals": {
"lab": ""
},
"refinishhours": "",
"vehicle_info": "Véhicule"
},
"successes": {
@@ -722,20 +720,24 @@
},
"production": {
"actions": {
"addcolumns": "",
"bodypriority-clear": "",
"bodypriority-set": "",
"paintpriority-clear": "",
"paintpriority-set": "",
"removecolumn": "",
"saveconfig": ""
},
"labels": {
"alert": "",
"alertoff": "",
"alerton": "",
"bodyhours": "",
"bodypriority": "",
"cycletime": "",
"note": "",
"paintpriority": ""
"paintpriority": "",
"refinishhours": ""
}
},
"profile": {