From 852fd9c3885729c9d7d0f106c79ba0327188c1ba Mon Sep 17 00:00:00 2001 From: Patrick Fic Date: Mon, 1 May 2023 13:04:10 -0700 Subject: [PATCH 01/21] IO-2261 Sample open search replacement. --- .../jobs-list-paginated.component.jsx | 47 +++++++++++++++---- client/src/graphql/jobs.queries.js | 9 +--- .../src/pages/jobs-all/jobs-all.container.jsx | 5 +- server/opensearch/os-handler.js | 6 ++- 4 files changed, 47 insertions(+), 20 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 5ef3ab976..faa8470cc 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 @@ -2,7 +2,7 @@ import { SyncOutlined } from "@ant-design/icons"; import { Button, Card, Input, Space, Table, Typography } from "antd"; import _ from "lodash"; import queryString from "query-string"; -import React from "react"; +import React, { useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; import { Link, useHistory, useLocation } from "react-router-dom"; @@ -11,6 +11,7 @@ import { selectBodyshop } from "../../redux/user/user.selectors"; import CurrencyFormatter from "../../utils/CurrencyFormatter"; import StartChatButton from "../chat-open-button/chat-open-button.component"; import OwnerNameDisplay from "../owner-name-display/owner-name-display.component"; +import axios from "axios"; const mapStateToProps = createStructuredSelector({ //currentUser: selectCurrentUser bodyshop: selectBodyshop, @@ -21,6 +22,7 @@ const mapDispatchToProps = (dispatch) => ({ export function JobsList({ bodyshop, refetch, loading, jobs, total }) { const search = queryString.parse(useLocation().search); + const [openSearchResults, setOpenSearchResults] = useState([]); const { page, sortcolumn, sortorder } = search; const history = useHistory(); @@ -193,6 +195,28 @@ export function JobsList({ bodyshop, refetch, loading, jobs, total }) { history.push({ search: queryString.stringify(search) }); }; + useEffect(() => { + if (search.search && search.search.trim() !== "") { + // setLoading(true); + searchJobs(); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + async function searchJobs(value) { + try { + const searchData = await axios.post("/search", { + search: value || search.search, + index: "jobs", + }); + + setOpenSearchResults(searchData.data.hits.hits.map((s) => s._source)); + } catch (error) { + } finally { + //setLoading(false) + } + } + return ( { search.search = value; history.push({ search: queryString.stringify(search) }); + searchJobs(value); }} enterButton /> @@ -228,16 +253,20 @@ export function JobsList({ bodyshop, refetch, loading, jobs, total }) { > diff --git a/client/src/graphql/jobs.queries.js b/client/src/graphql/jobs.queries.js index 50225795f..103e21b16 100644 --- a/client/src/graphql/jobs.queries.js +++ b/client/src/graphql/jobs.queries.js @@ -1781,14 +1781,12 @@ export const QUERY_ALL_JOB_FIELDS = gql` export const QUERY_ALL_JOBS_PAGINATED_STATUS_FILTERED = gql` query QUERY_ALL_JOBS_PAGINATED_STATUS_FILTERED( - $search: String $offset: Int $limit: Int $order: [jobs_order_by!] $statusList: [String!] ) { - search_jobs( - args: { search: $search } + jobs( offset: $offset limit: $limit order_by: $order @@ -1819,10 +1817,7 @@ export const QUERY_ALL_JOBS_PAGINATED_STATUS_FILTERED = gql` updated_at ded_amt } - search_jobs_aggregate( - args: { search: $search } - where: { status: { _in: $statusList } } - ) { + jobs_aggregate(where: { status: { _in: $statusList } }) { aggregate { count(distinct: true) } diff --git a/client/src/pages/jobs-all/jobs-all.container.jsx b/client/src/pages/jobs-all/jobs-all.container.jsx index a36745a0e..faa161571 100644 --- a/client/src/pages/jobs-all/jobs-all.container.jsx +++ b/client/src/pages/jobs-all/jobs-all.container.jsx @@ -33,7 +33,6 @@ export function AllJobs({ setBreadcrumbs, setSelectedHeader }) { fetchPolicy: "network-only", nextFetchPolicy: "network-only", variables: { - search: search || "", offset: page ? (page - 1) * 25 : 0, limit: 25, ...(statusFilters ? { statusList: JSON.parse(statusFilters) } : {}), @@ -67,8 +66,8 @@ export function AllJobs({ setBreadcrumbs, setSelectedHeader }) { refetch={refetch} loading={loading} searchParams={searchParams} - total={data ? data.search_jobs_aggregate.aggregate.count : 0} - jobs={data ? data.search_jobs : []} + total={data ? data.jobs_aggregate.aggregate.count : 0} + jobs={data ? data.jobs : []} /> ); diff --git a/server/opensearch/os-handler.js b/server/opensearch/os-handler.js index 6bb2adcdc..e1db64fa9 100644 --- a/server/opensearch/os-handler.js +++ b/server/opensearch/os-handler.js @@ -75,6 +75,9 @@ async function OpenSearchUpdateHandler(req, res) { "v_model_yr", "v_make_desc", "v_model_desc", + "clm_total", + "plate_no", + "ownr_ph1", ]); document.bodyshopid = req.body.event.data.new.shopid; break; @@ -176,7 +179,7 @@ async function OpenSearchUpdateHandler(req, res) { async function OpensearchSearchHandler(req, res) { try { - const { search, bodyshopid } = req.body; + const { search, bodyshopid, index } = req.body; if (!req.user) { res.sendStatus(401); return; @@ -205,6 +208,7 @@ async function OpensearchSearchHandler(req, res) { var osClient = await getClient(); const { body } = await osClient.search({ + ...(index ? { index } : {}), body: { size: 100, query: { From 759a8ac58c83d2c3598cce8f9e8915a28fb1e610 Mon Sep 17 00:00:00 2001 From: Allan Carr Date: Wed, 3 May 2023 16:29:01 -0700 Subject: [PATCH 02/21] IO-2261 Opensearch for Payments, Bills and All Jobs --- .../jobs-list-paginated.component.jsx | 6 +- .../payment-list-paginated.component.jsx | 72 ++++++++++++++----- client/src/graphql/bills.queries.js | 6 +- client/src/graphql/payments.queries.js | 15 ++-- .../src/pages/bills/bills.page.component.jsx | 69 +++++++++++++----- .../src/pages/bills/bills.page.container.jsx | 9 ++- .../src/pages/jobs-all/jobs-all.container.jsx | 2 +- .../payments-all.container.page.jsx | 11 +-- os-loader.js | 50 +++++++++---- server/opensearch/os-handler.js | 44 +++++++++--- 10 files changed, 198 insertions(+), 86 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 faa8470cc..7ce46616b 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 @@ -1,5 +1,6 @@ import { SyncOutlined } from "@ant-design/icons"; import { Button, Card, Input, Space, Table, Typography } from "antd"; +import axios from "axios"; import _ from "lodash"; import queryString from "query-string"; import React, { useEffect, useState } from "react"; @@ -11,7 +12,6 @@ import { selectBodyshop } from "../../redux/user/user.selectors"; import CurrencyFormatter from "../../utils/CurrencyFormatter"; import StartChatButton from "../chat-open-button/chat-open-button.component"; import OwnerNameDisplay from "../owner-name-display/owner-name-display.component"; -import axios from "axios"; const mapStateToProps = createStructuredSelector({ //currentUser: selectCurrentUser bodyshop: selectBodyshop, @@ -209,11 +209,11 @@ export function JobsList({ bodyshop, refetch, loading, jobs, total }) { search: value || search.search, index: "jobs", }); - setOpenSearchResults(searchData.data.hits.hits.map((s) => s._source)); } catch (error) { + console.log("Error while fetching search results", error); } finally { - //setLoading(false) + // setLoading(false); } } diff --git a/client/src/components/payments-list-paginated/payment-list-paginated.component.jsx b/client/src/components/payments-list-paginated/payment-list-paginated.component.jsx index 50b3d2b98..a502a52b9 100644 --- a/client/src/components/payments-list-paginated/payment-list-paginated.component.jsx +++ b/client/src/components/payments-list-paginated/payment-list-paginated.component.jsx @@ -1,7 +1,8 @@ import { EditFilled, SyncOutlined } from "@ant-design/icons"; import { Button, Card, Input, Space, Table, Typography } from "antd"; +import axios from "axios"; import queryString from "query-string"; -import React, { useState } from "react"; +import React, { useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; import { Link, useHistory, useLocation } from "react-router-dom"; @@ -10,11 +11,11 @@ import { setModalContext } from "../../redux/modals/modals.actions"; import { selectBodyshop } from "../../redux/user/user.selectors"; import CurrencyFormatter from "../../utils/CurrencyFormatter"; import { DateFormatter, DateTimeFormatter } from "../../utils/DateFormatter"; -import { alphaSort } from "../../utils/sorters"; import { TemplateList } from "../../utils/TemplateConstants"; +import { alphaSort } from "../../utils/sorters"; import CaBcEtfTableModalContainer from "../ca-bc-etf-table-modal/ca-bc-etf-table-modal.container"; -import PrintWrapperComponent from "../print-wrapper/print-wrapper.component"; import OwnerNameDisplay from "../owner-name-display/owner-name-display.component"; +import PrintWrapperComponent from "../print-wrapper/print-wrapper.component"; const mapStateToProps = createStructuredSelector({ //currentUser: selectCurrentUser @@ -39,6 +40,7 @@ export function PaymentsListPaginated({ bodyshop, }) { const search = queryString.parse(useLocation().search); + const [openSearchResults, setOpenSearchResults] = useState([]); const { page, sortcolumn, sortorder } = search; const history = useHistory(); const [state, setState] = useState({ @@ -54,11 +56,15 @@ export function PaymentsListPaginated({ key: "ro_number", sorter: (a, b) => alphaSort(a.job.ro_number, b.job.ro_number), sortOrder: sortcolumn === "ro_number" && sortorder, - render: (text, record) => ( - - {record.job.ro_number || t("general.labels.na")} - - ), + render: (text, record) => { + return record.job ? ( + + {record.job.ro_number || t("general.labels.na")} + + ) : ( + {t("general.labels.na")} + ); + }, }, { title: t("payments.fields.paymentnum"), @@ -75,13 +81,13 @@ export function PaymentsListPaginated({ sorter: (a, b) => alphaSort(a.job.ownr_ln, b.job.ownr_ln), sortOrder: sortcolumn === "owner" && sortorder, render: (text, record) => { - return record.job.owner ? ( - - + return record.job?.owner ? ( + + ) : ( - + ); }, @@ -177,6 +183,28 @@ export function PaymentsListPaginated({ history.push({ search: queryString.stringify(search) }); }; + useEffect(() => { + if (search.search && search.search.trim() !== "") { + // setLoading(true); + searchPayments(); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + async function searchPayments(value) { + try { + const searchData = await axios.post("/search", { + search: value || search.search, + index: "payments", + }); + setOpenSearchResults(searchData.data.hits.hits.map((s) => s._source)); + } catch (error) { + console.log("Error while fetching search results", error); + } finally { + // setLoading(false); + } + } + return ( { search.search = value; history.push({ search: queryString.stringify(search) }); + searchPayments(value); }} enterButton /> @@ -221,15 +250,20 @@ export function PaymentsListPaginated({
diff --git a/client/src/graphql/bills.queries.js b/client/src/graphql/bills.queries.js index 4d39eda47..6406edfe1 100644 --- a/client/src/graphql/bills.queries.js +++ b/client/src/graphql/bills.queries.js @@ -20,13 +20,11 @@ export const DELETE_BILL = gql` export const QUERY_ALL_BILLS_PAGINATED = gql` query QUERY_ALL_BILLS_PAGINATED( - $search: String $offset: Int $limit: Int $order: [bills_order_by!]! ) { - search_bills( - args: { search: $search } + bills( offset: $offset limit: $limit order_by: $order @@ -51,7 +49,7 @@ export const QUERY_ALL_BILLS_PAGINATED = gql` ro_number } } - search_bills_aggregate(args: { search: $search }) { + bills_aggregate { aggregate { count(distinct: true) } diff --git a/client/src/graphql/payments.queries.js b/client/src/graphql/payments.queries.js index 554e6c497..5141e9acf 100644 --- a/client/src/graphql/payments.queries.js +++ b/client/src/graphql/payments.queries.js @@ -12,13 +12,11 @@ export const INSERT_NEW_PAYMENT = gql` export const QUERY_ALL_PAYMENTS_PAGINATED = gql` query QUERY_ALL_PAYMENTS_PAGINATED( - $search: String $offset: Int $limit: Int $order: [payments_order_by!]! ) { - search_payments( - args: { search: $search } + payments( offset: $offset limit: $limit order_by: $order @@ -31,9 +29,16 @@ export const QUERY_ALL_PAYMENTS_PAGINATED = gql` job { id ro_number + ownerid + ownr_co_nm ownr_fn ownr_ln - ownr_co_nm + owner { + id + ownr_co_nm + ownr_fn + ownr_ln + } } transactionid memo @@ -44,7 +49,7 @@ export const QUERY_ALL_PAYMENTS_PAGINATED = gql` stripeid payer } - search_payments_aggregate(args: { search: $search }) { + payments_aggregate { aggregate { count(distinct: true) } diff --git a/client/src/pages/bills/bills.page.component.jsx b/client/src/pages/bills/bills.page.component.jsx index d9dc322e1..8647a6ded 100644 --- a/client/src/pages/bills/bills.page.component.jsx +++ b/client/src/pages/bills/bills.page.component.jsx @@ -1,7 +1,8 @@ -import { SyncOutlined, EditFilled } from "@ant-design/icons"; +import { EditFilled, SyncOutlined } from "@ant-design/icons"; import { Button, Card, Checkbox, Input, Space, Table, Typography } from "antd"; +import axios from "axios"; import queryString from "query-string"; -import React, { useState } from "react"; +import React, { useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; import { Link, useHistory, useLocation } from "react-router-dom"; @@ -11,8 +12,8 @@ import PrintWrapperComponent from "../../components/print-wrapper/print-wrapper. import { setModalContext } from "../../redux/modals/modals.actions"; import CurrencyFormatter from "../../utils/CurrencyFormatter"; import { DateFormatter } from "../../utils/DateFormatter"; -import { alphaSort, dateSort } from "../../utils/sorters"; import { TemplateList } from "../../utils/TemplateConstants"; +import { alphaSort, dateSort } from "../../utils/sorters"; const mapDispatchToProps = (dispatch) => ({ setPartsOrderContext: (context) => @@ -29,15 +30,16 @@ export function BillsListPage({ setPartsOrderContext, setBillEnterContext, }) { - const { t } = useTranslation(); + const search = queryString.parse(useLocation().search); + const [openSearchResults, setOpenSearchResults] = useState([]); + const { page } = search; + const history = useHistory(); const [state, setState] = useState({ sortedInfo: {}, + filteredInfo: { text: "" }, }); - const history = useHistory(); - const search = queryString.parse(useLocation().search); - const { page } = search; const Templates = TemplateList("bill"); - + const { t } = useTranslation(); const columns = [ { title: t("bills.fields.vendorname"), @@ -199,11 +201,32 @@ export function BillsListPage({ search.sortcolumn = sorter.order ? sorter.columnKey : null; search.sortorder = sorter.order; } - search.sort = JSON.stringify({ [sorter.columnKey]: sorter.order }); history.push({ search: queryString.stringify(search) }); }; + useEffect(() => { + if (search.search && search.search.trim() !== "") { + // setLoading(true); + searchBills(); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + async function searchBills(value) { + try { + const searchData = await axios.post("/search", { + search: value || search.search, + index: "bills", + }); + setOpenSearchResults(searchData.data.hits.hits.map((s) => s._source)); + } catch (error) { + console.log("Error while fetching search results", error); + } finally { + // setLoading(false); + } + } + return ( { search.search = value; history.push({ search: queryString.stringify(search) }); + searchBills(value); }} + enterButton /> } @@ -252,18 +277,24 @@ export function BillsListPage({
diff --git a/client/src/pages/bills/bills.page.container.jsx b/client/src/pages/bills/bills.page.container.jsx index a0340187b..22a8b61b9 100644 --- a/client/src/pages/bills/bills.page.container.jsx +++ b/client/src/pages/bills/bills.page.container.jsx @@ -1,6 +1,6 @@ +import { useQuery } from "@apollo/client"; import queryString from "query-string"; import React, { useEffect } from "react"; -import { useQuery } from "@apollo/client"; import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; import { useLocation } from "react-router-dom"; @@ -22,7 +22,7 @@ const mapDispatchToProps = (dispatch) => ({ export function BillsPageContainer({ setBreadcrumbs, setSelectedHeader }) { const { t } = useTranslation(); const searchParams = queryString.parse(useLocation().search); - const { page, sortcolumn, sortorder, search, searchObj } = searchParams; + const { page, sortcolumn, sortorder, searchObj } = searchParams; useEffect(() => { document.title = t("titles.bills-list"); @@ -38,7 +38,6 @@ export function BillsPageContainer({ setBreadcrumbs, setSelectedHeader }) { fetchPolicy: "network-only", nextFetchPolicy: "network-only", variables: { - search: search || "", offset: page ? (page - 1) * 25 : 0, limit: 25, order: [ @@ -61,10 +60,10 @@ export function BillsPageContainer({ setBreadcrumbs, setSelectedHeader }) {
diff --git a/client/src/pages/jobs-all/jobs-all.container.jsx b/client/src/pages/jobs-all/jobs-all.container.jsx index faa161571..2518d6c16 100644 --- a/client/src/pages/jobs-all/jobs-all.container.jsx +++ b/client/src/pages/jobs-all/jobs-all.container.jsx @@ -25,7 +25,7 @@ const mapDispatchToProps = (dispatch) => ({ export function AllJobs({ setBreadcrumbs, setSelectedHeader }) { const searchParams = queryString.parse(useLocation().search); - const { page, sortcolumn, sortorder, search, statusFilters } = searchParams; + const { page, sortcolumn, sortorder, statusFilters } = searchParams; const { loading, error, data, refetch } = useQuery( QUERY_ALL_JOBS_PAGINATED_STATUS_FILTERED, diff --git a/client/src/pages/payments-all/payments-all.container.page.jsx b/client/src/pages/payments-all/payments-all.container.page.jsx index 53f3959b3..07547bc2e 100644 --- a/client/src/pages/payments-all/payments-all.container.page.jsx +++ b/client/src/pages/payments-all/payments-all.container.page.jsx @@ -26,7 +26,7 @@ const mapDispatchToProps = (dispatch) => ({ export function AllJobs({ bodyshop, setBreadcrumbs, setSelectedHeader }) { const searchParams = queryString.parse(useLocation().search); - const { page, sortcolumn, sortorder, search } = searchParams; + const { page, sortcolumn, sortorder, searchObj } = searchParams; const { loading, error, data, refetch } = useQuery( QUERY_ALL_PAYMENTS_PAGINATED, @@ -34,11 +34,12 @@ export function AllJobs({ bodyshop, setBreadcrumbs, setSelectedHeader }) { fetchPolicy: "network-only", nextFetchPolicy: "network-only", variables: { - search: search || "", offset: page ? (page - 1) * 25 : 0, limit: 25, order: [ - { + searchObj + ? JSON.parse(searchObj) + : { [sortcolumn || "date"]: sortorder ? sortorder === "descend" ? "desc" @@ -66,8 +67,8 @@ export function AllJobs({ bodyshop, setBreadcrumbs, setSelectedHeader }) { refetch={refetch} loading={loading} searchParams={searchParams} - total={data ? data.search_payments_aggregate.aggregate.count : 0} - payments={data ? data.search_payments : []} + total={data ? data.payments_aggregate.aggregate.count : 0} + payments={data ? data.payments : []} /> ); diff --git a/os-loader.js b/os-loader.js index f8b8de52a..335a04778 100644 --- a/os-loader.js +++ b/os-loader.js @@ -50,7 +50,7 @@ const getClient = async () => { async function OpenSearchUpdateHandler(req, res) { try { - var osClient = await getClient(); + var osClient = await getClient(); // const osClient = new Client({ // node: `https://imex:password@search-imexonline-search-ixp2stfvwp6qocjsowzjzyreoy.ca-central-1.es.amazonaws.com`, // }); @@ -74,12 +74,18 @@ async function OpenSearchUpdateHandler(req, res) { const jobsData = await gqlclient.request(`query{jobs{ id bodyshopid:shopid - ro_number clm_no + clm_total + comment + ins_co_nm + ownr_co_nm ownr_fn ownr_ln + ownr_ph1 + ownr_ph2 + plate_no + ro_number status - ownr_co_nm v_model_yr v_make_desc v_model_desc @@ -128,12 +134,12 @@ async function OpenSearchUpdateHandler(req, res) { vehicles { id bodyshopid: shopid -v_model_yr -v_model_desc -v_make_desc -v_color -v_vin -plate_no + plate_no + v_model_yr + v_model_desc + v_make_desc + v_color + v_vin } } `); @@ -155,11 +161,25 @@ plate_no payments { id amount - paymentnum + created_at + exportedat memo + payer + paymentnum transactionid + type job { id + ownerid + ownr_co_nm + ownr_fn + ownr_ln + owner { + id + ownr_co_nm + ownr_fn + ownr_ln + } ro_number bodyshopid: shopid } @@ -187,9 +207,11 @@ plate_no const billsData = await gqlclient.request(`{ bills { id - total - invoice_number date + exported + invoice_number + is_credit_memo + total vendor { name id @@ -200,9 +222,7 @@ plate_no bodyshopid: shopid } } - } - - `); + }`); for (let i = 0; i <= billsData.bills.length / batchSize; i++) { const slicedArray = billsData.bills.slice( i * batchSize, diff --git a/server/opensearch/os-handler.js b/server/opensearch/os-handler.js index e1db64fa9..9e45b8791 100644 --- a/server/opensearch/os-handler.js +++ b/server/opensearch/os-handler.js @@ -66,18 +66,21 @@ async function OpenSearchUpdateHandler(req, res) { document = _.pick(req.body.event.data.new, [ "id", "bodyshopid", - "ro_number", "clm_no", + "clm_total", + "comment", + "ins_co_nm", + "ownr_co_nm", "ownr_fn", "ownr_ln", + "ownr_ph1", + "ownr_ph2", + "plate_no", + "ro_number", "status", - "ownr_co_nm", "v_model_yr", "v_make_desc", "v_model_desc", - "clm_total", - "plate_no", - "ownr_ph1", ]); document.bodyshopid = req.body.event.data.new.shopid; break; @@ -127,8 +130,10 @@ async function OpenSearchUpdateHandler(req, res) { document = { ..._.pick(req.body.event.data.new, [ "id", - "invoice_number", "date", + "exported", + "invoice_number", + "is_credit_memo", ]), ...bill.bills_by_pk, bodyshopid: bill.bills_by_pk.job.shopid, @@ -145,15 +150,34 @@ async function OpenSearchUpdateHandler(req, res) { id ro_number shopid + ownerid + ownr_co_nm + ownr_fn + ownr_ln + owner { + id + ownr_co_nm + ownr_fn + ownr_ln + } } } - } - - `, + } + `, { paymentId: req.body.event.data.new.id } ); document = { - ..._.pick(req.body.event.data.new, ["id", "invoice_number"]), + ..._.pick(req.body.event.data.new, [ + "id", + "amount", + "created_at", + "exportedat", + "memo", + "payer", + "paymentnum", + "transactionid", + "type", + ]), ...payment.payments_by_pk, bodyshopid: bill.payments_by_pk.job.shopid, }; From 6e5fcbfdbdc75897cb2c246129f29cb4cfcc4992 Mon Sep 17 00:00:00 2001 From: Allan Carr Date: Wed, 3 May 2023 16:30:48 -0700 Subject: [PATCH 03/21] IO-2267 Remove Sort for Linked Table fields --- .../payment-list-paginated.component.jsx | 8 +-- .../src/pages/bills/bills.page.component.jsx | 56 +++++++++---------- 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/client/src/components/payments-list-paginated/payment-list-paginated.component.jsx b/client/src/components/payments-list-paginated/payment-list-paginated.component.jsx index a502a52b9..0a202545e 100644 --- a/client/src/components/payments-list-paginated/payment-list-paginated.component.jsx +++ b/client/src/components/payments-list-paginated/payment-list-paginated.component.jsx @@ -54,8 +54,8 @@ export function PaymentsListPaginated({ title: t("jobs.fields.ro_number"), dataIndex: "ro_number", key: "ro_number", - sorter: (a, b) => alphaSort(a.job.ro_number, b.job.ro_number), - sortOrder: sortcolumn === "ro_number" && sortorder, + // sorter: (a, b) => alphaSort(a.job.ro_number, b.job.ro_number), + // sortOrder: sortcolumn === "ro_number" && sortorder, render: (text, record) => { return record.job ? ( @@ -78,8 +78,8 @@ export function PaymentsListPaginated({ dataIndex: "owner", key: "owner", ellipsis: true, - sorter: (a, b) => alphaSort(a.job.ownr_ln, b.job.ownr_ln), - sortOrder: sortcolumn === "owner" && sortorder, + // sorter: (a, b) => alphaSort(a.job.ownr_ln, b.job.ownr_ln), + // sortOrder: sortcolumn === "owner" && sortorder, render: (text, record) => { return record.job?.owner ? ( diff --git a/client/src/pages/bills/bills.page.component.jsx b/client/src/pages/bills/bills.page.component.jsx index 8647a6ded..d95558a32 100644 --- a/client/src/pages/bills/bills.page.component.jsx +++ b/client/src/pages/bills/bills.page.component.jsx @@ -45,20 +45,20 @@ export function BillsListPage({ title: t("bills.fields.vendorname"), dataIndex: "vendorname", key: "vendorname", - sortObject: (direction) => { - return { - vendor: { - name: direction - ? direction === "descend" - ? "desc" - : "asc" - : "desc", - }, - }; - }, - sorter: (a, b) => alphaSort(a.vendor.name, b.vendor.name), - sortOrder: - state.sortedInfo.columnKey === "vendorname" && state.sortedInfo.order, + // sortObject: (direction) => { + // return { + // vendor: { + // name: direction + // ? direction === "descend" + // ? "desc" + // : "asc" + // : "desc", + // }, + // }; + // }, + // sorter: (a, b) => alphaSort(a.vendor.name, b.vendor.name), + // sortOrder: + // state.sortedInfo.columnKey === "vendorname" && state.sortedInfo.order, render: (text, record) => {record.vendor.name}, }, { @@ -74,20 +74,20 @@ export function BillsListPage({ title: t("jobs.fields.ro_number"), dataIndex: "ro_number", key: "ro_number", - sortObject: (direction) => { - return { - job: { - ro_number: direction - ? direction === "descend" - ? "desc" - : "asc" - : "desc", - }, - }; - }, - sorter: (a, b) => alphaSort(a.job.ro_number, b.job.ro_number), - sortOrder: - state.sortedInfo.columnKey === "ro_number" && state.sortedInfo.order, + // sortObject: (direction) => { + // return { + // job: { + // ro_number: direction + // ? direction === "descend" + // ? "desc" + // : "asc" + // : "desc", + // }, + // }; + // }, + // sorter: (a, b) => alphaSort(a.job.ro_number, b.job.ro_number), + // sortOrder: + // state.sortedInfo.columnKey === "ro_number" && state.sortedInfo.order, render: (text, record) => record.job && ( From 08e5543536d33beead8b5fdbab8b40468c797921 Mon Sep 17 00:00:00 2001 From: swtmply Date: Fri, 5 May 2023 04:00:44 +0800 Subject: [PATCH 04/21] IO-1722 adjusted condition for text color --- .../production-board-kanban-card.component.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/components/production-board-kanban-card/production-board-kanban-card.component.jsx b/client/src/components/production-board-kanban-card/production-board-kanban-card.component.jsx index cb955a9c6..bab5b9851 100644 --- a/client/src/components/production-board-kanban-card/production-board-kanban-card.component.jsx +++ b/client/src/components/production-board-kanban-card/production-board-kanban-card.component.jsx @@ -86,8 +86,8 @@ export default function ProductionBoardCard( size="small" style={{ backgroundColor: cardSettings && cardSettings.cardcolor && bgColor, - - color: getContrastYIQ(bgColor), + color: + cardSettings && cardSettings.cardcolor && getContrastYIQ(bgColor), }} title={ From 6898d609fe02854e2322486743f02f19086c92e9 Mon Sep 17 00:00:00 2001 From: Allan Carr Date: Thu, 4 May 2023 15:17:37 -0700 Subject: [PATCH 05/21] IO-2261 Add Loading effect --- .../jobs-list-paginated/jobs-list-paginated.component.jsx | 8 +++++--- .../payment-list-paginated.component.jsx | 8 +++++--- client/src/pages/bills/bills.page.component.jsx | 8 +++++--- 3 files changed, 15 insertions(+), 9 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 7ce46616b..ec50e618c 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 @@ -23,6 +23,7 @@ const mapDispatchToProps = (dispatch) => ({ export function JobsList({ bodyshop, refetch, loading, jobs, total }) { const search = queryString.parse(useLocation().search); const [openSearchResults, setOpenSearchResults] = useState([]); + const [searchLoading, setSearchLoading] = useState(false); const { page, sortcolumn, sortorder } = search; const history = useHistory(); @@ -197,7 +198,6 @@ export function JobsList({ bodyshop, refetch, loading, jobs, total }) { useEffect(() => { if (search.search && search.search.trim() !== "") { - // setLoading(true); searchJobs(); } // eslint-disable-next-line react-hooks/exhaustive-deps @@ -205,6 +205,7 @@ export function JobsList({ bodyshop, refetch, loading, jobs, total }) { async function searchJobs(value) { try { + setSearchLoading(true); const searchData = await axios.post("/search", { search: value || search.search, index: "jobs", @@ -213,7 +214,7 @@ export function JobsList({ bodyshop, refetch, loading, jobs, total }) { } catch (error) { console.log("Error while fetching search results", error); } finally { - // setLoading(false); + setSearchLoading(false); } } @@ -246,13 +247,14 @@ export function JobsList({ bodyshop, refetch, loading, jobs, total }) { history.push({ search: queryString.stringify(search) }); searchJobs(value); }} + loading={loading || searchLoading} enterButton /> } >
{ if (search.search && search.search.trim() !== "") { - // setLoading(true); searchPayments(); } // eslint-disable-next-line react-hooks/exhaustive-deps @@ -193,6 +193,7 @@ export function PaymentsListPaginated({ async function searchPayments(value) { try { + setSearchLoading(true); const searchData = await axios.post("/search", { search: value || search.search, index: "payments", @@ -201,7 +202,7 @@ export function PaymentsListPaginated({ } catch (error) { console.log("Error while fetching search results", error); } finally { - // setLoading(false); + setSearchLoading(false); } } @@ -242,13 +243,14 @@ export function PaymentsListPaginated({ history.push({ search: queryString.stringify(search) }); searchPayments(value); }} + loading={loading || searchLoading} enterButton /> } >
{ if (search.search && search.search.trim() !== "") { - // setLoading(true); searchBills(); } // eslint-disable-next-line react-hooks/exhaustive-deps @@ -215,6 +215,7 @@ export function BillsListPage({ async function searchBills(value) { try { + setSearchLoading(true); const searchData = await axios.post("/search", { search: value || search.search, index: "bills", @@ -223,7 +224,7 @@ export function BillsListPage({ } catch (error) { console.log("Error while fetching search results", error); } finally { - // setLoading(false); + setSearchLoading(false); } } @@ -268,6 +269,7 @@ export function BillsListPage({ history.push({ search: queryString.stringify(search) }); searchBills(value); }} + loading={loading || searchLoading} enterButton /> @@ -276,7 +278,7 @@ export function BillsListPage({
Date: Thu, 4 May 2023 15:32:21 -0700 Subject: [PATCH 06/21] Revert "Revert "Merged in feature/IO-1722-job-size-color (pull request #746)"" This reverts commit 7dc3c006287f1be1a78a3d80732589236ceae592. --- ...ard-kanban-card-color-legend.component.jsx | 39 +++++++++++++++++++ ...production-board-kanban-card.component.jsx | 31 +++++++++++++++ ...n-board-kanban.card-settings.component.jsx | 7 ++++ .../production-board-kanban.component.jsx | 7 ++++ .../shop-info.scheduling.component.jsx | 9 +++++ client/src/translations/en_us/common.json | 7 +++- 6 files changed, 98 insertions(+), 2 deletions(-) create mode 100644 client/src/components/production-board-kanban-card/production-board-kanban-card-color-legend.component.jsx diff --git a/client/src/components/production-board-kanban-card/production-board-kanban-card-color-legend.component.jsx b/client/src/components/production-board-kanban-card/production-board-kanban-card-color-legend.component.jsx new file mode 100644 index 000000000..e9cc0f4e0 --- /dev/null +++ b/client/src/components/production-board-kanban-card/production-board-kanban-card-color-legend.component.jsx @@ -0,0 +1,39 @@ +import { Col, List, Space, Typography } from "antd"; +import React from "react"; +import { useTranslation } from "react-i18next"; + +const CardColorLegend = ({ bodyshop, cardSettings }) => { + const { t } = useTranslation(); + const data = bodyshop.ssbuckets.map((size) => ({ + label: size.label, + color: size.color?.hex ?? "white", + })); + + return ( + + {t("production.labels.legend")} + ( + + +
+
{item.label}
+
+
+ )} + /> + + ); +}; + +export default CardColorLegend; diff --git a/client/src/components/production-board-kanban-card/production-board-kanban-card.component.jsx b/client/src/components/production-board-kanban-card/production-board-kanban-card.component.jsx index 750204fb5..cb955a9c6 100644 --- a/client/src/components/production-board-kanban-card/production-board-kanban-card.component.jsx +++ b/client/src/components/production-board-kanban-card/production-board-kanban-card.component.jsx @@ -18,6 +18,28 @@ import moment from "moment"; import OwnerNameDisplay from "../owner-name-display/owner-name-display.component"; import JobPartsQueueCount from "../job-parts-queue-count/job-parts-queue-count.component"; +const cardColor = (ssbuckets, totalHrs) => { + const bucket = ssbuckets.filter( + (bucket) => + bucket.gte <= totalHrs && (!!bucket.lt ? bucket.lt > totalHrs : true) + )[0]; + + if (bucket.color) { + return bucket.color.hex; + } + + return ""; +}; + +function getContrastYIQ(hexColor) { + const r = parseInt(hexColor.substr(1, 2), 16); + const g = parseInt(hexColor.substr(3, 2), 16); + const b = parseInt(hexColor.substr(5, 2), 16); + const yiq = (r * 299 + g * 587 + b * 114) / 1000; + + return yiq >= 128 ? "black" : "white"; +} + export default function ProductionBoardCard( technician, card, @@ -54,10 +76,19 @@ export default function ProductionBoardCard( .isSame(moment(card.scheduled_completion), "day") && "production-completion-soon")); + const totalHrs = + card.labhrs.aggregate.sum.mod_lb_hrs + card.larhrs.aggregate.sum.mod_lb_hrs; + const bgColor = cardColor(bodyshop.ssbuckets, totalHrs); + return ( diff --git a/client/src/components/production-board-kanban/production-board-kanban.card-settings.component.jsx b/client/src/components/production-board-kanban/production-board-kanban.card-settings.component.jsx index 25c77e307..bc7f83494 100644 --- a/client/src/components/production-board-kanban/production-board-kanban.card-settings.component.jsx +++ b/client/src/components/production-board-kanban/production-board-kanban.card-settings.component.jsx @@ -104,6 +104,13 @@ export default function ProductionBoardKanbanCardSettings({ > + + +
} /> + + {cardSettings.cardcolor && ( + + )} + + + + + + { diff --git a/client/src/translations/en_us/common.json b/client/src/translations/en_us/common.json index f52178267..1819fadbe 100644 --- a/client/src/translations/en_us/common.json +++ b/client/src/translations/en_us/common.json @@ -508,7 +508,8 @@ "id": "ID", "label": "Label", "lt": "Less than (hrs)", - "target": "Target (count)" + "target": "Target (count)", + "color": "Job Color" }, "state": "Province/State", "state_tax_id": "Provincial/State Tax ID (PST, QST)", @@ -2385,7 +2386,9 @@ "sublets": "Sublets", "totalhours": "Total Hrs ", "touchtime": "T/T", - "viewname": "View Name" + "viewname": "View Name", + "legend": "Legend:", + "cardcolor": "Card Colors" }, "successes": { "removed": "Job removed from production." From ac72177fbb928570df7164be9e1da6a16a64cc10 Mon Sep 17 00:00:00 2001 From: Allan Carr Date: Thu, 4 May 2023 18:27:47 -0700 Subject: [PATCH 07/21] IO-2261 All Jobs, Bills, Payments Adjust Pagination settings and on clear delete search.page to reset. Adjust payments for bodyshopid as it was pointed at bill instead of payment --- .../jobs-list-paginated/jobs-list-paginated.component.jsx | 7 +++++-- .../payment-list-paginated.component.jsx | 7 +++++-- client/src/pages/bills/bills.page.component.jsx | 7 +++++-- server/opensearch/os-handler.js | 5 +---- 4 files changed, 16 insertions(+), 10 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 ec50e618c..7d332d61f 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 @@ -230,6 +230,7 @@ export function JobsList({ bodyshop, refetch, loading, jobs, total }) {