From a297bba19306eacb6ae28062f6ab6fb4ce610385 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Fri, 2 Aug 2024 11:29:31 -0400 Subject: [PATCH] - Check Point Signed-off-by: Dave Richer --- .../production-board-kanban.component.jsx | 6 +- .../production-board-kanban.container.jsx | 2 + ...uction-board-kanban.settings.component.jsx | 254 ------------------ .../production-board-kanban.statistics.jsx | 16 +- .../production-board-kanban.utils.js | 32 ++- .../settings/InformationSettings.jsx | 35 +++ .../settings/LayoutSettings.jsx | 71 +++++ .../settings/StatisticsSettings.jsx | 57 ++++ .../{ => settings}/defaultKanbanSettings.js | 0 ...uction-board-kanban.settings.component.jsx | 125 +++++++++ 10 files changed, 316 insertions(+), 282 deletions(-) delete mode 100644 client/src/components/production-board-kanban/production-board-kanban.settings.component.jsx create mode 100644 client/src/components/production-board-kanban/settings/InformationSettings.jsx create mode 100644 client/src/components/production-board-kanban/settings/LayoutSettings.jsx create mode 100644 client/src/components/production-board-kanban/settings/StatisticsSettings.jsx rename client/src/components/production-board-kanban/{ => settings}/defaultKanbanSettings.js (100%) create mode 100644 client/src/components/production-board-kanban/settings/production-board-kanban.settings.component.jsx diff --git a/client/src/components/production-board-kanban/production-board-kanban.component.jsx b/client/src/components/production-board-kanban/production-board-kanban.component.jsx index 2406eefa0..dc8a6a929 100644 --- a/client/src/components/production-board-kanban/production-board-kanban.component.jsx +++ b/client/src/components/production-board-kanban/production-board-kanban.component.jsx @@ -18,10 +18,10 @@ import ProductionListDetailComponent from "../production-list-detail/production- import CardColorLegend from "../production-board-kanban-card/production-board-kanban-card-color-legend.component"; import "./production-board-kanban.styles.scss"; import { createBoardData } from "./production-board-kanban.utils.js"; -import ProductionBoardKanbanSettings from "./production-board-kanban.settings.component.jsx"; +import ProductionBoardKanbanSettings from "./settings/production-board-kanban.settings.component.jsx"; import cloneDeep from "lodash/cloneDeep"; import isEqual from "lodash/isEqual"; -import { defaultKanbanSettings } from "./defaultKanbanSettings.js"; +import { defaultKanbanSettings } from "./settings/defaultKanbanSettings.js"; import NoteUpsertModal from "../../components/note-upsert-modal/note-upsert-modal.container"; const mapStateToProps = createStructuredSelector({ @@ -59,7 +59,7 @@ function ProductionBoardKanbanComponent({ data, bodyshop, refetch, insertAuditTr useEffect(() => { setIsMoving(true); - const newBoardData = createBoardData(statuses, data, filter); + const newBoardData = createBoardData({ statuses, data, filter }); newBoardData.lanes = newBoardData.lanes.map((lane) => ({ ...lane, 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 d4834cc94..a0b8cc984 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 @@ -37,6 +37,8 @@ function ProductionBoardKanbanContainer({ bodyshop, currentUser }) { onError: (error) => console.error(`Error fetching Kanban settings: ${error.message}`) }); + // 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}`)); diff --git a/client/src/components/production-board-kanban/production-board-kanban.settings.component.jsx b/client/src/components/production-board-kanban/production-board-kanban.settings.component.jsx deleted file mode 100644 index d5cadf5f9..000000000 --- a/client/src/components/production-board-kanban/production-board-kanban.settings.component.jsx +++ /dev/null @@ -1,254 +0,0 @@ -import { useMutation } from "@apollo/client"; -import { Button, Card, Checkbox, Col, Form, notification, Popover, Radio, Row, Tabs } from "antd"; -import React, { useEffect, useState } from "react"; -import { useTranslation } from "react-i18next"; -import { UPDATE_KANBAN_SETTINGS } from "../../graphql/user.queries"; -import { DragDropContext, Draggable, Droppable } from "./trello-board/dnd/lib"; -import { defaultKanbanSettings, statisticsItems } from "./defaultKanbanSettings.js"; - -const LayoutSettings = ({ t }) => ( - - - {[ - { - name: "orientation", - label: t("production.labels.orientation"), - options: [ - { value: true, label: t("production.labels.vertical") }, - { value: false, label: t("production.labels.horizontal") } - ] - }, - { - name: "cardSize", - label: t("production.labels.card_size"), - options: [ - { value: "small", label: t("production.options.small") }, - { value: "medium", label: t("production.options.medium") }, - { value: "large", label: t("production.options.large") } - ] - }, - { - name: "compact", - label: t("production.labels.compact"), - options: [ - { value: true, label: t("production.labels.tall") }, - { value: false, label: t("production.labels.wide") } - ] - }, - { - name: "cardcolor", - label: t("production.labels.cardcolor"), - options: [ - { value: true, label: t("production.labels.on") }, - { value: false, label: t("production.labels.off") } - ] - }, - { - name: "kiosk", - label: t("production.labels.kiosk_mode"), - options: [ - { value: true, label: t("production.labels.on") }, - { value: false, label: t("production.labels.off") } - ] - } - ].map(({ name, label, options }) => ( - - - - {options.map((option) => ( - - {option.label} - - ))} - - - - ))} - - -); - -const InformationSettings = ({ t }) => ( - - - {[ - "model_info", - "ownr_nm", - "clm_no", - "ins_co_nm", - "employeeassignments", - "actual_in", - "scheduled_completion", - "ats", - "production_note", - "sublets", - "partsstatus" - ].map((item) => ( - - - {t(`production.labels.${item}`)} - - - ))} - - -); - -const StatisticsSettings = ({ t, statisticsOrder, setStatisticsOrder, setHasChanges }) => { - const onDragEnd = (result) => { - if (!result.destination) return; - const newOrder = Array.from(statisticsOrder); - const [movedItem] = newOrder.splice(result.source.index, 1); - newOrder.splice(result.destination.index, 0, movedItem); - setStatisticsOrder(newOrder); - setHasChanges(true); - }; - - return ( - - - {(provided) => ( -
- {statisticsOrder.map((itemId, index) => { - const item = statisticsItems.find((stat) => stat.id === itemId); - return ( - - {(provided) => ( -
- - - {t(`production.settings.statistics.${item.label}`)} - - -
- )} -
- ); - })} - {provided.placeholder} -
- )} -
-
- ); -}; - -export default function ProductionBoardKanbanSettings({ associationSettings, parentLoading }) { - const [form] = Form.useForm(); - const [open, setOpen] = useState(false); - const [loading, setLoading] = useState(false); - const [hasChanges, setHasChanges] = useState(false); - const [statisticsOrder, setStatisticsOrder] = useState(defaultKanbanSettings.statisticsOrder); - - const [updateKbSettings] = useMutation(UPDATE_KANBAN_SETTINGS); - const { t } = useTranslation(); - - useEffect(() => { - if (associationSettings?.kanban_settings) { - form.setFieldsValue(associationSettings.kanban_settings); - if (associationSettings.kanban_settings.statisticsOrder) { - setStatisticsOrder(associationSettings.kanban_settings.statisticsOrder); - } - } - }, [form, associationSettings]); - - const handleFinish = async (values) => { - setLoading(true); - parentLoading(true); - - const result = await updateKbSettings({ - variables: { - id: associationSettings?.id, - ks: { ...associationSettings.kanban_settings, ...values, statisticsOrder } - } - }); - - if (result.errors) { - notification.open({ - type: "error", - message: t("production.errors.settings", { - error: JSON.stringify(result.errors) - }) - }); - } - - setOpen(false); - setLoading(false); - parentLoading(false); - setHasChanges(false); - }; - - const handleValuesChange = () => setHasChanges(true); - - const handleRestoreDefaults = () => { - form.setFieldsValue({ - ...defaultKanbanSettings, - statisticsOrder: defaultKanbanSettings.statisticsOrder - }); - setStatisticsOrder(defaultKanbanSettings.statisticsOrder); - setHasChanges(true); - }; - - const overlay = ( - -
- - }, - { - key: "2", - label: t("production.settings.information"), - children: - }, - { - key: "3", - label: t("production.settings.statistics_title"), - children: ( - - ) - } - ]} - /> - - - - - - - - - - - - -
- ); - - return ( - - - - ); -} diff --git a/client/src/components/production-board-kanban/production-board-kanban.statistics.jsx b/client/src/components/production-board-kanban/production-board-kanban.statistics.jsx index 34baa8f8c..97242656d 100644 --- a/client/src/components/production-board-kanban/production-board-kanban.statistics.jsx +++ b/client/src/components/production-board-kanban/production-board-kanban.statistics.jsx @@ -2,7 +2,7 @@ import React, { useMemo } from "react"; import { Card, Statistic } from "antd"; import { useTranslation } from "react-i18next"; import PropTypes from "prop-types"; -import { statisticsItems } from "./defaultKanbanSettings.js"; +import { statisticsItems } from "./settings/defaultKanbanSettings.js"; export const StatisticType = { HOURS: "hours", @@ -152,15 +152,15 @@ const ProductionStatistics = ({ data, cardSettings, reducerData }) => { ); const sortedStatistics = useMemo(() => { - const sorted = []; - cardSettings.statisticsOrder.forEach((orderId) => { - const value = statistics.find((stat) => stat.id === orderId); - if (value.value !== null) { + const statisticsMap = new Map(statistics.map((stat) => [stat.id, stat])); + + return cardSettings.statisticsOrder.reduce((sorted, orderId) => { + const value = statisticsMap.get(orderId); + if (value && value.value !== null) { sorted.push(value); } - }); - - return sorted; + return sorted; + }, []); }, [statistics, cardSettings.statisticsOrder]); return ( diff --git a/client/src/components/production-board-kanban/production-board-kanban.utils.js b/client/src/components/production-board-kanban/production-board-kanban.utils.js index affe7102e..10eec0771 100644 --- a/client/src/components/production-board-kanban/production-board-kanban.utils.js +++ b/client/src/components/production-board-kanban/production-board-kanban.utils.js @@ -28,7 +28,7 @@ const sortByParentId = (arr) => { }; // Function to create board data based on statuses and jobs, with optional filtering -export const createBoardData = (statuses, Jobs, filter) => { +export const createBoardData = ({ statuses, data, filter }) => { const { search, employeeId } = filter; const lanes = statuses.map((status) => ({ @@ -38,7 +38,7 @@ export const createBoardData = (statuses, Jobs, filter) => { })); const filteredJobs = - (search === "" || !search) && !employeeId ? Jobs : Jobs.filter((job) => checkFilter(search, employeeId, job)); + (search === "" || !search) && !employeeId ? data : data.filter((job) => checkFilter(search, employeeId, job)); const DataGroupedByStatus = groupBy(filteredJobs, "status"); @@ -67,26 +67,24 @@ export const createBoardData = (statuses, Jobs, filter) => { // Function to check if a job matches the search and/or employeeId filter const checkFilter = (search, employeeId, job) => { - const lowerSearch = search?.toLowerCase() || ""; + const lowerSearch = search?.toLowerCase() ?? ""; const matchesSearch = lowerSearch && - ((job.ro_number || "").toLowerCase().includes(lowerSearch) || - (job.ownr_fn || "").toLowerCase().includes(lowerSearch) || - (job.ownr_co_nm || "").toLowerCase().includes(lowerSearch) || - (job.ownr_ln || "").toLowerCase().includes(lowerSearch) || - (job.status || "").toLowerCase().includes(lowerSearch) || - (job.v_make_desc || "").toLowerCase().includes(lowerSearch) || - (job.v_model_desc || "").toLowerCase().includes(lowerSearch) || - (job.clm_no || "").toLowerCase().includes(lowerSearch) || - (job.plate_no || "").toLowerCase().includes(lowerSearch)); + [ + job.ro_number, + job.ownr_fn, + job.ownr_co_nm, + job.ownr_ln, + job.status, + job.v_make_desc, + job.v_model_desc, + job.clm_no, + job.plate_no + ].some((field) => field?.toLowerCase().includes(lowerSearch)); const matchesEmployeeId = - employeeId && - (job.employee_body === employeeId || - job.employee_prep === employeeId || - job.employee_csr === employeeId || - job.employee_refinish === employeeId); + employeeId && [job.employee_body, job.employee_prep, job.employee_csr, job.employee_refinish].includes(employeeId); return matchesSearch || matchesEmployeeId; }; diff --git a/client/src/components/production-board-kanban/settings/InformationSettings.jsx b/client/src/components/production-board-kanban/settings/InformationSettings.jsx new file mode 100644 index 000000000..1657d070d --- /dev/null +++ b/client/src/components/production-board-kanban/settings/InformationSettings.jsx @@ -0,0 +1,35 @@ +import { Card, Checkbox, Col, Form, Row } from "antd"; +import React from "react"; +import PropTypes from "prop-types"; + +const InformationSettings = ({ t }) => ( + + + {[ + "model_info", + "ownr_nm", + "clm_no", + "ins_co_nm", + "employeeassignments", + "actual_in", + "scheduled_completion", + "ats", + "production_note", + "sublets", + "partsstatus" + ].map((item) => ( + + + {t(`production.labels.${item}`)} + + + ))} + + +); + +InformationSettings.propTypes = { + t: PropTypes.func.isRequired +}; + +export default InformationSettings; diff --git a/client/src/components/production-board-kanban/settings/LayoutSettings.jsx b/client/src/components/production-board-kanban/settings/LayoutSettings.jsx new file mode 100644 index 000000000..a4a050145 --- /dev/null +++ b/client/src/components/production-board-kanban/settings/LayoutSettings.jsx @@ -0,0 +1,71 @@ +import { Card, Col, Form, Radio, Row } from "antd"; +import React from "react"; +import PropTypes from "prop-types"; + +const LayoutSettings = ({ t }) => ( + + + {[ + { + name: "orientation", + label: t("production.labels.orientation"), + options: [ + { value: true, label: t("production.labels.vertical") }, + { value: false, label: t("production.labels.horizontal") } + ] + }, + { + name: "cardSize", + label: t("production.labels.card_size"), + options: [ + { value: "small", label: t("production.options.small") }, + { value: "medium", label: t("production.options.medium") }, + { value: "large", label: t("production.options.large") } + ] + }, + { + name: "compact", + label: t("production.labels.compact"), + options: [ + { value: true, label: t("production.labels.tall") }, + { value: false, label: t("production.labels.wide") } + ] + }, + { + name: "cardcolor", + label: t("production.labels.cardcolor"), + options: [ + { value: true, label: t("production.labels.on") }, + { value: false, label: t("production.labels.off") } + ] + }, + { + name: "kiosk", + label: t("production.labels.kiosk_mode"), + options: [ + { value: true, label: t("production.labels.on") }, + { value: false, label: t("production.labels.off") } + ] + } + ].map(({ name, label, options }) => ( + + + + {options.map((option) => ( + + {option.label} + + ))} + + + + ))} + + +); + +LayoutSettings.propTypes = { + t: PropTypes.func.isRequired +}; + +export default LayoutSettings; diff --git a/client/src/components/production-board-kanban/settings/StatisticsSettings.jsx b/client/src/components/production-board-kanban/settings/StatisticsSettings.jsx new file mode 100644 index 000000000..a8326da41 --- /dev/null +++ b/client/src/components/production-board-kanban/settings/StatisticsSettings.jsx @@ -0,0 +1,57 @@ +import { DragDropContext, Draggable, Droppable } from "../trello-board/dnd/lib/index.js"; +import { statisticsItems } from "./defaultKanbanSettings.js"; +import { Card, Checkbox, Form } from "antd"; +import React from "react"; +import PropTypes from "prop-types"; + +const StatisticsSettings = ({ t, statisticsOrder, setStatisticsOrder, setHasChanges }) => { + const onDragEnd = (result) => { + if (!result.destination) return; + const newOrder = Array.from(statisticsOrder); + const [movedItem] = newOrder.splice(result.source.index, 1); + newOrder.splice(result.destination.index, 0, movedItem); + setStatisticsOrder(newOrder); + setHasChanges(true); + }; + + return ( + + + {(provided) => ( +
+ {statisticsOrder.map((itemId, index) => { + const item = statisticsItems.find((stat) => stat.id === itemId); + return ( + + {(provided) => ( +
+ + + {t(`production.settings.statistics.${item.label}`)} + + +
+ )} +
+ ); + })} + {provided.placeholder} +
+ )} +
+
+ ); +}; + +StatisticsSettings.propTypes = { + t: PropTypes.func.isRequired, + statisticsOrder: PropTypes.arrayOf(PropTypes.number).isRequired, + setStatisticsOrder: PropTypes.func.isRequired, + setHasChanges: PropTypes.func.isRequired +}; + +export default StatisticsSettings; diff --git a/client/src/components/production-board-kanban/defaultKanbanSettings.js b/client/src/components/production-board-kanban/settings/defaultKanbanSettings.js similarity index 100% rename from client/src/components/production-board-kanban/defaultKanbanSettings.js rename to client/src/components/production-board-kanban/settings/defaultKanbanSettings.js diff --git a/client/src/components/production-board-kanban/settings/production-board-kanban.settings.component.jsx b/client/src/components/production-board-kanban/settings/production-board-kanban.settings.component.jsx new file mode 100644 index 000000000..fd69b3638 --- /dev/null +++ b/client/src/components/production-board-kanban/settings/production-board-kanban.settings.component.jsx @@ -0,0 +1,125 @@ +import { useMutation } from "@apollo/client"; +import { Button, Card, Col, Form, notification, Popover, Row, Tabs } from "antd"; +import React, { useEffect, useState } from "react"; +import { useTranslation } from "react-i18next"; +import { UPDATE_KANBAN_SETTINGS } from "../../../graphql/user.queries.js"; +import { defaultKanbanSettings } from "./defaultKanbanSettings.js"; +import LayoutSettings from "./LayoutSettings.jsx"; +import InformationSettings from "./InformationSettings.jsx"; +import StatisticsSettings from "./StatisticsSettings.jsx"; + +export default function ProductionBoardKanbanSettings({ associationSettings, parentLoading }) { + const [form] = Form.useForm(); + const [open, setOpen] = useState(false); + const [loading, setLoading] = useState(false); + const [hasChanges, setHasChanges] = useState(false); + const [statisticsOrder, setStatisticsOrder] = useState(defaultKanbanSettings.statisticsOrder); + + const [updateKbSettings] = useMutation(UPDATE_KANBAN_SETTINGS); + const { t } = useTranslation(); + + useEffect(() => { + if (associationSettings?.kanban_settings) { + form.setFieldsValue(associationSettings.kanban_settings); + if (associationSettings.kanban_settings.statisticsOrder) { + setStatisticsOrder(associationSettings.kanban_settings.statisticsOrder); + } + } + }, [form, associationSettings]); + + const handleFinish = async (values) => { + setLoading(true); + parentLoading(true); + + const result = await updateKbSettings({ + variables: { + id: associationSettings?.id, + ks: { ...associationSettings.kanban_settings, ...values, statisticsOrder } + } + }); + + if (result.errors) { + notification.open({ + type: "error", + message: t("production.errors.settings", { + error: JSON.stringify(result.errors) + }) + }); + } + + setOpen(false); + setLoading(false); + parentLoading(false); + setHasChanges(false); + }; + + const handleValuesChange = () => setHasChanges(true); + + const handleRestoreDefaults = () => { + form.setFieldsValue({ + ...defaultKanbanSettings, + statisticsOrder: defaultKanbanSettings.statisticsOrder + }); + setStatisticsOrder(defaultKanbanSettings.statisticsOrder); + setHasChanges(true); + }; + + const overlay = ( + +
+ + }, + { + key: "2", + label: t("production.settings.information"), + children: + }, + { + key: "3", + label: t("production.settings.statistics_title"), + children: ( + + ) + } + ]} + /> + + + + + + + + + + + + +
+ ); + + return ( + + + + ); +}