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 a0b8cc984..45bfb353c 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,12 @@ -import React, { useEffect, useMemo } from "react"; +import React, { useEffect, useMemo, useRef } from "react"; import { useQuery, useSubscription } from "@apollo/client"; import { connect } from "react-redux"; import { createStructuredSelector } from "reselect"; -import { QUERY_JOBS_IN_PRODUCTION, SUBSCRIPTION_JOBS_IN_PRODUCTION } from "../../graphql/jobs.queries"; +import { + QUERY_JOBS_IN_PRODUCTION, + SUBSCRIPTION_JOBS_IN_PRODUCTION, + SUBSCRIPTION_JOBS_IN_PRODUCTION_VIEW +} from "../../graphql/jobs.queries"; import { QUERY_KANBAN_SETTINGS } from "../../graphql/user.queries"; import { selectBodyshop, selectCurrentUser } from "../../redux/user/user.selectors"; import ProductionBoardKanbanComponent from "./production-board-kanban.component"; @@ -12,7 +16,9 @@ const mapStateToProps = createStructuredSelector({ currentUser: selectCurrentUser }); -function ProductionBoardKanbanContainer({ bodyshop, currentUser }) { +function ProductionBoardKanbanContainer({ bodyshop, currentUser, subscriptionType = "direct" }) { + const fired = useRef(false); // useRef to keep track of whether the subscription fired + const combinedStatuses = useMemo( () => [ ...bodyshop.md_ro_statuses.production_statuses, @@ -28,9 +34,12 @@ function ProductionBoardKanbanContainer({ bodyshop, currentUser }) { onError: (error) => console.error(`Error fetching jobs in production: ${error.message}`) }); - const { data: updatedJobs } = useSubscription(SUBSCRIPTION_JOBS_IN_PRODUCTION, { - onError: (error) => console.error(`Error subscribing to jobs in production: ${error.message}`) - }); + const { data: updatedJobs } = useSubscription( + subscriptionType === "view" ? SUBSCRIPTION_JOBS_IN_PRODUCTION_VIEW : SUBSCRIPTION_JOBS_IN_PRODUCTION, + { + onError: (error) => console.error(`Error subscribing to jobs in production: ${error.message}`) + } + ); const { loading: associationSettingsLoading, data: associationSettings } = useQuery(QUERY_KANBAN_SETTINGS, { variables: { email: currentUser.email }, @@ -40,10 +49,15 @@ function ProductionBoardKanbanContainer({ bodyshop, currentUser }) { // const currentReducerData = useSelector((state) => (state.trello.lanes ? state.trello : {})); useEffect(() => { - if (updatedJobs && data) { - refetch().catch((err) => console.error(`Error re-fetching jobs in production: ${err.message}`)); + if (!updatedJobs) { + return; } - }, [updatedJobs, data, refetch]); + if (!fired.current) { + fired.current = true; + return; + } + refetch().catch((err) => console.error(`Error re-fetching jobs in production: ${err.message}`)); + }, [updatedJobs, refetch]); const filteredAssociationSettings = useMemo(() => { return associationSettings?.associations[0] || null; 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 29ddf015a..9f564bde7 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 @@ -4,12 +4,13 @@ import { QUERY_EXACT_JOB_IN_PRODUCTION, QUERY_EXACT_JOBS_IN_PRODUCTION, QUERY_JOBS_IN_PRODUCTION, - SUBSCRIPTION_JOBS_IN_PRODUCTION + SUBSCRIPTION_JOBS_IN_PRODUCTION, + SUBSCRIPTION_JOBS_IN_PRODUCTION_VIEW } from "../../graphql/jobs.queries"; import ProductionListTable from "./production-list-table.component"; import _ from "lodash"; -export default function ProductionListTableContainer() { +export default function ProductionListTableContainer({ subscriptionType = "direct" }) { const { refetch, loading, data } = useQuery(QUERY_JOBS_IN_PRODUCTION, { pollInterval: 3600000, fetchPolicy: "network-only", @@ -17,7 +18,9 @@ export default function ProductionListTableContainer() { }); const client = useApolloClient(); const [joblist, setJoblist] = useState([]); - const { data: updatedJobs } = useSubscription(SUBSCRIPTION_JOBS_IN_PRODUCTION); + const { data: updatedJobs } = useSubscription( + subscriptionType === "view" ? SUBSCRIPTION_JOBS_IN_PRODUCTION_VIEW : SUBSCRIPTION_JOBS_IN_PRODUCTION + ); useEffect(() => { if (!(data && data.jobs)) return; diff --git a/client/src/graphql/jobs.queries.js b/client/src/graphql/jobs.queries.js index 90169eccc..a71d08d10 100644 --- a/client/src/graphql/jobs.queries.js +++ b/client/src/graphql/jobs.queries.js @@ -2461,6 +2461,14 @@ export const SUBSCRIPTION_JOBS_IN_PRODUCTION = gql` } } `; +export const SUBSCRIPTION_JOBS_IN_PRODUCTION_VIEW = gql` + subscription SUBSCRIPTION_JOBS_IN_PRODUCTION_VIEW { + jobs: jobs_inproduction { + id + updated_at + } + } +`; export const QUERY_JOBS_IN_PRODUCTION = gql` query QUERY_JOBS_IN_PRODUCTION { diff --git a/client/src/pages/production-board/production-board.component.jsx b/client/src/pages/production-board/production-board.component.jsx index 9b69da414..e5dfe7dff 100644 --- a/client/src/pages/production-board/production-board.component.jsx +++ b/client/src/pages/production-board/production-board.component.jsx @@ -1,6 +1,26 @@ import React from "react"; import ProductionBoardKanbanContainer from "../../components/production-board-kanban/production-board-kanban.container"; +import { connect } from "react-redux"; +import { createStructuredSelector } from "reselect"; +import { selectBodyshop } from "../../redux/user/user.selectors"; +import { useSplitTreatments } from "@splitsoftware/splitio-react"; +const mapStateToProps = createStructuredSelector({ + //currentUser: selectCurrentUser + bodyshop: selectBodyshop +}); +const mapDispatchToProps = (dispatch) => ({ + //setUserLanguage: language => dispatch(setUserLanguage(language)) +}); +export default connect(mapStateToProps, mapDispatchToProps)(ProductionBoardComponent); -export default function ProductionBoardComponent() { - return ; +export function ProductionBoardComponent({ bodyshop }) { + const { + treatments: { Production_Use_View } + } = useSplitTreatments({ + attributes: {}, + names: ["Production_Use_View"], + splitKey: bodyshop && bodyshop.imexshopid + }); + + return ; } diff --git a/client/src/pages/production-list/production-list.component.jsx b/client/src/pages/production-list/production-list.component.jsx index 01dd29d51..177108f6d 100644 --- a/client/src/pages/production-list/production-list.component.jsx +++ b/client/src/pages/production-list/production-list.component.jsx @@ -2,11 +2,31 @@ import React from "react"; import NoteUpsertModal from "../../components/note-upsert-modal/note-upsert-modal.container"; import ProductionListTable from "../../components/production-list-table/production-list-table.container"; -export default function ProductionListComponent() { +import { connect } from "react-redux"; +import { createStructuredSelector } from "reselect"; +import { selectBodyshop } from "../../redux/user/user.selectors"; +import { useSplitTreatments } from "@splitsoftware/splitio-react"; +const mapStateToProps = createStructuredSelector({ + bodyshop: selectBodyshop +}); +const mapDispatchToProps = (dispatch) => ({ + //setUserLanguage: language => dispatch(setUserLanguage(language)) +}); +export default connect(mapStateToProps, mapDispatchToProps)(ProductionListComponent); + +export function ProductionListComponent({ bodyshop }) { + const { + treatments: { Production_Use_View } + } = useSplitTreatments({ + attributes: {}, + names: ["Production_Use_View"], + splitKey: bodyshop && bodyshop.imexshopid + }); + return ( <> - + ); } diff --git a/hasura/metadata/tables.yaml b/hasura/metadata/tables.yaml index e5e086300..70be46ad0 100644 --- a/hasura/metadata/tables.yaml +++ b/hasura/metadata/tables.yaml @@ -4359,6 +4359,35 @@ template_engine: Kriti url: '{{$base_url}}/opensearch' version: 2 +- table: + name: jobs_inproduction + schema: public + object_relationships: + - name: bodyshop + using: + manual_configuration: + column_mapping: + shopid: id + insertion_order: null + remote_table: + name: bodyshops + schema: public + select_permissions: + - role: user + permission: + columns: + - id + - shopid + - updated_at + filter: + bodyshop: + associations: + _and: + - user: + authid: + _eq: X-Hasura-User-Id + - active: + _eq: true - table: name: masterdata schema: public diff --git a/hasura/migrations/1726773072213_run_sql_migration/down.sql b/hasura/migrations/1726773072213_run_sql_migration/down.sql new file mode 100644 index 000000000..4f5681185 --- /dev/null +++ b/hasura/migrations/1726773072213_run_sql_migration/down.sql @@ -0,0 +1,11 @@ +-- Could not auto-generate a down migration. +-- Please write an appropriate down migration for the SQL below: +-- CREATE +-- OR REPLACE VIEW "public"."jobs_inproduction" AS +-- SELECT +-- j.id, +-- j.updated_at +-- FROM +-- jobs j +-- WHERE +-- j.inproduction=true; diff --git a/hasura/migrations/1726773072213_run_sql_migration/up.sql b/hasura/migrations/1726773072213_run_sql_migration/up.sql new file mode 100644 index 000000000..317afef83 --- /dev/null +++ b/hasura/migrations/1726773072213_run_sql_migration/up.sql @@ -0,0 +1,9 @@ +CREATE +OR REPLACE VIEW "public"."jobs_inproduction" AS +SELECT + j.id, + j.updated_at +FROM + jobs j +WHERE +j.inproduction=true; diff --git a/hasura/migrations/1726773316245_run_sql_migration/down.sql b/hasura/migrations/1726773316245_run_sql_migration/down.sql new file mode 100644 index 000000000..153bb816b --- /dev/null +++ b/hasura/migrations/1726773316245_run_sql_migration/down.sql @@ -0,0 +1,8 @@ +-- Could not auto-generate a down migration. +-- Please write an appropriate down migration for the SQL below: +-- CREATE OR REPLACE VIEW "public"."jobs_inproduction" AS +-- SELECT j.id, +-- j.updated_at, +-- j.shopid +-- FROM jobs j +-- WHERE (j.inproduction = true); diff --git a/hasura/migrations/1726773316245_run_sql_migration/up.sql b/hasura/migrations/1726773316245_run_sql_migration/up.sql new file mode 100644 index 000000000..8bc73f558 --- /dev/null +++ b/hasura/migrations/1726773316245_run_sql_migration/up.sql @@ -0,0 +1,6 @@ +CREATE OR REPLACE VIEW "public"."jobs_inproduction" AS + SELECT j.id, + j.updated_at, + j.shopid + FROM jobs j + WHERE (j.inproduction = true); diff --git a/hasura/migrations/1726773326353_run_sql_migration/down.sql b/hasura/migrations/1726773326353_run_sql_migration/down.sql new file mode 100644 index 000000000..153bb816b --- /dev/null +++ b/hasura/migrations/1726773326353_run_sql_migration/down.sql @@ -0,0 +1,8 @@ +-- Could not auto-generate a down migration. +-- Please write an appropriate down migration for the SQL below: +-- CREATE OR REPLACE VIEW "public"."jobs_inproduction" AS +-- SELECT j.id, +-- j.updated_at, +-- j.shopid +-- FROM jobs j +-- WHERE (j.inproduction = true); diff --git a/hasura/migrations/1726773326353_run_sql_migration/up.sql b/hasura/migrations/1726773326353_run_sql_migration/up.sql new file mode 100644 index 000000000..8bc73f558 --- /dev/null +++ b/hasura/migrations/1726773326353_run_sql_migration/up.sql @@ -0,0 +1,6 @@ +CREATE OR REPLACE VIEW "public"."jobs_inproduction" AS + SELECT j.id, + j.updated_at, + j.shopid + FROM jobs j + WHERE (j.inproduction = true); diff --git a/hasura/migrations/1726775434726_run_sql_migration/down.sql b/hasura/migrations/1726775434726_run_sql_migration/down.sql new file mode 100644 index 000000000..16ca01c42 --- /dev/null +++ b/hasura/migrations/1726775434726_run_sql_migration/down.sql @@ -0,0 +1,3 @@ +-- Could not auto-generate a down migration. +-- Please write an appropriate down migration for the SQL below: +-- CREATE INDEX idx_jobs_inproduction_true_cast ON jobs(inproduction) WHERE inproduction = ('true') :: boolean; diff --git a/hasura/migrations/1726775434726_run_sql_migration/up.sql b/hasura/migrations/1726775434726_run_sql_migration/up.sql new file mode 100644 index 000000000..a6f352908 --- /dev/null +++ b/hasura/migrations/1726775434726_run_sql_migration/up.sql @@ -0,0 +1 @@ +CREATE INDEX idx_jobs_inproduction_true_cast ON jobs(inproduction) WHERE inproduction = ('true') :: boolean; diff --git a/hasura/migrations/1726775487038_drop_index_idx_jobs_inproduction_true_cast/down.sql b/hasura/migrations/1726775487038_drop_index_idx_jobs_inproduction_true_cast/down.sql new file mode 100644 index 000000000..a5f6e49ae --- /dev/null +++ b/hasura/migrations/1726775487038_drop_index_idx_jobs_inproduction_true_cast/down.sql @@ -0,0 +1,2 @@ +CREATE INDEX "idx_jobs_inproduction_true_cast" on + "public"."jobs" using btree ("inproduction"); diff --git a/hasura/migrations/1726775487038_drop_index_idx_jobs_inproduction_true_cast/up.sql b/hasura/migrations/1726775487038_drop_index_idx_jobs_inproduction_true_cast/up.sql new file mode 100644 index 000000000..d0163192a --- /dev/null +++ b/hasura/migrations/1726775487038_drop_index_idx_jobs_inproduction_true_cast/up.sql @@ -0,0 +1 @@ +DROP INDEX IF EXISTS "public"."idx_jobs_inproduction_true_cast";