diff --git a/bodyshop_translations.babel b/bodyshop_translations.babel index 7ee01f302..8e1022741 100644 --- a/bodyshop_translations.babel +++ b/bodyshop_translations.babel @@ -8184,27 +8184,6 @@ - - bodyhours - false - - - - - - en-US - false - - - es-MX - false - - - fr-CA - false - - - cards @@ -8871,27 +8850,6 @@ - - refinishhours - false - - - - - - en-US - false - - - es-MX - false - - - fr-CA - false - - - vehicle_info false @@ -11074,6 +11032,27 @@ actions + + addcolumns + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + bodypriority-clear false @@ -11158,6 +11137,27 @@ + + removecolumn + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + saveconfig false @@ -11247,6 +11247,27 @@ + + bodyhours + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + bodypriority false @@ -11331,6 +11352,27 @@ + + refinishhours + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + diff --git a/client/src/components/breadcrumbs/breadcrumbs.component.jsx b/client/src/components/breadcrumbs/breadcrumbs.component.jsx index 62ebb2b5a..ded2134a4 100644 --- a/client/src/components/breadcrumbs/breadcrumbs.component.jsx +++ b/client/src/components/breadcrumbs/breadcrumbs.component.jsx @@ -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 ( - Home + + + + + {breadcrumbs.map((item) => item.link ? ( diff --git a/client/src/components/production-list-columns/production-list-columns.add.component.jsx b/client/src/components/production-list-columns/production-list-columns.add.component.jsx new file mode 100644 index 000000000..5afeb8421 --- /dev/null +++ b/client/src/components/production-list-columns/production-list-columns.add.component.jsx @@ -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 = ( + + {dataSource + .filter((i) => !columnKeys.includes(i.key)) + .map((item) => ( + {item.title} + ))} + + ); + return ( +
+ + + +
+ ); +} + +// c.key)} +// render={(item) => item.title} +// onChange={(nextTargetKeys, direction, moveKeys) => { +// setColumns(dataSource.filter((i) => nextTargetKeys.includes(i.key))); +// }} +// /> diff --git a/client/src/components/production-list-columns/production-list-columns.component.jsx b/client/src/components/production-list-columns/production-list-columns.component.jsx deleted file mode 100644 index 8b93d8a24..000000000 --- a/client/src/components/production-list-columns/production-list-columns.component.jsx +++ /dev/null @@ -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 ( -
- c.key)} - render={(item) => item.title} - onChange={(nextTargetKeys, direction, moveKeys) => { - setColumns(dataSource.filter((i) => nextTargetKeys.includes(i.key))); - }} - /> -
- ); -} diff --git a/client/src/components/production-list-columns/production-list-columns.data.js b/client/src/components/production-list-columns/production-list-columns.data.js index 5b8843f5a..397980211 100644 --- a/client/src/components/production-list-columns/production-list-columns.data.js +++ b/client/src/components/production-list-columns/production-list-columns.data.js @@ -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) => , }, { - 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) => ( - - {(record.production_vars && record.production_vars.note) || ""} - - ), + ellipsis: true, + render: (text, record) => , }, { title: i18n.t("production.labels.cycletime"), diff --git a/client/src/components/production-list-columns/production-list-columns.productionnote.component.jsx b/client/src/components/production-list-columns/production-list-columns.productionnote.component.jsx new file mode 100644 index 000000000..43bf239a5 --- /dev/null +++ b/client/src/components/production-list-columns/production-list-columns.productionnote.component.jsx @@ -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 ( + + +
+ +
+ + } + trigger={["contextMenu"]}> +
+ {(record.production_vars && record.production_vars.note) || " "} +
+
+ ); +} diff --git a/client/src/components/production-list-columns/production-list-columns.status.component.jsx b/client/src/components/production-list-columns/production-list-columns.status.component.jsx new file mode 100644 index 000000000..9f85f92fc --- /dev/null +++ b/client/src/components/production-list-columns/production-list-columns.status.component.jsx @@ -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 ( + + {bodyshop.md_ro_statuses.statuses.map((item) => ( + {item} + ))} + + } + trigger={["contextMenu"]}> +
{record.status}
+
+ ); +} +export default connect(mapStateToProps, null)(ProductionListColumnStatus); diff --git a/client/src/components/production-list-table/production-list-table.component.jsx b/client/src/components/production-list-table/production-list-table.component.jsx index 7805eb4ce..1bae0d2d1 100644 --- a/client/src/components/production-list-table/production-list-table.component.jsx +++ b/client/src/components/production-list-table/production-list-table.component.jsx @@ -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) => ( + + + {t("production.actions.removecolumn")} + + + } + trigger={["contextMenu"]}> + {col.title} + + ); if (!!!columns) return
No columns found.
; return ( @@ -50,22 +70,26 @@ export function ProductionListTable({ size='small' pagination={false} title={() => ( -
+
+ -
)} - pagination={{ position: "top" }} columns={columns.map((c) => { return { ...c, sortOrder: state.sortedInfo.columnKey === c.key && state.sortedInfo.order, + title: headerItem(c), }; })} rowKey='id' diff --git a/client/src/components/production-list-table/production-list-table.container.jsx b/client/src/components/production-list-table/production-list-table.container.jsx index 652601a01..e357807f9 100644 --- a/client/src/components/production-list-table/production-list-table.container.jsx +++ b/client/src/components/production-list-table/production-list-table.container.jsx @@ -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 ( -
+ -
+ ); } diff --git a/client/src/graphql/jobs.queries.js b/client/src/graphql/jobs.queries.js index f303cf909..6ba8fa12f 100644 --- a/client/src/graphql/jobs.queries.js +++ b/client/src/graphql/jobs.queries.js @@ -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) { diff --git a/client/src/pages/production-list/production-list.component.jsx b/client/src/pages/production-list/production-list.component.jsx index dd9b43737..161c02891 100644 --- a/client/src/pages/production-list/production-list.component.jsx +++ b/client/src/pages/production-list/production-list.component.jsx @@ -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 ( -
- - -
- ); + return ; } diff --git a/client/src/translations/en_us/common.json b/client/src/translations/en_us/common.json index 6ad894fc3..89ba35c18 100644 --- a/client/src/translations/en_us/common.json +++ b/client/src/translations/en_us/common.json @@ -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": { diff --git a/client/src/translations/es/common.json b/client/src/translations/es/common.json index 09c47fcbc..131efa2af 100644 --- a/client/src/translations/es/common.json +++ b/client/src/translations/es/common.json @@ -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": { diff --git a/client/src/translations/fr/common.json b/client/src/translations/fr/common.json index abd197d87..79dacbb1a 100644 --- a/client/src/translations/fr/common.json +++ b/client/src/translations/fr/common.json @@ -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": {