From ebe5c5b11397485e9a45f0e184b6aabffb3caac8 Mon Sep 17 00:00:00 2001 From: Allan Carr Date: Fri, 12 Jan 2024 21:06:39 -0800 Subject: [PATCH 01/10] IO-2520 Adjust to imexshopid instead of shopname & prettify --- server/data/kaizen.js | 13 ++++++++++--- server/graphql-client/queries.js | 4 ++-- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/server/data/kaizen.js b/server/data/kaizen.js index 0df82a9ce..0d3720d25 100644 --- a/server/data/kaizen.js +++ b/server/data/kaizen.js @@ -29,17 +29,24 @@ const ftpSetup = { password: process.env.KAIZEN_PASSWORD, debug: (message, ...data) => logger.log(message, "DEBUG", "api", null, data), algorithms: { - serverHostKey: ["ssh-rsa", "ssh-dss", "rsa-sha2-256", "rsa-sha2-512", "ecdsa-sha2-nistp256", "ecdsa-sha2-nistp384"], + serverHostKey: [ + "ssh-rsa", + "ssh-dss", + "rsa-sha2-256", + "rsa-sha2-512", + "ecdsa-sha2-nistp256", + "ecdsa-sha2-nistp384", + ], }, }; exports.default = async (req, res) => { //Query for the List of Bodyshop Clients. logger.log("kaizen-start", "DEBUG", "api", null, null); - const kaizenShopsNames = ["SUMMIT", "STRATHMORE", "SUNRIDGE"]; + const kaizenShopsIDs = ["SUMMIT", "STRATHMORE", "SUNRIDGE"]; const { bodyshops } = await client.request(queries.GET_KAIZEN_SHOPS, { - shopname: kaizenShopsNames, + imexshopid: kaizenShopsIDs, }); const specificShopIds = req.body.bodyshopIds; // ['uuid] diff --git a/server/graphql-client/queries.js b/server/graphql-client/queries.js index 554388afe..b9c491de7 100644 --- a/server/graphql-client/queries.js +++ b/server/graphql-client/queries.js @@ -1739,8 +1739,8 @@ exports.GET_ENTEGRAL_SHOPS = `query GET_ENTEGRAL_SHOPS { } }`; -exports.GET_KAIZEN_SHOPS = `query GET_KAIZEN_SHOPS($shopname: [String]) { - bodyshops(where: {shopname: {_in: $shopname}}){ +exports.GET_KAIZEN_SHOPS = `query GET_KAIZEN_SHOPS($imexshopid: [String]) { + bodyshops(where: {imexshopid: {_in: $imexshopid}}){ id shopname address1 From 7245d4eab24cdb682c4fa9bca639eabff9e8be02 Mon Sep 17 00:00:00 2001 From: Allan Carr Date: Mon, 15 Jan 2024 18:54:28 -0800 Subject: [PATCH 02/10] IO-2603 Open Orders Excel --- client/src/translations/en_us/common.json | 1 + client/src/translations/es/common.json | 1 + client/src/translations/fr/common.json | 1 + client/src/utils/TemplateConstants.js | 13 +++++++++++++ 4 files changed, 16 insertions(+) diff --git a/client/src/translations/en_us/common.json b/client/src/translations/en_us/common.json index 09798f0a5..46dfbe01f 100644 --- a/client/src/translations/en_us/common.json +++ b/client/src/translations/en_us/common.json @@ -2621,6 +2621,7 @@ "open_orders": "Open Orders by Date", "open_orders_csr": "Open Orders by CSR", "open_orders_estimator": "Open Orders by Estimator", + "open_orders_excel": "Open Orders - Excel", "open_orders_ins_co": "Open Orders by Insurance Company", "open_orders_referral": "Open Orders by Referral Source", "open_orders_specific_csr": "Open Orders filtered by CSR", diff --git a/client/src/translations/es/common.json b/client/src/translations/es/common.json index da9f6b4e0..e7688ca48 100644 --- a/client/src/translations/es/common.json +++ b/client/src/translations/es/common.json @@ -2621,6 +2621,7 @@ "open_orders": "", "open_orders_csr": "", "open_orders_estimator": "", + "open_orders_excel": "", "open_orders_ins_co": "", "open_orders_referral": "", "open_orders_specific_csr": "", diff --git a/client/src/translations/fr/common.json b/client/src/translations/fr/common.json index a4c1dc686..4121c0c21 100644 --- a/client/src/translations/fr/common.json +++ b/client/src/translations/fr/common.json @@ -2621,6 +2621,7 @@ "open_orders": "", "open_orders_csr": "", "open_orders_estimator": "", + "open_orders_excel": "", "open_orders_ins_co": "", "open_orders_referral": "", "open_orders_specific_csr": "", diff --git a/client/src/utils/TemplateConstants.js b/client/src/utils/TemplateConstants.js index 365b2431e..eeb937c3a 100644 --- a/client/src/utils/TemplateConstants.js +++ b/client/src/utils/TemplateConstants.js @@ -2026,6 +2026,19 @@ export const TemplateList = (type, context) => { }, group: "customers", }, + open_orders_excel: { + title: i18n.t("reportcenter.templates.open_orders_excel"), + subject: i18n.t("reportcenter.templates.open_orders_excel"), + key: "open_orders_excel", + //idtype: "vendor", + reporttype: "excel", + disabled: false, + rangeFilter: { + object: i18n.t("reportcenter.labels.objects.jobs"), + field: i18n.t("jobs.fields.date_open"), + }, + group: "jobs", + }, } : {}), ...(!type || type === "courtesycarcontract" From b6b445dc21d9e1aed6ee91a048be4d1bd838d750 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Tue, 16 Jan 2024 14:02:54 -0500 Subject: [PATCH 03/10] - Update the look and feel of the chat message list (prevents breaking when zoomed in and out like previous implementation) Signed-off-by: Dave Richer --- .../chat-conversation-list.component.jsx | 198 +++++++++--------- .../chat-conversation-list.styles.scss | 7 +- 2 files changed, 101 insertions(+), 104 deletions(-) diff --git a/client/src/components/chat-conversation-list/chat-conversation-list.component.jsx b/client/src/components/chat-conversation-list/chat-conversation-list.component.jsx index 1f9f66e7b..3568a4d20 100644 --- a/client/src/components/chat-conversation-list/chat-conversation-list.component.jsx +++ b/client/src/components/chat-conversation-list/chat-conversation-list.component.jsx @@ -1,120 +1,116 @@ -import {Badge, List, Space, Tag} from "antd"; +import {Badge, Card, List, Space, Tag} from "antd"; import React from "react"; -import { connect } from "react-redux"; -import { - AutoSizer, - CellMeasurer, - CellMeasurerCache, - List as VirtualizedList, -} from "react-virtualized"; -import { createStructuredSelector } from "reselect"; -import { setSelectedConversation } from "../../redux/messaging/messaging.actions"; -import { selectSelectedConversation } from "../../redux/messaging/messaging.selectors"; -import { TimeAgoFormatter } from "../../utils/DateFormatter"; +import {connect} from "react-redux"; +import {AutoSizer, CellMeasurer, CellMeasurerCache, List as VirtualizedList,} from "react-virtualized"; +import {createStructuredSelector} from "reselect"; +import {setSelectedConversation} from "../../redux/messaging/messaging.actions"; +import {selectSelectedConversation} from "../../redux/messaging/messaging.selectors"; +import {TimeAgoFormatter} from "../../utils/DateFormatter"; import PhoneFormatter from "../../utils/PhoneFormatter"; -import OwnerNameDisplay from "../owner-name-display/owner-name-display.component"; - +import OwnerNameDisplay, {OwnerNameDisplayFunction} from "../owner-name-display/owner-name-display.component"; +import _ from "lodash"; import "./chat-conversation-list.styles.scss"; const mapStateToProps = createStructuredSelector({ - selectedConversation: selectSelectedConversation, + selectedConversation: selectSelectedConversation, }); const mapDispatchToProps = (dispatch) => ({ - setSelectedConversation: (conversationId) => - dispatch(setSelectedConversation(conversationId)), + setSelectedConversation: (conversationId) => + dispatch(setSelectedConversation(conversationId)), }); function ChatConversationListComponent({ - conversationList, - selectedConversation, - setSelectedConversation, - loadMoreConversations, -}) { - const cache = new CellMeasurerCache({ - fixedWidth: true, - defaultHeight: 60, - }); + conversationList, + selectedConversation, + setSelectedConversation, + loadMoreConversations, + }) { + const cache = new CellMeasurerCache({ + fixedWidth: true, + defaultHeight: 60, + }); + + const rowRenderer = ({index, key, style, parent}) => { + const item = conversationList[index]; + const cardContentRight = + {item.updated_at}; + const cardContentLeft = item.job_conversations.length > 0 + ? item.job_conversations.map((j, idx) => ( + {j.job.ro_number} + )) + : null; + + const names = <>{_.uniq(item.job_conversations.map((j, idx) => + OwnerNameDisplayFunction(j.job) + ))} + + const cardTitle = <> + {item.label && {item.label}} + {item.job_conversations.length > 0 ? ( + + {names} + + ) : ( + + {item.phone_num} + + )} + + const cardExtra = + const cardStyle = index % 2 === 0 ? {backgroundColor: '#f0f2f5'} : {backgroundColor: '#ffffff'}; + return ( + + setSelectedConversation(item.id)} + style={style} + className={`chat-list-item + ${ + item.id === selectedConversation + ? "chat-list-selected-conversation" + : null + }`} + > + +
+ {cardContentLeft} +
+
{cardContentRight}
+
+
+
+ ); + }; - const rowRenderer = ({ index, key, style, parent }) => { - const item = conversationList[index]; return ( - - setSelectedConversation(item.id)} - style={style} - className={`chat-list-item - ${ - item.id === selectedConversation - ? "chat-list-selected-conversation" - : null - }`} - > - - - {item.label && {item.label}} - {item.job_conversations.length > 0 ? ( - - {item.job_conversations.map((j, idx) => ( - - ))} - - ) : ( - - {item.phone_num} - +
+ + {({height, width}) => ( + { + if (scrollTop + clientHeight === scrollHeight) { + loadMoreConversations(); + } + }} + /> )} - - - - {item.job_conversations.length > 0 - ? item.job_conversations.map((j, idx) => ( - {j.job.ro_number} - )) - : null} - - - {item.updated_at} - - - - - - - - + +
); - }; - - return ( -
- - {({ height, width }) => ( - { - if (scrollTop + clientHeight === scrollHeight) { - loadMoreConversations(); - } - }} - /> - )} - -
- ); } export default connect( - mapStateToProps, - mapDispatchToProps + mapStateToProps, + mapDispatchToProps )(ChatConversationListComponent); diff --git a/client/src/components/chat-conversation-list/chat-conversation-list.styles.scss b/client/src/components/chat-conversation-list/chat-conversation-list.styles.scss index 44f6f8ec8..a63474c04 100644 --- a/client/src/components/chat-conversation-list/chat-conversation-list.styles.scss +++ b/client/src/components/chat-conversation-list/chat-conversation-list.styles.scss @@ -7,10 +7,11 @@ border: 1px solid gainsboro; } .chat-list-item { + .ant-card-head { + border: none; + } &:hover { cursor: pointer; color: #ff7a00; } - - border-bottom: 1px solid gainsboro; -} \ No newline at end of file +} From a38611a58460d0c538281ab11b613731cc60f114 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Tue, 16 Jan 2024 14:12:54 -0500 Subject: [PATCH 04/10] - Fix chat list item selected background (regression) Signed-off-by: Dave Richer --- .../chat-conversation-list.component.jsx | 18 ++++++++++++++---- .../chat-conversation-list.styles.scss | 3 --- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/client/src/components/chat-conversation-list/chat-conversation-list.component.jsx b/client/src/components/chat-conversation-list/chat-conversation-list.component.jsx index 3568a4d20..01a4ebe53 100644 --- a/client/src/components/chat-conversation-list/chat-conversation-list.component.jsx +++ b/client/src/components/chat-conversation-list/chat-conversation-list.component.jsx @@ -7,7 +7,7 @@ import {setSelectedConversation} from "../../redux/messaging/messaging.actions"; import {selectSelectedConversation} from "../../redux/messaging/messaging.selectors"; import {TimeAgoFormatter} from "../../utils/DateFormatter"; import PhoneFormatter from "../../utils/PhoneFormatter"; -import OwnerNameDisplay, {OwnerNameDisplayFunction} from "../owner-name-display/owner-name-display.component"; +import {OwnerNameDisplayFunction} from "../owner-name-display/owner-name-display.component"; import _ from "lodash"; import "./chat-conversation-list.styles.scss"; @@ -58,7 +58,16 @@ function ChatConversationListComponent({ )} const cardExtra = - const cardStyle = index % 2 === 0 ? {backgroundColor: '#f0f2f5'} : {backgroundColor: '#ffffff'}; + + const getCardStyle = () => { + if (item.id === selectedConversation) { + return { + backgroundColor: 'rgba(128, 128, 128, 0.2)' + } + } + return index % 2 === 0 ? {backgroundColor: '#f0f2f5'} : {backgroundColor: '#ffffff'}; + } + return ( - +
{cardContentLeft}
-
{cardContentRight}
+
{cardContentRight}
diff --git a/client/src/components/chat-conversation-list/chat-conversation-list.styles.scss b/client/src/components/chat-conversation-list/chat-conversation-list.styles.scss index a63474c04..7915c5c2a 100644 --- a/client/src/components/chat-conversation-list/chat-conversation-list.styles.scss +++ b/client/src/components/chat-conversation-list/chat-conversation-list.styles.scss @@ -1,6 +1,3 @@ -.chat-list-selected-conversation { - background-color: rgba(128, 128, 128, 0.2); -} .chat-list-container { overflow: hidden; height: 100%; From 690e65df0b3065d4a5335ca6002684d25419368a Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Tue, 16 Jan 2024 14:14:00 -0500 Subject: [PATCH 05/10] - A little refactor cleanup Signed-off-by: Dave Richer --- .../chat-conversation-list.component.jsx | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/client/src/components/chat-conversation-list/chat-conversation-list.component.jsx b/client/src/components/chat-conversation-list/chat-conversation-list.component.jsx index 01a4ebe53..3e47943e2 100644 --- a/client/src/components/chat-conversation-list/chat-conversation-list.component.jsx +++ b/client/src/components/chat-conversation-list/chat-conversation-list.component.jsx @@ -59,14 +59,10 @@ function ChatConversationListComponent({ const cardExtra = - const getCardStyle = () => { - if (item.id === selectedConversation) { - return { - backgroundColor: 'rgba(128, 128, 128, 0.2)' - } - } - return index % 2 === 0 ? {backgroundColor: '#f0f2f5'} : {backgroundColor: '#ffffff'}; - } + const getCardStyle = () => + item.id === selectedConversation + ? { backgroundColor: 'rgba(128, 128, 128, 0.2)' } + : { backgroundColor: index % 2 === 0 ? '#f0f2f5' : '#ffffff' }; return ( Date: Tue, 16 Jan 2024 12:11:18 -0800 Subject: [PATCH 06/10] IO-2531 Retain Filtered Statue for Jobs Pages --- .../jobs-list-paginated.component.jsx | 7 +- .../jobs-list/jobs-list.component.jsx | 725 +++++++++--------- .../jobs-ready-list.component.jsx | 44 +- 3 files changed, 397 insertions(+), 379 deletions(-) diff --git a/client/src/components/jobs-list-paginated/jobs-list-paginated.component.jsx b/client/src/components/jobs-list-paginated/jobs-list-paginated.component.jsx index b5048d0ef..1b4c6f435 100644 --- a/client/src/components/jobs-list-paginated/jobs-list-paginated.component.jsx +++ b/client/src/components/jobs-list-paginated/jobs-list-paginated.component.jsx @@ -10,9 +10,10 @@ import { Link, useHistory, useLocation } from "react-router-dom"; import { createStructuredSelector } from "reselect"; import { selectBodyshop } from "../../redux/user/user.selectors"; import CurrencyFormatter from "../../utils/CurrencyFormatter"; +import { pageLimit } from "../../utils/config"; +import useLocalStorage from "../../utils/useLocalStorage"; import StartChatButton from "../chat-open-button/chat-open-button.component"; import OwnerNameDisplay from "../owner-name-display/owner-name-display.component"; -import {pageLimit} from "../../utils/config"; const mapStateToProps = createStructuredSelector({ //currentUser: selectCurrentUser bodyshop: selectBodyshop, @@ -25,6 +26,8 @@ export function JobsList({ bodyshop, refetch, loading, jobs, total }) { const search = queryString.parse(useLocation().search); const [openSearchResults, setOpenSearchResults] = useState([]); const [searchLoading, setSearchLoading] = useState(false); + const [filter, setFilter] = useLocalStorage("filter_jobs_all", null); + console.log("filter", filter); const { page, sortcolumn, sortorder } = search; const history = useHistory(); @@ -93,6 +96,7 @@ export function JobsList({ bodyshop, refetch, loading, jobs, total }) { render: (text, record) => { return record.status || t("general.labels.na"); }, + filteredValue: filter?.status || null, filters: bodyshop.md_ro_statuses.statuses.map((s) => { return { text: s, value: [s] }; }), @@ -189,6 +193,7 @@ export function JobsList({ bodyshop, refetch, loading, jobs, total }) { } else { delete search.statusFilters; } + setFilter(filters); history.push({ search: queryString.stringify(search) }); }; diff --git a/client/src/components/jobs-list/jobs-list.component.jsx b/client/src/components/jobs-list/jobs-list.component.jsx index fb2e1daa6..7761c0ed9 100644 --- a/client/src/components/jobs-list/jobs-list.component.jsx +++ b/client/src/components/jobs-list/jobs-list.component.jsx @@ -1,8 +1,8 @@ import { - SyncOutlined, + BranchesOutlined, ExclamationCircleFilled, PauseCircleOutlined, - BranchesOutlined, + SyncOutlined, } from "@ant-design/icons"; import { useQuery } from "@apollo/client"; import { Button, Card, Grid, Input, Space, Table, Tooltip } from "antd"; @@ -14,382 +14,389 @@ import { Link, useHistory, useLocation } from "react-router-dom"; import { createStructuredSelector } from "reselect"; import { QUERY_ALL_ACTIVE_JOBS } from "../../graphql/jobs.queries"; import { selectBodyshop } from "../../redux/user/user.selectors"; -import { onlyUnique } from "../../utils/arrayHelper"; import CurrencyFormatter from "../../utils/CurrencyFormatter"; -import { alphaSort } from "../../utils/sorters"; +import { onlyUnique } from "../../utils/arrayHelper"; +import { alphaSort, statusSort } from "../../utils/sorters"; +import useLocalStorage from "../../utils/useLocalStorage"; import AlertComponent from "../alert/alert.component"; import ChatOpenButton from "../chat-open-button/chat-open-button.component"; import OwnerNameDisplay from "../owner-name-display/owner-name-display.component"; const mapStateToProps = createStructuredSelector({ - bodyshop: selectBodyshop, + bodyshop: selectBodyshop, }); export function JobsList({ bodyshop }) { - const searchParams = queryString.parse(useLocation().search); - const { selected } = searchParams; - const selectedBreakpoint = Object.entries(Grid.useBreakpoint()) - .filter((screen) => !!screen[1]) - .slice(-1)[0]; - const { loading, error, data, refetch } = useQuery(QUERY_ALL_ACTIVE_JOBS, { - variables: { - statuses: bodyshop.md_ro_statuses.active_statuses || ["Open", "Open*"], - }, - fetchPolicy: "network-only", - nextFetchPolicy: "network-only", - }); + const searchParams = queryString.parse(useLocation().search); + const { selected } = searchParams; + const selectedBreakpoint = Object.entries(Grid.useBreakpoint()) + .filter((screen) => !!screen[1]) + .slice(-1)[0]; + const { loading, error, data, refetch } = useQuery(QUERY_ALL_ACTIVE_JOBS, { + variables: { + statuses: bodyshop.md_ro_statuses.active_statuses || ["Open", "Open*"], + }, + fetchPolicy: "network-only", + nextFetchPolicy: "network-only", + }); - const [state, setState] = useState({ - sortedInfo: {}, - filteredInfo: { text: "" }, - }); + const [state, setState] = useState({ sortedInfo: {} }); + const [filter, setFilter] = useLocalStorage("filter_jobs_list", null); - const { t } = useTranslation(); - const history = useHistory(); - const [searchText, setSearchText] = useState(""); + const { t } = useTranslation(); + const history = useHistory(); + const [searchText, setSearchText] = useState(""); - if (error) return ; + if (error) return ; - const jobs = data - ? searchText === "" - ? data.jobs - : data.jobs.filter( - (j) => - (j.ro_number || "") - .toString() - .toLowerCase() - .includes(searchText.toLowerCase()) || - (j.ownr_co_nm || "") - .toLowerCase() - .includes(searchText.toLowerCase()) || - (j.comments || "") - .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()) || - (j.plate_no || "") - .toLowerCase() - .includes(searchText.toLowerCase()) || - (j.v_model_desc || "") - .toLowerCase() - .includes(searchText.toLowerCase()) || - (j.est_ct_fn || "") - .toLowerCase() - .includes(searchText.toLowerCase()) || - (j.est_ct_ln || "") - .toLowerCase() - .includes(searchText.toLowerCase()) || - (j.v_make_desc || "") - .toLowerCase() - .includes(searchText.toLowerCase()) - ) - : []; + const jobs = data + ? searchText === "" + ? data.jobs + : data.jobs.filter( + (j) => + (j.ro_number || "") + .toString() + .toLowerCase() + .includes(searchText.toLowerCase()) || + (j.ownr_co_nm || "") + .toLowerCase() + .includes(searchText.toLowerCase()) || + (j.comments || "") + .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()) || + (j.plate_no || "") + .toLowerCase() + .includes(searchText.toLowerCase()) || + (j.v_model_desc || "") + .toLowerCase() + .includes(searchText.toLowerCase()) || + (j.est_ct_fn || "") + .toLowerCase() + .includes(searchText.toLowerCase()) || + (j.est_ct_ln || "") + .toLowerCase() + .includes(searchText.toLowerCase()) || + (j.v_make_desc || "") + .toLowerCase() + .includes(searchText.toLowerCase()) + ) + : []; - const handleTableChange = (pagination, filters, sorter) => { - setState({ ...state, filteredInfo: filters, sortedInfo: sorter }); - }; + const handleTableChange = (pagination, filters, sorter) => { + setState({ ...state, sortedInfo: sorter }); + setFilter(filters); + }; - const handleOnRowClick = (record) => { - if (record) { - if (record.id) { - history.push({ - search: queryString.stringify({ - ...searchParams, - selected: record.id, - }), - }); - } - } - }; + const handleOnRowClick = (record) => { + if (record) { + if (record.id) { + history.push({ + search: queryString.stringify({ + ...searchParams, + selected: record.id, + }), + }); + } + } + }; - const columns = [ - { - title: t("jobs.fields.ro_number"), - dataIndex: "ro_number", - key: "ro_number", - sorter: (a, b) => - parseInt((a.ro_number || "0").replace(/\D/g, "")) - - parseInt((b.ro_number || "0").replace(/\D/g, "")), - sortOrder: - state.sortedInfo.columnKey === "ro_number" && state.sortedInfo.order, - - render: (text, record) => ( - e.stopPropagation()} - > - - {record.ro_number || t("general.labels.na")} - {record.production_vars && record.production_vars.alert ? ( - - ) : null} - {record.suspended && ( - - )} - {record.iouparent && ( - - - - )} - - - ), - }, - { - title: t("jobs.fields.owner"), - dataIndex: "owner", - key: "owner", - ellipsis: true, - - responsive: ["md"], - sorter: (a, b) => alphaSort(a.ownr_ln, b.ownr_ln), - sortOrder: - state.sortedInfo.columnKey === "owner" && state.sortedInfo.order, - render: (text, record) => { - return record.ownerid ? ( - e.stopPropagation()} - > - - - ) : ( - + const columns = [ + { + title: t("jobs.fields.ro_number"), + dataIndex: "ro_number", + key: "ro_number", + sorter: (a, b) => + parseInt((a.ro_number || "0").replace(/\D/g, "")) - + parseInt((b.ro_number || "0").replace(/\D/g, "")), + sortOrder: + state.sortedInfo.columnKey === "ro_number" && state.sortedInfo.order, + render: (text, record) => ( + e.stopPropagation()} + > + + {record.ro_number || t("general.labels.na")} + {record.production_vars && record.production_vars.alert ? ( + + ) : null} + {record.suspended && ( + + )} + {record.iouparent && ( + + + + )} + + + ), + }, + { + title: t("jobs.fields.owner"), + dataIndex: "owner", + key: "owner", + ellipsis: true, + responsive: ["md"], + sorter: (a, b) => alphaSort(a.ownr_ln, b.ownr_ln), + sortOrder: + state.sortedInfo.columnKey === "owner" && state.sortedInfo.order, + render: (text, record) => { + return record.ownerid ? ( + e.stopPropagation()} + > + + + ) : ( + - ); + ); + }, + }, + { + title: t("jobs.fields.ownr_ph1"), + dataIndex: "ownr_ph1", + key: "ownr_ph1", + ellipsis: true, + responsive: ["md"], + render: (text, record) => ( + + ), + }, + { + title: t("jobs.fields.ownr_ph2"), + dataIndex: "ownr_ph2", + key: "ownr_ph2", + ellipsis: true, + responsive: ["md"], + render: (text, record) => ( + + ), + }, + { + title: t("jobs.fields.status"), + dataIndex: "status", + key: "status", + ellipsis: true, + sorter: (a, b) => alphaSort(a.status, b.status), + sortOrder: + state.sortedInfo.columnKey === "status" && state.sortedInfo.order, + filteredValue: filter?.status || null, + filters: + (jobs && + jobs + .map((j) => j.status) + .filter(onlyUnique) + .map((s) => { + return { + text: s || "No Status*", + value: [s], + }; + }) + .sort((a, b) => + statusSort( + a.text, + b.text, + bodyshop.md_ro_statuses.active_statuses + ) + )) || + [], + onFilter: (value, record) => value.includes(record.status), + }, + + { + title: t("jobs.fields.vehicle"), + dataIndex: "vehicle", + key: "vehicle", + ellipsis: true, + render: (text, record) => { + return record.vehicleid ? ( + e.stopPropagation()} + > + {`${record.v_model_yr || ""} ${record.v_make_desc || ""} ${ + record.v_model_desc || "" + }`} + + ) : ( + {`${record.v_model_yr || ""} ${record.v_make_desc || ""} ${ + record.v_model_desc || "" + }`} + ); + }, + }, + { + title: t("vehicles.fields.plate_no"), + dataIndex: "plate_no", + key: "plate_no", + ellipsis: true, + + responsive: ["md"], + sorter: (a, b) => alphaSort(a.plate_no, b.plate_no), + sortOrder: + state.sortedInfo.columnKey === "plate_no" && state.sortedInfo.order, + }, + { + title: t("jobs.fields.clm_no"), + dataIndex: "clm_no", + key: "clm_no", + ellipsis: true, + responsive: ["md"], + sorter: (a, b) => alphaSort(a.clm_no, b.clm_no), + sortOrder: + state.sortedInfo.columnKey === "clm_no" && state.sortedInfo.order, + render: (text, record) => + `${record.clm_no || ""}${ + record.po_number ? ` (PO: ${record.po_number})` : "" + }`, + }, + { + title: t("jobs.fields.ins_co_nm"), + dataIndex: "ins_co_nm", + key: "ins_co_nm", + ellipsis: true, + filteredValue: filter?.ins_co_nm || null, + filters: + (jobs && + jobs + .map((j) => j.ins_co_nm) + .filter(onlyUnique) + .map((s) => { + return { + text: s || "No Ins. Co.*", + value: [s], + }; + }) + .sort((a, b) => alphaSort(a.text, b.text))) || + [], + onFilter: (value, record) => value.includes(record.ins_co_nm), + responsive: ["md"], + }, + { + title: t("jobs.fields.clm_total"), + dataIndex: "clm_total", + key: "clm_total", + responsive: ["md"], + ellipsis: true, + sorter: (a, b) => a.clm_total - b.clm_total, + sortOrder: + state.sortedInfo.columnKey === "clm_total" && state.sortedInfo.order, + render: (text, record) => ( + {record.clm_total} + ), + }, + { + title: t("jobs.labels.estimator"), + dataIndex: "jobs.labels.estimator", + key: "estimator", + ellipsis: true, + responsive: ["xl"], + filterSearch: true, + filteredValue: filter?.estimator || null, + filters: + (jobs && + jobs + .map((j) => `${j.est_ct_fn || ""} ${j.est_ct_ln || ""}`.trim()) + .filter(onlyUnique) + .map((s) => { + return { + text: s || "No Estimator*", + value: [s], + }; + }) + .sort((a, b) => alphaSort(a.text, b.text))) || + [], + onFilter: (value, record) => + value.includes( + `${record.est_ct_fn || ""} ${record.est_ct_ln || ""}`.trim() + ), + render: (text, record) => + `${record.est_ct_fn || ""} ${record.est_ct_ln || ""}`.trim(), + }, + { + title: t("jobs.fields.comment"), + dataIndex: "comment", + key: "comment", + ellipsis: true, + responsive: ["md"], + }, + // { + // title: t("jobs.fields.owner_owing"), + // dataIndex: "owner_owing", + // key: "owner_owing", + // responsive: ["md"], + // render: (text, record) => ( + // {record.owner_owing} + // ), + // }, + ]; + + const scrollMapper = { + xs: true, + sm: true, + md: true, + lg: "100%", + xl: "100%", + xxl: "100%", + }; + + return ( + + + { + setSearchText(e.target.value); + }} + value={searchText} + enterButton + /> + + } + > + { + handleOnRowClick(record); + }, + selectedRowKeys: [selected], + type: "radio", + }} + onChange={handleTableChange} + onRow={(record, rowIndex) => { + return { + onClick: (event) => { + handleOnRowClick(record); }, - }, - { - title: t("jobs.fields.ownr_ph1"), - dataIndex: "ownr_ph1", - key: "ownr_ph1", - ellipsis: true, - responsive: ["md"], - render: (text, record) => ( - - ), - }, - { - title: t("jobs.fields.ownr_ph2"), - dataIndex: "ownr_ph2", - key: "ownr_ph2", - ellipsis: true, - responsive: ["md"], - render: (text, record) => ( - - ), - }, - - { - title: t("jobs.fields.status"), - dataIndex: "status", - key: "status", - ellipsis: true, - - sorter: (a, b) => alphaSort(a.status, b.status), - sortOrder: - state.sortedInfo.columnKey === "status" && state.sortedInfo.order, - filters: - (jobs && - jobs - .map((j) => j.status) - .filter(onlyUnique) - .map((s) => { - return { - text: s || "No Status*", - value: [s], - }; - })) || - [], - onFilter: (value, record) => value.includes(record.status), - }, - - { - title: t("jobs.fields.vehicle"), - dataIndex: "vehicle", - key: "vehicle", - ellipsis: true, - render: (text, record) => { - return record.vehicleid ? ( - e.stopPropagation()} - > - {`${record.v_model_yr || ""} ${record.v_make_desc || ""} ${ - record.v_model_desc || "" - }`} - - ) : ( - {`${record.v_model_yr || ""} ${record.v_make_desc || ""} ${ - record.v_model_desc || "" - }`} - ); - }, - }, - { - title: t("vehicles.fields.plate_no"), - dataIndex: "plate_no", - key: "plate_no", - ellipsis: true, - - responsive: ["md"], - sorter: (a, b) => alphaSort(a.plate_no, b.plate_no), - sortOrder: - state.sortedInfo.columnKey === "plate_no" && state.sortedInfo.order, - }, - { - title: t("jobs.fields.clm_no"), - dataIndex: "clm_no", - key: "clm_no", - ellipsis: true, - responsive: ["md"], - sorter: (a, b) => alphaSort(a.clm_no, b.clm_no), - sortOrder: - state.sortedInfo.columnKey === "clm_no" && state.sortedInfo.order, - render: (text, record) => - `${record.clm_no || ""}${ - record.po_number ? ` (PO: ${record.po_number})` : "" - }`, - }, - { - title: t("jobs.fields.ins_co_nm"), - dataIndex: "ins_co_nm", - key: "ins_co_nm", - ellipsis: true, - filters: - (jobs && - jobs - .map((j) => j.ins_co_nm) - .filter(onlyUnique) - .map((s) => { - return { - text: s, - value: [s], - }; - })) || - [], - onFilter: (value, record) => value.includes(record.ins_co_nm), - responsive: ["md"], - }, - { - title: t("jobs.fields.clm_total"), - dataIndex: "clm_total", - key: "clm_total", - responsive: ["md"], - ellipsis: true, - - sorter: (a, b) => a.clm_total - b.clm_total, - sortOrder: - state.sortedInfo.columnKey === "clm_total" && state.sortedInfo.order, - render: (text, record) => ( - {record.clm_total} - ), - }, - { - title: t("jobs.labels.estimator"), - dataIndex: "jobs.labels.estimator", - key: "jobs.labels.estimator", - ellipsis: true, - responsive: ["xl"], - filterSearch: true, - filters: - (jobs && - jobs - .map((j) => `${j.est_ct_fn || ""} ${j.est_ct_ln || ""}`.trim()) - .filter(onlyUnique) - .map((s) => { - return { - text: s || "N/A", - value: [s], - }; - })) || - [], - onFilter: (value, record) => - value.includes( - `${record.est_ct_fn || ""} ${record.est_ct_ln || ""}`.trim() - ), - render: (text, record) => - `${record.est_ct_fn || ""} ${record.est_ct_ln || ""}`.trim(), - }, - { - title: t("jobs.fields.comment"), - dataIndex: "comment", - key: "comment", - ellipsis: true, - responsive: ["md"], - }, - // { - // title: t("jobs.fields.owner_owing"), - // dataIndex: "owner_owing", - // key: "owner_owing", - // responsive: ["md"], - // render: (text, record) => ( - // {record.owner_owing} - // ), - // }, - ]; - - const scrollMapper = { - xs: true, - sm: true, - md: true, - lg: "100%", - xl: "100%", - xxl: "100%", - }; - - return ( - - - { - setSearchText(e.target.value); - }} - value={searchText} - enterButton - /> - - } - > -
{ - handleOnRowClick(record); - }, - selectedRowKeys: [selected], - type: "radio", - }} - onChange={handleTableChange} - onRow={(record, rowIndex) => { - return { - onClick: (event) => { - handleOnRowClick(record); - }, - }; - }} - /> - - ); + }; + }} + /> + + ); } export default connect(mapStateToProps, null)(JobsList); diff --git a/client/src/components/jobs-ready-list/jobs-ready-list.component.jsx b/client/src/components/jobs-ready-list/jobs-ready-list.component.jsx index fee461df2..147f6ea23 100644 --- a/client/src/components/jobs-ready-list/jobs-ready-list.component.jsx +++ b/client/src/components/jobs-ready-list/jobs-ready-list.component.jsx @@ -16,11 +16,12 @@ import { QUERY_ALL_ACTIVE_JOBS } from "../../graphql/jobs.queries"; import { selectBodyshop } from "../../redux/user/user.selectors"; import CurrencyFormatter from "../../utils/CurrencyFormatter"; import { onlyUnique } from "../../utils/arrayHelper"; -import { alphaSort } from "../../utils/sorters"; +import { pageLimit } from "../../utils/config"; +import { alphaSort, statusSort } from "../../utils/sorters"; +import useLocalStorage from "../../utils/useLocalStorage"; import AlertComponent from "../alert/alert.component"; import ChatOpenButton from "../chat-open-button/chat-open-button.component"; import OwnerNameDisplay from "../owner-name-display/owner-name-display.component"; -import {pageLimit} from "../../utils/config"; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop, @@ -53,10 +54,8 @@ export function JobsReadyList({ bodyshop }) { nextFetchPolicy: "network-only", }); - const [state, setState] = useState({ - sortedInfo: {}, - filteredInfo: { text: "" }, - }); + const [state, setState] = useState({ sortedInfo: {} }); + const [filter, setFilter] = useLocalStorage("filter_jobs_ready", null); const { t } = useTranslation(); const history = useHistory(); @@ -105,7 +104,8 @@ export function JobsReadyList({ bodyshop }) { : []; const handleTableChange = (pagination, filters, sorter) => { - setState({ ...state, filteredInfo: filters, sortedInfo: sorter }); + setState({ ...state, sortedInfo: sorter }); + setFilter(filters); }; const handleOnRowClick = (record) => { @@ -129,7 +129,6 @@ export function JobsReadyList({ bodyshop }) { sorter: (a, b) => alphaSort(a.ro_number, b.ro_number), sortOrder: state.sortedInfo.columnKey === "ro_number" && state.sortedInfo.order, - render: (text, record) => ( alphaSort(a.ownr_ln, b.ownr_ln), sortOrder: @@ -197,16 +195,15 @@ export function JobsReadyList({ bodyshop }) { ), }, - { title: t("jobs.fields.status"), dataIndex: "status", key: "status", ellipsis: true, - sorter: (a, b) => alphaSort(a.status, b.status), sortOrder: state.sortedInfo.columnKey === "status" && state.sortedInfo.order, + filteredValue: filter?.status || null, filters: (jobs && jobs @@ -217,11 +214,17 @@ export function JobsReadyList({ bodyshop }) { text: s || "No Status*", value: [s], }; - })) || + }) + .sort((a, b) => + statusSort( + a.text, + b.text, + bodyshop.md_ro_statuses.active_statuses + ) + )) || [], onFilter: (value, record) => value.includes(record.status), }, - { title: t("jobs.fields.vehicle"), dataIndex: "vehicle", @@ -274,6 +277,7 @@ export function JobsReadyList({ bodyshop }) { dataIndex: "ins_co_nm", key: "ins_co_nm", ellipsis: true, + filteredValue: filter?.ins_co_nm || null, filters: (jobs && jobs @@ -281,10 +285,11 @@ export function JobsReadyList({ bodyshop }) { .filter(onlyUnique) .map((s) => { return { - text: s, + text: s || "No Ins Co.*", value: [s], }; - })) || + }) + .sort((a, b) => alphaSort(a.text, b.text))) || [], onFilter: (value, record) => value.includes(record.ins_co_nm), responsive: ["md"], @@ -295,7 +300,6 @@ export function JobsReadyList({ bodyshop }) { key: "clm_total", responsive: ["md"], ellipsis: true, - sorter: (a, b) => a.clm_total - b.clm_total, sortOrder: state.sortedInfo.columnKey === "clm_total" && state.sortedInfo.order, @@ -306,9 +310,10 @@ export function JobsReadyList({ bodyshop }) { { title: t("jobs.labels.estimator"), dataIndex: "jobs.labels.estimator", - key: "jobs.labels.estimator", + key: "estimator", ellipsis: true, responsive: ["xl"], + filteredValue: filter?.estimator || null, filterSearch: true, filters: (jobs && @@ -317,10 +322,11 @@ export function JobsReadyList({ bodyshop }) { .filter(onlyUnique) .map((s) => { return { - text: s || "N/A", + text: s || "No Estimator*", value: [s], }; - })) || + }) + .sort((a, b) => alphaSort(a.text, b.text))) || [], onFilter: (value, record) => value.includes( From 0cc367b25e9c78550ba65e7a19595b9f43a915db Mon Sep 17 00:00:00 2001 From: Allan Carr Date: Tue, 16 Jan 2024 12:12:53 -0800 Subject: [PATCH 07/10] IO-2531 Remove Console Log --- .../jobs-list-paginated/jobs-list-paginated.component.jsx | 1 - 1 file changed, 1 deletion(-) diff --git a/client/src/components/jobs-list-paginated/jobs-list-paginated.component.jsx b/client/src/components/jobs-list-paginated/jobs-list-paginated.component.jsx index 1b4c6f435..e247f5450 100644 --- a/client/src/components/jobs-list-paginated/jobs-list-paginated.component.jsx +++ b/client/src/components/jobs-list-paginated/jobs-list-paginated.component.jsx @@ -27,7 +27,6 @@ export function JobsList({ bodyshop, refetch, loading, jobs, total }) { const [openSearchResults, setOpenSearchResults] = useState([]); const [searchLoading, setSearchLoading] = useState(false); const [filter, setFilter] = useLocalStorage("filter_jobs_all", null); - console.log("filter", filter); const { page, sortcolumn, sortorder } = search; const history = useHistory(); From 78a136e277d7653ee1f6cded8261bbdc90c58339 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Tue, 16 Jan 2024 15:17:00 -0500 Subject: [PATCH 08/10] - Fix the page layout, the footer was in the content section causing it not to remain at the bottom and just reside 'at the bottom' of the content section. Also added a 100% on the outer container height (100vh) so the grey background fills the page Signed-off-by: Dave Richer --- .../pages/manage/manage.page.component.jsx | 52 +++++++++---------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/client/src/pages/manage/manage.page.component.jsx b/client/src/pages/manage/manage.page.component.jsx index 58658b39b..a654ee98a 100644 --- a/client/src/pages/manage/manage.page.component.jsx +++ b/client/src/pages/manage/manage.page.component.jsx @@ -362,11 +362,10 @@ export function Manage({conflict, bodyshop}) { return ( <> - - + + - } showDialog> @@ -374,30 +373,31 @@ export function Manage({conflict, bodyshop}) { -
-
-
-
- {`ImEX Online ${ - process.env.REACT_APP_GIT_SHA - } - ${preval`module.exports = new Date().toLocaleString("en-US", {timeZone: "America/Los_Angeles"});`}`} -
-
-
- - Disclaimer & Notices - -
-
+
+
+
+
+
+ {`ImEX Online ${ + process.env.REACT_APP_GIT_SHA + } - ${preval`module.exports = new Date().toLocaleString("en-US", {timeZone: "America/Los_Angeles"});`}`} +
+
+
+ + Disclaimer & Notices + +
+
); From 69791a3cdd8abc0b112d84bceca58b260f4b7050 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Wed, 17 Jan 2024 00:19:51 -0500 Subject: [PATCH 09/10] - Fix spacing on so me alerts Signed-off-by: Dave Richer --- .../src/components/alert/alert.component.jsx | 2 +- .../schedule-calendar-header.component.js | 1 - .../scheduler-calendar-wrapper.component.jsx | 88 ++++++++++--------- 3 files changed, 49 insertions(+), 42 deletions(-) diff --git a/client/src/components/alert/alert.component.jsx b/client/src/components/alert/alert.component.jsx index f02edd614..9d054c45f 100644 --- a/client/src/components/alert/alert.component.jsx +++ b/client/src/components/alert/alert.component.jsx @@ -2,5 +2,5 @@ import { Alert } from "antd"; import React from "react"; export default function AlertComponent(props) { - return ; + return ; } diff --git a/client/src/components/schedule-calendar-wrapper/schedule-calendar-header.component.js b/client/src/components/schedule-calendar-wrapper/schedule-calendar-header.component.js index 0b85d7212..cfd09aec3 100644 --- a/client/src/components/schedule-calendar-wrapper/schedule-calendar-header.component.js +++ b/client/src/components/schedule-calendar-wrapper/schedule-calendar-header.component.js @@ -37,7 +37,6 @@ export function ScheduleCalendarHeaderComponent({ events, ...otherProps }) { - console.log(`ScheduleCalendarHeaderComponent: ${label} Calculating: ${calculating}`) const ATSToday = useMemo(() => { if (!events) return []; return _.groupBy( diff --git a/client/src/components/schedule-calendar-wrapper/scheduler-calendar-wrapper.component.jsx b/client/src/components/schedule-calendar-wrapper/scheduler-calendar-wrapper.component.jsx index 298b2eae8..7f5781de8 100644 --- a/client/src/components/schedule-calendar-wrapper/scheduler-calendar-wrapper.component.jsx +++ b/client/src/components/schedule-calendar-wrapper/scheduler-calendar-wrapper.component.jsx @@ -11,7 +11,7 @@ import HeaderComponent from "./schedule-calendar-header.component"; import "./schedule-calendar.styles.scss"; import JobDetailCards from "../job-detail-cards/job-detail-cards.component"; import { selectProblemJobs } from "../../redux/application/application.selectors"; -import { Alert, Collapse } from "antd"; +import {Alert, Collapse, Space} from "antd"; import { useTranslation, Trans } from "react-i18next"; import { Link } from "react-router-dom"; @@ -55,57 +55,65 @@ export function ScheduleCalendarWrapperComponent({ <> {problemJobs && problemJobs.length > 2 ? ( - + {t("appointments.labels.severalerrorsfound")} } > - {problemJobs.map((problem) => ( - , - ]} - values={{ - ro_number: problem.ro_number, - code: problem.code, - }} + + {problemJobs.map((problem) => ( + , + ]} + values={{ + ro_number: problem.ro_number, + code: problem.code, + }} + /> + } /> - } - /> - ))} + ))} + + ) : ( - problemJobs.map((problem) => ( - , - ]} - values={{ - ro_number: problem.ro_number, - code: problem.code, - }} - /> + + { + problemJobs.map((problem) => ( + , + ]} + values={{ + ro_number: problem.ro_number, + code: problem.code, + }} + /> + } + /> + )) } - /> - )) - )} + + )} Date: Wed, 17 Jan 2024 19:54:03 -0500 Subject: [PATCH 10/10] - progress Signed-off-by: Dave Richer --- client/src/index.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/client/src/index.js b/client/src/index.js index 9bf4faddb..9bcdc55ec 100644 --- a/client/src/index.js +++ b/client/src/index.js @@ -12,7 +12,6 @@ import { persistor, store } from "./redux/store"; import reportWebVitals from "./reportWebVitals"; import "./translations/i18n"; import "./utils/CleanAxios"; -import {ConfigProvider} from "antd"; import {defaultTheme} from "@ant-design/compatible"; //import { BrowserTracing } from "@sentry/tracing"; //import "antd/dist/antd.css"; @@ -67,7 +66,7 @@ function App() { // https://ant.design/docs/react/migrate-less-variables // TODO - Client Update - At a later time it might be worth removing these defaults ReactDOM.createRoot(document.getElementById('root')).render( - + );