diff --git a/client/src/components/production-board-kanban/production-board-kanban.container.jsx b/client/src/components/production-board-kanban/production-board-kanban.container.jsx index 27170c90c..0de09e444 100644 --- a/client/src/components/production-board-kanban/production-board-kanban.container.jsx +++ b/client/src/components/production-board-kanban/production-board-kanban.container.jsx @@ -1,8 +1,13 @@ -import { useQuery, useSubscription } from "@apollo/client"; -import React from "react"; +import { useApolloClient, useQuery, useSubscription } from "@apollo/client"; +import _ from "lodash"; +import React, { useEffect, useState } from "react"; import { connect } from "react-redux"; import { createStructuredSelector } from "reselect"; -import { SUBSCRIPTION_JOBS_IN_PRODUCTION } from "../../graphql/jobs.queries"; +import { + QUERY_EXACT_JOB_IN_PRODUCTION, + QUERY_JOBS_IN_PRODUCTION, + SUBSCRIPTION_JOBS_IN_PRODUCTION, +} from "../../graphql/jobs.queries"; import { QUERY_KANBAN_SETTINGS } from "../../graphql/user.queries"; import { selectBodyshop, @@ -14,13 +19,47 @@ const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop, currentUser: selectCurrentUser, }); - export function ProductionBoardKanbanContainer({ bodyshop, currentUser }) { - const { loading, data } = useSubscription( - SUBSCRIPTION_JOBS_IN_PRODUCTION, - {} + const { loading, data } = useQuery(QUERY_JOBS_IN_PRODUCTION); + const client = useApolloClient(); + const [joblist, setJoblist] = useState([]); + const { data: updatedJobs } = useSubscription( + SUBSCRIPTION_JOBS_IN_PRODUCTION ); + useEffect(() => { + if (!(data && data.jobs)) return; + setJoblist( + data.jobs.map((j) => { + return { id: j.id, updated_at: j.updated_at }; + }) + ); + }, [data]); + + useEffect(() => { + if (!updatedJobs || joblist.length === 0) return; + + const jobDiff = _.differenceWith( + updatedJobs.jobs, + joblist, + (a, b) => a.id === b.id && a.updated_at === b.updated_at + ); + + jobDiff.forEach((job) => { + getUpdatedJobData(job.id); + }); + + setJoblist(updatedJobs); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [updatedJobs]); + + const getUpdatedJobData = async (jobId) => { + client.query({ + query: QUERY_EXACT_JOB_IN_PRODUCTION, + variables: { id: jobId }, + }); + }; + const { loading: associationSettingsLoading, data: associationSettings } = useQuery(QUERY_KANBAN_SETTINGS, { variables: { email: currentUser.email }, 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 d13a71d33..720b17285 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,13 +1,53 @@ -import { useSubscription } from "@apollo/client"; -import React from "react"; -import { SUBSCRIPTION_JOBS_IN_PRODUCTION } from "../../graphql/jobs.queries"; +import { useApolloClient, useQuery, useSubscription } from "@apollo/client"; +import React, { useEffect, useState } from "react"; +import { + QUERY_EXACT_JOB_IN_PRODUCTION, + QUERY_JOBS_IN_PRODUCTION, + SUBSCRIPTION_JOBS_IN_PRODUCTION, +} from "../../graphql/jobs.queries"; import ProductionListTable from "./production-list-table.component"; +import _ from "lodash"; export default function ProductionListTableContainer() { - const { loading, data } = useSubscription( - SUBSCRIPTION_JOBS_IN_PRODUCTION, - {} + const { loading, data } = useQuery(QUERY_JOBS_IN_PRODUCTION); + const client = useApolloClient(); + const [joblist, setJoblist] = useState([]); + const { data: updatedJobs } = useSubscription( + SUBSCRIPTION_JOBS_IN_PRODUCTION ); + useEffect(() => { + if (!(data && data.jobs)) return; + setJoblist( + data.jobs.map((j) => { + return { id: j.id, updated_at: j.updated_at }; + }) + ); + }, [data]); + + useEffect(() => { + if (!updatedJobs || joblist.length === 0) return; + + const jobDiff = _.differenceWith( + updatedJobs.jobs, + joblist, + (a, b) => a.id === b.id && a.updated_at === b.updated_at + ); + + jobDiff.forEach((job) => { + getUpdatedJobData(job.id); + }); + + setJoblist(updatedJobs); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [updatedJobs]); + + const getUpdatedJobData = async (jobId) => { + client.query({ + query: QUERY_EXACT_JOB_IN_PRODUCTION, + variables: { id: jobId }, + }); + }; + return ; } diff --git a/client/src/components/production-sublets-manage/production-sublets-manage.component.jsx b/client/src/components/production-sublets-manage/production-sublets-manage.component.jsx index 2fdc2619b..9a7e8e6bc 100644 --- a/client/src/components/production-sublets-manage/production-sublets-manage.component.jsx +++ b/client/src/components/production-sublets-manage/production-sublets-manage.component.jsx @@ -3,10 +3,10 @@ import { Button, List, notification, Popover } from "antd"; import React, { useMemo, useState } from "react"; import { useMutation } from "@apollo/client"; import { useTranslation } from "react-i18next"; -import { UPDATE_JOB_LINE } from "../../graphql/jobs-lines.queries"; +import { UPDATE_JOB_LINE_SUBLET } from "../../graphql/jobs-lines.queries"; export default function ProductionSubletsManageComponent({ subletJobLines }) { const { t } = useTranslation(); - const [updateJobLine] = useMutation(UPDATE_JOB_LINE); + const [updateJobLine] = useMutation(UPDATE_JOB_LINE_SUBLET); const [loading, setLoading] = useState(false); const subletCount = useMemo(() => { return { @@ -22,6 +22,8 @@ export default function ProductionSubletsManageComponent({ subletJobLines }) { const result = await updateJobLine({ variables: { + jobId: sublet.jobid, + now: new Date(), lineId: sublet.id, line: { sublet_completed: diff --git a/client/src/graphql/jobs-lines.queries.js b/client/src/graphql/jobs-lines.queries.js index d95fc4538..d4e50fd94 100644 --- a/client/src/graphql/jobs-lines.queries.js +++ b/client/src/graphql/jobs-lines.queries.js @@ -136,6 +136,27 @@ export const RECEIVE_PARTS_LINE = gql` } `; +export const UPDATE_JOB_LINE_SUBLET = gql` + mutation UPDATE_JOB_LINE_SUBLET( + $lineId: uuid! + $line: joblines_set_input! + $now: timestamptz! + $jobId: uuid! + ) { + update_jobs_by_pk(pk_columns: { id: $jobId }, _set: { updated_at: $now }) { + id + updated_at + } + update_joblines(where: { id: { _eq: $lineId } }, _set: $line) { + returning { + id + sublet_completed + sublet_ignored + } + } + } +`; + export const UPDATE_JOB_LINE = gql` mutation UPDATE_JOB_LINE($lineId: uuid!, $line: joblines_set_input!) { update_joblines(where: { id: { _eq: $lineId } }, _set: $line) { diff --git a/client/src/graphql/jobs.queries.js b/client/src/graphql/jobs.queries.js index eb228f2fe..822dadf36 100644 --- a/client/src/graphql/jobs.queries.js +++ b/client/src/graphql/jobs.queries.js @@ -105,10 +105,18 @@ export const QUERY_PARTS_QUEUE = gql` } } `; - export const SUBSCRIPTION_JOBS_IN_PRODUCTION = gql` subscription SUBSCRIPTION_JOBS_IN_PRODUCTION { jobs(where: { inproduction: { _eq: true } }) { + id + updated_at + } + } +`; + +export const QUERY_EXACT_JOB_IN_PRODUCTION = gql` + query QUERY_EXACT_JOB_IN_PRODUCTION($id: uuid!) { + jobs(where: { id: { _eq: $id } }) { id status ro_number @@ -171,6 +179,79 @@ export const SUBSCRIPTION_JOBS_IN_PRODUCTION = gql` line_desc sublet_ignored sublet_completed + jobid + } + } + } +`; + +export const QUERY_JOBS_IN_PRODUCTION = gql` + query QUERY_JOBS_IN_PRODUCTION { + jobs(where: { inproduction: { _eq: true } }) { + id + updated_at + status + ro_number + ownr_fn + ownr_ln + ownr_co_nm + v_model_yr + v_model_desc + clm_no + v_make_desc + v_color + plate_no + actual_in + scheduled_completion + scheduled_delivery + date_last_contacted + date_next_contact + ins_co_nm + clm_total + ownr_ph1 + ownr_ph2 + special_coverage_policy + owner_owing + production_vars + kanbanparent + alt_transport + employee_body + employee_refinish + employee_prep + employee_csr + labhrs: joblines_aggregate( + where: { + _and: [{ mod_lbr_ty: { _neq: "LAR" } }, { removed: { _eq: false } }] + } + ) { + aggregate { + sum { + mod_lb_hrs + } + } + } + larhrs: joblines_aggregate( + where: { + _and: [{ mod_lbr_ty: { _eq: "LAR" } }, { removed: { _eq: false } }] + } + ) { + aggregate { + sum { + mod_lb_hrs + } + } + } + subletLines: joblines( + where: { + _and: { part_type: { _in: ["PAS", "PASL"] }, removed: { _eq: false } } + } + order_by: { line_no: asc } + ) { + id + line_desc + sublet_ignored + sublet_completed + jobid } } } @@ -875,6 +956,7 @@ export const UPDATE_JOB = gql` update_jobs(where: { id: { _eq: $jobId } }, _set: $job) { returning { id + date_exported status alt_transport @@ -1589,46 +1671,6 @@ export const QUERY_ALL_JOB_FIELDS = gql` } } `; -export const QUERY_JOBS_IN_PRODUCTION = gql` - query QUERY_JOBS_IN_PRODUCTION { - jobs( - where: { inproduction: { _eq: true } } - order_by: { scheduled_completion: asc } - ) { - id - ro_number - ownr_co_nm - ownr_fn - ownr_ln - v_model_yr - v_make_desc - v_model_desc - scheduled_completion - labhrs: joblines_aggregate( - where: { - _and: [{ mod_lbr_ty: { _neq: "LAR" } }, { removed: { _eq: false } }] - } - ) { - aggregate { - sum { - mod_lb_hrs - } - } - } - larhrs: joblines_aggregate( - where: { - _and: [{ mod_lbr_ty: { _eq: "LAR" } }, { removed: { _eq: false } }] - } - ) { - aggregate { - sum { - mod_lb_hrs - } - } - } - } - } -`; export const QUERY_ALL_JOBS_PAGINATED_STATUS_FILTERED = gql` query QUERY_ALL_JOBS_PAGINATED_STATUS_FILTERED(